2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internals.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internals.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
46 #include <mono/utils/checked-build.h>
50 gboolean mono_print_vtable = FALSE;
51 gboolean mono_align_small_structs = FALSE;
54 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
55 guint32 classes_size, class_ext_size;
57 /* Low level lock which protects data structures in this module */
58 static mono_mutex_t classes_mutex;
60 /* Function supplied by the runtime to find classes by name using information from the AOT file */
61 static MonoGetClassFromName get_class_from_name = NULL;
63 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
64 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
65 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
66 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
67 static int generic_array_methods (MonoClass *klass);
68 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
70 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
71 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
72 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
73 static guint32 mono_field_resolve_flags (MonoClassField *field);
74 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
75 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
78 We use gclass recording to allow recursive system f types to be referenced by a parent.
80 Given the following type hierarchy:
82 class TextBox : TextBoxBase<TextBox> {}
83 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
84 class TextInput<T> : Input<T> where T: TextInput<T> {}
87 The runtime tries to load TextBoxBase<>.
88 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
89 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
90 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
92 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
93 at this point, iow, both are registered in the type map and both and a NULL parent. This means
94 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
96 To fix that what we do is to record all generic instantes created while resolving the parent of
97 any generic type definition and, after resolved, correct the parent field if needed.
100 static int record_gclass_instantiation;
101 static GSList *gclass_recorded_list;
102 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
107 mono_locks_os_acquire (&classes_mutex, ClassesLock);
111 classes_unlock (void)
113 mono_locks_os_release (&classes_mutex, ClassesLock);
117 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
120 enable_gclass_recording (void)
122 ++record_gclass_instantiation;
126 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
129 disable_gclass_recording (gclass_record_func func, void *user_data)
131 GSList **head = &gclass_recorded_list;
133 g_assert (record_gclass_instantiation > 0);
134 --record_gclass_instantiation;
137 GSList *node = *head;
138 if (func ((MonoClass*)node->data, user_data)) {
140 g_slist_free_1 (node);
146 /* We automatically discard all recorded gclasses when disabled. */
147 if (!record_gclass_instantiation && gclass_recorded_list) {
148 g_slist_free (gclass_recorded_list);
149 gclass_recorded_list = NULL;
154 * mono_class_from_typeref:
155 * @image: a MonoImage
156 * @type_token: a TypeRef token
158 * Creates the MonoClass* structure representing the type defined by
159 * the typeref token valid inside @image.
160 * Returns: The MonoClass* representing the typeref token, NULL ifcould
164 mono_class_from_typeref (MonoImage *image, guint32 type_token)
167 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
168 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
173 * mono_class_from_typeref_checked:
174 * @image: a MonoImage
175 * @type_token: a TypeRef token
176 * @error: error return code, if any.
178 * Creates the MonoClass* structure representing the type defined by
179 * the typeref token valid inside @image.
181 * Returns: The MonoClass* representing the typeref token, NULL if it could
182 * not be loaded with the @error value filled with the information about the
186 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
188 guint32 cols [MONO_TYPEREF_SIZE];
189 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
191 const char *name, *nspace;
192 MonoClass *res = NULL;
195 mono_error_init (error);
197 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
200 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
202 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
203 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
205 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
206 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
207 case MONO_RESOLUTION_SCOPE_MODULE:
209 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
210 This is not the observed behavior of existing implementations.
211 The defacto behavior is that it's just a typedef in disguise.
213 /* a typedef in disguise */
214 res = mono_class_from_name_checked (image, nspace, name, error);
217 case MONO_RESOLUTION_SCOPE_MODULEREF:
218 module = mono_image_load_module (image, idx);
220 res = mono_class_from_name_checked (module, nspace, name, error);
223 case MONO_RESOLUTION_SCOPE_TYPEREF: {
224 MonoClass *enclosing;
227 if (idx == mono_metadata_token_index (type_token)) {
228 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
232 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
233 return_val_if_nok (error, NULL);
235 if (enclosing->nested_classes_inited && enclosing->ext) {
236 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
237 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
238 res = (MonoClass *)tmp->data;
239 if (strcmp (res->name, name) == 0)
243 /* Don't call mono_class_init as we might've been called by it recursively */
244 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
246 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
247 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
248 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
250 if (strcmp (nname, name) == 0)
251 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
253 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
256 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
259 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
263 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
264 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
268 if (!image->references || !image->references [idx - 1])
269 mono_assembly_load_reference (image, idx - 1);
270 g_assert (image->references [idx - 1]);
272 /* If the assembly did not load, register this as a type load exception */
273 if (image->references [idx - 1] == REFERENCE_MISSING){
274 MonoAssemblyName aname;
277 mono_assembly_get_assemblyref (image, idx - 1, &aname);
278 human_name = mono_stringify_assembly_name (&aname);
279 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
283 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
286 /* Generic case, should be avoided for when a better error is possible. */
287 if (!res && mono_error_ok (error)) {
288 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
289 mono_error_set_from_loader_error (error);
291 char *name = mono_class_name_from_token (image, type_token);
292 char *assembly = mono_assembly_name_from_token (image, type_token);
293 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
296 mono_loader_assert_no_error ();
302 mono_image_memdup (MonoImage *image, void *data, guint size)
304 void *res = mono_image_alloc (image, size);
305 memcpy (res, data, size);
309 /* Copy everything mono_metadata_free_array free. */
311 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
314 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
316 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
318 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
320 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
322 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
324 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
329 /* Copy everything mono_metadata_free_method_signature free. */
331 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
335 sig = mono_metadata_signature_dup_full (image, sig);
337 sig->ret = mono_metadata_type_dup (image, sig->ret);
338 for (i = 0; i < sig->param_count; ++i)
339 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
345 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
347 MonoAssembly *ta = klass->image->assembly;
350 name = mono_stringify_assembly_name (&ta->aname);
351 g_string_append_printf (str, ", %s", name);
356 mono_type_name_check_byref (MonoType *type, GString *str)
359 g_string_append_c (str, '&');
363 * mono_identifier_escape_type_name_chars:
364 * @str: a destination string
365 * @identifier: an IDENTIFIER in internal form
369 * The displayed form of the identifier is appended to str.
371 * The displayed form of an identifier has the characters ,+&*[]\
372 * that have special meaning in type names escaped with a preceeding
373 * backslash (\) character.
376 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
382 // reserve space for common case: there will be no escaped characters.
383 g_string_set_size(str, n + strlen(identifier));
384 g_string_set_size(str, n);
386 for (const char* s = identifier; *s != 0 ; s++) {
395 g_string_append_c (str, '\\');
396 g_string_append_c (str, *s);
399 g_string_append_c (str, *s);
407 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
408 MonoTypeNameFormat format)
412 switch (type->type) {
413 case MONO_TYPE_ARRAY: {
414 int i, rank = type->data.array->rank;
415 MonoTypeNameFormat nested_format;
417 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
418 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
420 mono_type_get_name_recurse (
421 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
422 g_string_append_c (str, '[');
424 g_string_append_c (str, '*');
425 for (i = 1; i < rank; i++)
426 g_string_append_c (str, ',');
427 g_string_append_c (str, ']');
429 mono_type_name_check_byref (type, str);
431 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
432 _mono_type_get_assembly_name (type->data.array->eklass, str);
435 case MONO_TYPE_SZARRAY: {
436 MonoTypeNameFormat nested_format;
438 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
439 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
441 mono_type_get_name_recurse (
442 &type->data.klass->byval_arg, str, FALSE, nested_format);
443 g_string_append (str, "[]");
445 mono_type_name_check_byref (type, str);
447 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
448 _mono_type_get_assembly_name (type->data.klass, str);
451 case MONO_TYPE_PTR: {
452 MonoTypeNameFormat nested_format;
454 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
455 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
457 mono_type_get_name_recurse (
458 type->data.type, str, FALSE, nested_format);
459 g_string_append_c (str, '*');
461 mono_type_name_check_byref (type, str);
463 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
464 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
469 if (!mono_generic_param_info (type->data.generic_param))
470 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
472 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
474 mono_type_name_check_byref (type, str);
478 klass = mono_class_from_mono_type (type);
479 if (klass->nested_in) {
480 mono_type_get_name_recurse (
481 &klass->nested_in->byval_arg, str, TRUE, format);
482 if (format == MONO_TYPE_NAME_FORMAT_IL)
483 g_string_append_c (str, '.');
485 g_string_append_c (str, '+');
486 } else if (*klass->name_space) {
487 if (format == MONO_TYPE_NAME_FORMAT_IL)
488 g_string_append (str, klass->name_space);
490 mono_identifier_escape_type_name_chars (str, klass->name_space);
491 g_string_append_c (str, '.');
493 if (format == MONO_TYPE_NAME_FORMAT_IL) {
494 char *s = strchr (klass->name, '`');
495 int len = s ? s - klass->name : strlen (klass->name);
496 g_string_append_len (str, klass->name, len);
498 mono_identifier_escape_type_name_chars (str, klass->name);
502 if (klass->generic_class) {
503 MonoGenericClass *gclass = klass->generic_class;
504 MonoGenericInst *inst = gclass->context.class_inst;
505 MonoTypeNameFormat nested_format;
508 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
509 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
511 if (format == MONO_TYPE_NAME_FORMAT_IL)
512 g_string_append_c (str, '<');
514 g_string_append_c (str, '[');
515 for (i = 0; i < inst->type_argc; i++) {
516 MonoType *t = inst->type_argv [i];
519 g_string_append_c (str, ',');
520 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
521 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
522 g_string_append_c (str, '[');
523 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
524 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
525 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
526 g_string_append_c (str, ']');
528 if (format == MONO_TYPE_NAME_FORMAT_IL)
529 g_string_append_c (str, '>');
531 g_string_append_c (str, ']');
532 } else if (klass->generic_container &&
533 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
534 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
537 if (format == MONO_TYPE_NAME_FORMAT_IL)
538 g_string_append_c (str, '<');
540 g_string_append_c (str, '[');
541 for (i = 0; i < klass->generic_container->type_argc; i++) {
543 g_string_append_c (str, ',');
544 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
546 if (format == MONO_TYPE_NAME_FORMAT_IL)
547 g_string_append_c (str, '>');
549 g_string_append_c (str, ']');
552 mono_type_name_check_byref (type, str);
554 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
555 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
556 _mono_type_get_assembly_name (klass, str);
562 * mono_type_get_name_full:
564 * @format: the format for the return string.
567 * Returns: The string representation in a number of formats:
569 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
570 * returned in the formatrequired by System.Reflection, this is the
571 * inverse of mono_reflection_parse_type ().
573 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
574 * be used by the IL assembler.
576 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
578 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
581 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
585 result = g_string_new ("");
587 mono_type_get_name_recurse (type, result, FALSE, format);
589 return g_string_free (result, FALSE);
593 * mono_type_get_full_name:
596 * Returns: The string representation for type as required by System.Reflection.
597 * The inverse of mono_reflection_parse_type ().
600 mono_type_get_full_name (MonoClass *klass)
602 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
606 * mono_type_get_name:
609 * Returns: The string representation for type as it would be represented in IL code.
612 mono_type_get_name (MonoType *type)
614 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
618 * mono_type_get_underlying_type:
621 * Returns: The MonoType for the underlying integer type if @type
622 * is an enum and byref is false, otherwise the type itself.
625 mono_type_get_underlying_type (MonoType *type)
627 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
628 return mono_class_enum_basetype (type->data.klass);
629 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
630 return mono_class_enum_basetype (type->data.generic_class->container_class);
635 * mono_class_is_open_constructed_type:
638 * Returns: TRUE if type represents a generics open constructed type.
639 * IOW, not all type parameters required for the instantiation have
640 * been provided or it's a generic type definition.
642 * An open constructed type means it's a non realizable type. Not to
643 * be mixed up with an abstract type - we can't cast or dispatch to
644 * an open type, for example.
647 mono_class_is_open_constructed_type (MonoType *t)
653 case MONO_TYPE_SZARRAY:
654 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
655 case MONO_TYPE_ARRAY:
656 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
658 return mono_class_is_open_constructed_type (t->data.type);
659 case MONO_TYPE_GENERICINST:
660 return t->data.generic_class->context.class_inst->is_open;
661 case MONO_TYPE_CLASS:
662 case MONO_TYPE_VALUETYPE:
663 return t->data.klass->generic_container != NULL;
670 This is a simple function to catch the most common bad instances of generic types.
671 Specially those that might lead to further failures in the runtime.
674 is_valid_generic_argument (MonoType *type)
676 switch (type->type) {
678 //case MONO_TYPE_TYPEDBYREF:
686 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
688 mono_error_init (error);
690 switch (type->type) {
691 case MONO_TYPE_MVAR: {
693 int num = mono_type_get_generic_param_num (type);
694 MonoGenericInst *inst = context->method_inst;
697 if (num >= inst->type_argc) {
698 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
699 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
700 num, info ? info->name : "", inst->type_argc);
704 if (!is_valid_generic_argument (inst->type_argv [num])) {
705 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
706 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
707 num, info ? info->name : "", inst->type_argv [num]->type);
711 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
712 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
713 * ->byref and ->attrs from @type are propagated to the returned type.
715 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
716 nt->byref = type->byref;
717 nt->attrs = type->attrs;
720 case MONO_TYPE_VAR: {
722 int num = mono_type_get_generic_param_num (type);
723 MonoGenericInst *inst = context->class_inst;
726 if (num >= inst->type_argc) {
727 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
728 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
729 num, info ? info->name : "", inst->type_argc);
732 if (!is_valid_generic_argument (inst->type_argv [num])) {
733 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
734 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
735 num, info ? info->name : "", inst->type_argv [num]->type);
738 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
739 nt->byref = type->byref;
740 nt->attrs = type->attrs;
743 case MONO_TYPE_SZARRAY: {
744 MonoClass *eclass = type->data.klass;
745 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
746 if (!inflated || !mono_error_ok (error))
748 nt = mono_metadata_type_dup (image, type);
749 nt->data.klass = mono_class_from_mono_type (inflated);
750 mono_metadata_free_type (inflated);
753 case MONO_TYPE_ARRAY: {
754 MonoClass *eclass = type->data.array->eklass;
755 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
756 if (!inflated || !mono_error_ok (error))
758 nt = mono_metadata_type_dup (image, type);
759 nt->data.array->eklass = mono_class_from_mono_type (inflated);
760 mono_metadata_free_type (inflated);
763 case MONO_TYPE_GENERICINST: {
764 MonoGenericClass *gclass = type->data.generic_class;
765 MonoGenericInst *inst;
767 if (!gclass->context.class_inst->is_open)
770 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
771 return_val_if_nok (error, NULL);
773 if (inst != gclass->context.class_inst)
774 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
776 if (gclass == type->data.generic_class)
779 nt = mono_metadata_type_dup (image, type);
780 nt->data.generic_class = gclass;
783 case MONO_TYPE_CLASS:
784 case MONO_TYPE_VALUETYPE: {
785 MonoClass *klass = type->data.klass;
786 MonoGenericContainer *container = klass->generic_container;
787 MonoGenericInst *inst;
788 MonoGenericClass *gclass = NULL;
794 /* We can't use context->class_inst directly, since it can have more elements */
795 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
796 return_val_if_nok (error, NULL);
798 if (inst == container->context.class_inst)
801 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
803 nt = mono_metadata_type_dup (image, type);
804 nt->type = MONO_TYPE_GENERICINST;
805 nt->data.generic_class = gclass;
815 mono_generic_class_get_context (MonoGenericClass *gclass)
817 return &gclass->context;
821 mono_class_get_context (MonoClass *klass)
823 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
827 * mono_class_get_generic_container:
829 * Return the generic container of KLASS which should be a generic type definition.
831 MonoGenericContainer*
832 mono_class_get_generic_container (MonoClass *klass)
834 g_assert (klass->is_generic);
836 return klass->generic_container;
840 * mono_class_get_generic_class:
842 * Return the MonoGenericClass of KLASS, which should be a generic instance.
845 mono_class_get_generic_class (MonoClass *klass)
847 g_assert (klass->is_inflated);
849 return klass->generic_class;
853 * mono_class_inflate_generic_type_with_mempool:
854 * @mempool: a mempool
856 * @context: a generics context
857 * @error: error context
859 * The same as mono_class_inflate_generic_type, but allocates the MonoType
860 * from mempool if it is non-NULL. If it is NULL, the MonoType is
861 * allocated on the heap and is owned by the caller.
862 * The returned type can potentially be the same as TYPE, so it should not be
863 * modified by the caller, and it should be freed using mono_metadata_free_type ().
866 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
868 MonoType *inflated = NULL;
869 mono_error_init (error);
872 inflated = inflate_generic_type (image, type, context, error);
873 return_val_if_nok (error, NULL);
876 MonoType *shared = mono_metadata_get_shared_type (type);
881 return mono_metadata_type_dup (image, type);
885 mono_stats.inflated_type_count++;
890 * mono_class_inflate_generic_type:
892 * @context: a generics context
894 * If @type is a generic type and @context is not NULL, instantiate it using the
895 * generics context @context.
897 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
898 * on the heap and is owned by the caller. Returns NULL on error.
900 * @deprecated Please use mono_class_inflate_generic_type_checked instead
903 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
907 result = mono_class_inflate_generic_type_checked (type, context, &error);
908 mono_error_cleanup (&error);
913 * mono_class_inflate_generic_type:
915 * @context: a generics context
916 * @error: error context to use
918 * If @type is a generic type and @context is not NULL, instantiate it using the
919 * generics context @context.
921 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
922 * on the heap and is owned by the caller.
925 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
927 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
931 * mono_class_inflate_generic_type_no_copy:
933 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
937 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
939 MonoType *inflated = NULL;
941 mono_error_init (error);
943 inflated = inflate_generic_type (image, type, context, error);
944 return_val_if_nok (error, NULL);
950 mono_stats.inflated_type_count++;
955 * mono_class_inflate_generic_class:
957 * Inflate the class @gklass with @context. Set @error on failure.
960 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
965 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
966 return_val_if_nok (error, NULL);
968 res = mono_class_from_mono_type (inflated);
969 mono_metadata_free_type (inflated);
974 static MonoGenericContext
975 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
977 MonoGenericInst *class_inst = NULL;
978 MonoGenericInst *method_inst = NULL;
979 MonoGenericContext res = { NULL, NULL };
981 mono_error_init (error);
983 if (context->class_inst) {
984 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
985 if (!mono_error_ok (error))
989 if (context->method_inst) {
990 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
991 if (!mono_error_ok (error))
995 res.class_inst = class_inst;
996 res.method_inst = method_inst;
1002 * mono_class_inflate_generic_method:
1003 * @method: a generic method
1004 * @context: a generics context
1006 * Instantiate the generic method @method using the generics context @context.
1008 * Returns: The new instantiated method
1011 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1013 return mono_class_inflate_generic_method_full (method, NULL, context);
1017 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1019 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1023 * mono_class_inflate_generic_method_full:
1025 * Instantiate method @method with the generic context @context.
1026 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1027 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1030 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1033 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1034 if (!mono_error_ok (&error))
1035 /*FIXME do proper error handling - on this case, kill this function. */
1036 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1042 * mono_class_inflate_generic_method_full_checked:
1043 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1046 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1049 MonoMethodInflated *iresult, *cached;
1050 MonoMethodSignature *sig;
1051 MonoGenericContext tmp_context;
1053 mono_error_init (error);
1055 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1056 while (method->is_inflated) {
1057 MonoGenericContext *method_context = mono_method_get_context (method);
1058 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1060 tmp_context = inflate_generic_context (method_context, context, error);
1061 return_val_if_nok (error, NULL);
1063 context = &tmp_context;
1065 if (mono_metadata_generic_context_equal (method_context, context))
1068 method = imethod->declaring;
1072 * A method only needs to be inflated if the context has argument for which it is
1075 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1076 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1079 if (!((method->is_generic && context->method_inst) ||
1080 (method->klass->generic_container && context->class_inst)))
1083 iresult = g_new0 (MonoMethodInflated, 1);
1084 iresult->context = *context;
1085 iresult->declaring = method;
1087 if (!context->method_inst && method->is_generic)
1088 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1090 if (!context->class_inst) {
1091 g_assert (!iresult->declaring->klass->generic_class);
1092 if (iresult->declaring->klass->generic_container)
1093 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1094 else if (iresult->declaring->klass->generic_class)
1095 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1097 /* This can happen with some callers like mono_object_get_virtual_method () */
1098 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1099 iresult->context.class_inst = NULL;
1101 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1104 mono_image_set_lock (set);
1105 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1106 mono_image_set_unlock (set);
1110 return (MonoMethod*)cached;
1113 mono_stats.inflated_method_count++;
1115 inflated_methods_size += sizeof (MonoMethodInflated);
1117 sig = mono_method_signature (method);
1119 char *name = mono_type_get_full_name (method->klass);
1120 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1126 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1128 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1131 result = (MonoMethod *) iresult;
1132 result->is_inflated = TRUE;
1133 result->is_generic = FALSE;
1134 result->sre_method = FALSE;
1135 result->signature = NULL;
1137 if (!context->method_inst) {
1138 /* Set the generic_container of the result to the generic_container of method */
1139 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1141 if (generic_container) {
1142 result->is_generic = 1;
1143 mono_method_set_generic_container (result, generic_container);
1147 if (!klass_hint || !klass_hint->generic_class ||
1148 klass_hint->generic_class->container_class != method->klass ||
1149 klass_hint->generic_class->context.class_inst != context->class_inst)
1152 if (method->klass->generic_container)
1153 result->klass = klass_hint;
1155 if (!result->klass) {
1156 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1157 if (!mono_error_ok (error))
1160 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1162 mono_metadata_free_type (inflated);
1166 * FIXME: This should hold, but it doesn't:
1168 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1169 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1170 * g_assert (result->is_generic);
1173 * Fixing this here causes other things to break, hence a very
1174 * ugly hack in mini-trampolines.c - see
1175 * is_generic_method_definition().
1179 mono_image_set_lock (set);
1180 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1182 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1183 iresult->owner = set;
1186 mono_image_set_unlock (set);
1188 return (MonoMethod*)cached;
1196 * mono_get_inflated_method:
1198 * Obsolete. We keep it around since it's mentioned in the public API.
1201 mono_get_inflated_method (MonoMethod *method)
1207 * mono_method_get_context_general:
1209 * @uninflated: handle uninflated methods?
1211 * Returns the generic context of a method or NULL if it doesn't have
1212 * one. For an inflated method that's the context stored in the
1213 * method. Otherwise it's in the method's generic container or in the
1214 * generic container of the method's class.
1217 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1219 if (method->is_inflated) {
1220 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1221 return &imethod->context;
1225 if (method->is_generic)
1226 return &(mono_method_get_generic_container (method)->context);
1227 if (method->klass->generic_container)
1228 return &method->klass->generic_container->context;
1233 * mono_method_get_context:
1236 * Returns the generic context for method if it's inflated, otherwise
1240 mono_method_get_context (MonoMethod *method)
1242 return mono_method_get_context_general (method, FALSE);
1246 * mono_method_get_generic_container:
1248 * Returns the generic container of METHOD, which should be a generic method definition.
1249 * Returns NULL if METHOD is not a generic method definition.
1250 * LOCKING: Acquires the loader lock.
1252 MonoGenericContainer*
1253 mono_method_get_generic_container (MonoMethod *method)
1255 MonoGenericContainer *container;
1257 if (!method->is_generic)
1260 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1261 g_assert (container);
1267 * mono_method_set_generic_container:
1269 * Sets the generic container of METHOD to CONTAINER.
1270 * LOCKING: Acquires the image lock.
1273 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1275 g_assert (method->is_generic);
1277 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1281 * mono_class_find_enum_basetype:
1282 * @class: The enum class
1284 * Determine the basetype of an enum by iterating through its fields. We do this
1285 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1288 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1290 MonoGenericContainer *container = NULL;
1291 MonoImage *m = klass->image;
1292 const int top = klass->field.count;
1295 g_assert (klass->enumtype);
1297 mono_error_init (error);
1299 if (klass->generic_container)
1300 container = klass->generic_container;
1301 else if (klass->generic_class) {
1302 MonoClass *gklass = klass->generic_class->container_class;
1304 container = gklass->generic_container;
1305 g_assert (container);
1309 * Fetch all the field information.
1311 for (i = 0; i < top; i++){
1313 guint32 cols [MONO_FIELD_SIZE];
1314 int idx = klass->field.first + i;
1317 /* klass->field.first and idx points into the fieldptr table */
1318 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1320 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1323 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1324 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1328 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1329 mono_metadata_decode_value (sig, &sig);
1330 /* FIELD signature == 0x06 */
1332 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1336 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1340 if (klass->generic_class) {
1341 //FIXME do we leak here?
1342 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1343 if (!mono_error_ok (error))
1345 ftype->attrs = cols [MONO_FIELD_FLAGS];
1350 mono_error_set_type_load_class (error, klass, "Could not find base type");
1353 mono_loader_assert_no_error ();
1358 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1361 mono_type_has_exceptions (MonoType *type)
1363 switch (type->type) {
1364 case MONO_TYPE_CLASS:
1365 case MONO_TYPE_VALUETYPE:
1366 case MONO_TYPE_SZARRAY:
1367 return mono_class_has_failure (type->data.klass);
1368 case MONO_TYPE_ARRAY:
1369 return mono_class_has_failure (type->data.array->eklass);
1370 case MONO_TYPE_GENERICINST:
1371 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1380 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1384 mono_class_alloc (MonoClass *klass, int size)
1386 if (klass->generic_class)
1387 return mono_image_set_alloc (klass->generic_class->owner, size);
1389 return mono_image_alloc (klass->image, size);
1393 mono_class_alloc0 (MonoClass *klass, int size)
1397 res = mono_class_alloc (klass, size);
1398 memset (res, 0, size);
1402 #define mono_class_new0(klass,struct_type, n_structs) \
1403 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1406 * mono_class_setup_basic_field_info:
1407 * @class: The class to initialize
1409 * Initializes the klass->fields.
1410 * LOCKING: Assumes the loader lock is held.
1413 mono_class_setup_basic_field_info (MonoClass *klass)
1415 MonoClassField *field;
1423 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1424 image = klass->image;
1425 top = klass->field.count;
1427 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1429 * This happens when a generic instance of an unfinished generic typebuilder
1430 * is used as an element type for creating an array type. We can't initialize
1431 * the fields of this class using the fields of gklass, since gklass is not
1432 * finished yet, fields could be added to it later.
1438 mono_class_setup_basic_field_info (gtd);
1440 top = gtd->field.count;
1441 klass->field.first = gtd->field.first;
1442 klass->field.count = gtd->field.count;
1445 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1448 * Fetch all the field information.
1450 for (i = 0; i < top; i++){
1451 field = &klass->fields [i];
1452 field->parent = klass;
1455 field->name = mono_field_get_name (>d->fields [i]);
1457 int idx = klass->field.first + i;
1458 /* klass->field.first and idx points into the fieldptr table */
1459 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1460 /* The name is needed for fieldrefs */
1461 field->name = mono_metadata_string_heap (image, name_idx);
1467 * mono_class_setup_fields:
1468 * @class: The class to initialize
1470 * Initializes the klass->fields.
1471 * LOCKING: Assumes the loader lock is held.
1474 mono_class_setup_fields (MonoClass *klass)
1477 MonoImage *m = klass->image;
1479 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1480 int i, blittable = TRUE;
1481 guint32 real_size = 0;
1482 guint32 packing_size = 0;
1484 gboolean explicit_size;
1485 MonoClassField *field;
1486 MonoGenericContainer *container = NULL;
1487 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1490 * FIXME: We have a race condition here. It's possible that this function returns
1491 * to its caller with `instance_size` set to `0` instead of the actual size. This
1492 * is not a problem when the function is called recursively on the same class,
1493 * because the size will be initialized by the outer invocation. What follows is a
1494 * description of how it can occur in other cases, too. There it is a problem,
1495 * because it can lead to the GC being asked to allocate an object of size `0`,
1496 * which SGen chokes on. The race condition is triggered infrequently by
1497 * `tests/sgen-suspend.cs`.
1499 * This function is called for a class whenever one of its subclasses is inited.
1500 * For example, it's called for every subclass of Object. What it does is this:
1502 * if (klass->setup_fields_called)
1505 * klass->instance_size = 0;
1507 * klass->setup_fields_called = 1;
1508 * ... critical point
1509 * klass->instance_size = actual_instance_size;
1511 * The last two steps are sometimes reversed, but that only changes the way in which
1512 * the race condition works.
1514 * Assume thread A goes through this function and makes it to the critical point.
1515 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1516 * immediately, but `instance_size` is incorrect.
1518 * The other case looks like this:
1520 * if (klass->setup_fields_called)
1522 * ... critical point X
1523 * klass->instance_size = 0;
1524 * ... critical point Y
1525 * klass->instance_size = actual_instance_size;
1527 * klass->setup_fields_called = 1;
1529 * Assume thread A goes through the function and makes it to critical point X. Now
1530 * thread B runs through the whole of the function, returning, assuming
1531 * `instance_size` is set. At that point thread A gets to run and makes it to
1532 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1535 if (klass->setup_fields_called)
1538 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1540 * This happens when a generic instance of an unfinished generic typebuilder
1541 * is used as an element type for creating an array type. We can't initialize
1542 * the fields of this class using the fields of gklass, since gklass is not
1543 * finished yet, fields could be added to it later.
1548 mono_class_setup_basic_field_info (klass);
1549 top = klass->field.count;
1552 mono_class_setup_fields (gtd);
1553 if (mono_class_has_failure (gtd)) {
1554 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1561 klass->sizes.class_size = 0;
1563 if (klass->parent) {
1564 /* For generic instances, klass->parent might not have been initialized */
1565 mono_class_init (klass->parent);
1566 if (!klass->parent->size_inited) {
1567 mono_class_setup_fields (klass->parent);
1568 if (mono_class_has_failure (klass->parent)) {
1569 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1573 instance_size += klass->parent->instance_size;
1574 klass->min_align = klass->parent->min_align;
1575 /* we use |= since it may have been set already */
1576 klass->has_references |= klass->parent->has_references;
1577 blittable = klass->parent->blittable;
1579 instance_size = sizeof (MonoObject);
1580 klass->min_align = 1;
1583 /* We can't really enable 16 bytes alignment until the GC supports it.
1584 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1585 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1586 Bug #506144 is an example of this issue.
1588 if (klass->simd_type)
1589 klass->min_align = 16;
1591 /* Get the real size */
1592 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1594 if (explicit_size) {
1595 if ((packing_size & 0xffffff00) != 0) {
1596 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1597 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1600 klass->packing_size = packing_size;
1601 real_size += instance_size;
1605 if (explicit_size && real_size) {
1606 instance_size = MAX (real_size, instance_size);
1608 klass->blittable = blittable;
1609 if (!klass->instance_size)
1610 klass->instance_size = instance_size;
1611 mono_memory_barrier ();
1612 klass->size_inited = 1;
1613 klass->fields_inited = 1;
1614 klass->setup_fields_called = 1;
1618 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1621 /* Prevent infinite loops if the class references itself */
1622 klass->setup_fields_called = 1;
1624 if (klass->generic_container) {
1625 container = klass->generic_container;
1627 container = gtd->generic_container;
1628 g_assert (container);
1632 * Fetch all the field information.
1634 for (i = 0; i < top; i++){
1635 int idx = klass->field.first + i;
1636 field = &klass->fields [i];
1638 field->parent = klass;
1641 mono_field_resolve_type (field, &error);
1642 if (!mono_error_ok (&error)) {
1643 /*mono_field_resolve_type already failed class*/
1644 mono_error_cleanup (&error);
1648 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1649 g_assert (field->type);
1652 if (mono_field_is_deleted (field))
1655 MonoClassField *gfield = >d->fields [i];
1656 field->offset = gfield->offset;
1658 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1660 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1661 field->offset = offset;
1663 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1664 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1667 if (field->offset < -1) { /*-1 is used to encode special static fields */
1668 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1671 if (klass->generic_container) {
1672 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1678 /* Only do these checks if we still think this type is blittable */
1679 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1680 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1683 MonoClass *field_class = mono_class_from_mono_type (field->type);
1685 mono_class_setup_fields (field_class);
1686 if (mono_class_has_failure (field_class)) {
1687 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1691 if (!field_class || !field_class->blittable)
1696 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1697 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1698 blittable = klass->element_class->blittable;
1701 if (mono_type_has_exceptions (field->type)) {
1702 char *class_name = mono_type_get_full_name (klass);
1703 char *type_name = mono_type_full_name (field->type);
1705 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1706 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1707 g_free (class_name);
1711 /* The def_value of fields is compute lazily during vtable creation */
1714 if (klass == mono_defaults.string_class)
1717 klass->blittable = blittable;
1719 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1720 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1723 if (explicit_size && real_size) {
1724 instance_size = MAX (real_size, instance_size);
1727 if (mono_class_has_failure (klass))
1729 mono_class_layout_fields (klass, instance_size);
1731 /*valuetypes can't be neither bigger than 1Mb or empty. */
1732 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1733 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1735 mono_memory_barrier ();
1736 klass->fields_inited = 1;
1740 * mono_class_setup_fields_locking:
1741 * @class: The class to initialize
1743 * Initializes the klass->fields array of fields.
1744 * Aquires the loader lock.
1747 mono_class_setup_fields_locking (MonoClass *klass)
1749 /* This can be checked without locks */
1750 if (klass->fields_inited)
1752 mono_loader_lock ();
1753 mono_class_setup_fields (klass);
1754 mono_loader_unlock ();
1758 * mono_class_has_references:
1760 * Returns whenever @klass->has_references is set, initializing it if needed.
1761 * Aquires the loader lock.
1764 mono_class_has_references (MonoClass *klass)
1766 if (klass->init_pending) {
1767 /* Be conservative */
1770 mono_class_init (klass);
1772 return klass->has_references;
1777 * mono_type_get_basic_type_from_generic:
1780 * Returns a closed type corresponding to the possibly open type
1784 mono_type_get_basic_type_from_generic (MonoType *type)
1786 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1787 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1788 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1789 return &mono_defaults.object_class->byval_arg;
1794 type_has_references (MonoClass *klass, MonoType *ftype)
1796 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)))))
1798 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1799 MonoGenericParam *gparam = ftype->data.generic_param;
1801 if (gparam->gshared_constraint)
1802 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1808 * mono_class_layout_fields:
1810 * @instance_size: base instance size
1812 * Compute the placement of fields inside an object or struct, according to
1813 * the layout rules and set the following fields in @class:
1814 * - has_references (if the class contains instance references firled or structs that contain references)
1815 * - has_static_refs (same, but for static fields)
1816 * - instance_size (size of the object in memory)
1817 * - class_size (size needed for the static fields)
1818 * - size_inited (flag set when the instance_size is set)
1820 * LOCKING: this is supposed to be called with the loader lock held.
1823 mono_class_layout_fields (MonoClass *klass, int instance_size)
1826 const int top = klass->field.count;
1827 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1828 guint32 pass, passes, real_size;
1829 gboolean gc_aware_layout = FALSE;
1830 gboolean has_static_fields = FALSE;
1831 MonoClassField *field;
1834 * When we do generic sharing we need to have layout
1835 * information for open generic classes (either with a generic
1836 * context containing type variables or with a generic
1837 * container), so we don't return in that case anymore.
1841 * Enable GC aware auto layout: in this mode, reference
1842 * fields are grouped together inside objects, increasing collector
1844 * Requires that all classes whose layout is known to native code be annotated
1845 * with [StructLayout (LayoutKind.Sequential)]
1846 * Value types have gc_aware_layout disabled by default, as per
1847 * what the default is for other runtimes.
1849 /* corlib is missing [StructLayout] directives in many places */
1850 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1851 if (!klass->valuetype)
1852 gc_aware_layout = TRUE;
1855 /* Compute klass->has_references */
1857 * Process non-static fields first, since static fields might recursively
1858 * refer to the class itself.
1860 for (i = 0; i < top; i++) {
1863 field = &klass->fields [i];
1865 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1866 ftype = mono_type_get_underlying_type (field->type);
1867 ftype = mono_type_get_basic_type_from_generic (ftype);
1868 if (type_has_references (klass, ftype))
1869 klass->has_references = TRUE;
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_static_refs = TRUE;
1886 for (i = 0; i < top; i++) {
1889 field = &klass->fields [i];
1891 ftype = mono_type_get_underlying_type (field->type);
1892 ftype = mono_type_get_basic_type_from_generic (ftype);
1893 if (type_has_references (klass, ftype)) {
1894 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1895 klass->has_static_refs = TRUE;
1897 klass->has_references = TRUE;
1902 * Compute field layout and total size (not considering static fields)
1905 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1906 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1908 if (gc_aware_layout)
1913 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1916 if (klass->parent) {
1917 mono_class_setup_fields (klass->parent);
1918 if (mono_class_has_failure (klass->parent)) {
1919 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1922 real_size = klass->parent->instance_size;
1924 real_size = sizeof (MonoObject);
1927 for (pass = 0; pass < passes; ++pass) {
1928 for (i = 0; i < top; i++){
1933 field = &klass->fields [i];
1935 if (mono_field_is_deleted (field))
1937 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1940 ftype = mono_type_get_underlying_type (field->type);
1941 ftype = mono_type_get_basic_type_from_generic (ftype);
1942 if (gc_aware_layout) {
1943 if (type_has_references (klass, ftype)) {
1952 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1953 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1954 /* This field is a hack inserted by MCS to empty structures */
1958 size = mono_type_size (field->type, &align);
1960 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1961 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1962 /* if the field has managed references, we need to force-align it
1965 if (type_has_references (klass, ftype))
1966 align = MAX (align, sizeof (gpointer));
1968 klass->min_align = MAX (align, klass->min_align);
1969 field->offset = real_size;
1971 field->offset += align - 1;
1972 field->offset &= ~(align - 1);
1974 /*TypeBuilders produce all sort of weird things*/
1975 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1976 real_size = field->offset + size;
1979 instance_size = MAX (real_size, instance_size);
1981 if (instance_size & (klass->min_align - 1)) {
1982 instance_size += klass->min_align - 1;
1983 instance_size &= ~(klass->min_align - 1);
1987 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1991 for (i = 0; i < top; i++) {
1996 field = &klass->fields [i];
1999 * There must be info about all the fields in a type if it
2000 * uses explicit layout.
2002 if (mono_field_is_deleted (field))
2004 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2007 size = mono_type_size (field->type, &align);
2008 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2009 klass->min_align = MAX (align, klass->min_align);
2012 * When we get here, field->offset is already set by the
2013 * loader (for either runtime fields or fields loaded from metadata).
2014 * The offset is from the start of the object: this works for both
2015 * classes and valuetypes.
2017 field->offset += sizeof (MonoObject);
2018 ftype = mono_type_get_underlying_type (field->type);
2019 ftype = mono_type_get_basic_type_from_generic (ftype);
2020 if (type_has_references (klass, ftype)) {
2021 if (field->offset % sizeof (gpointer)) {
2022 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2029 real_size = MAX (real_size, size + field->offset);
2032 if (klass->has_references) {
2033 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2035 /* Check for overlapping reference and non-reference fields */
2036 for (i = 0; i < top; i++) {
2039 field = &klass->fields [i];
2041 if (mono_field_is_deleted (field))
2043 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2045 ftype = mono_type_get_underlying_type (field->type);
2046 if (MONO_TYPE_IS_REFERENCE (ftype))
2047 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2049 for (i = 0; i < top; i++) {
2050 field = &klass->fields [i];
2052 if (mono_field_is_deleted (field))
2054 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2057 // FIXME: Too much code does this
2059 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2060 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);
2061 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2065 g_free (ref_bitmap);
2068 instance_size = MAX (real_size, instance_size);
2069 if (instance_size & (klass->min_align - 1)) {
2070 instance_size += klass->min_align - 1;
2071 instance_size &= ~(klass->min_align - 1);
2077 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2079 * This leads to all kinds of problems with nested structs, so only
2080 * enable it when a MONO_DEBUG property is set.
2082 * For small structs, set min_align to at least the struct size to improve
2083 * performance, and since the JIT memset/memcpy code assumes this and generates
2084 * unaligned accesses otherwise. See #78990 for a testcase.
2086 if (mono_align_small_structs) {
2087 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2088 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2092 if (klass->instance_size && !klass->image->dynamic) {
2093 /* Might be already set using cached info */
2094 g_assert (klass->instance_size == instance_size);
2096 klass->instance_size = instance_size;
2098 mono_memory_barrier ();
2099 klass->size_inited = 1;
2102 * Compute static field layout and size
2104 for (i = 0; i < top; i++){
2108 field = &klass->fields [i];
2110 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2112 if (mono_field_is_deleted (field))
2115 if (mono_type_has_exceptions (field->type)) {
2116 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2120 has_static_fields = TRUE;
2122 size = mono_type_size (field->type, &align);
2123 field->offset = klass->sizes.class_size;
2124 /*align is always non-zero here*/
2125 field->offset += align - 1;
2126 field->offset &= ~(align - 1);
2127 klass->sizes.class_size = field->offset + size;
2130 if (has_static_fields && klass->sizes.class_size == 0)
2131 /* Simplify code which depends on class_size != 0 if the class has static fields */
2132 klass->sizes.class_size = 8;
2136 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2140 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2141 method->klass = klass;
2142 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2143 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2144 method->signature = sig;
2145 method->name = name;
2148 if (name [0] == '.') {
2149 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2151 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2157 * mono_class_setup_methods:
2160 * Initializes the 'methods' array in CLASS.
2161 * Calling this method should be avoided if possible since it allocates a lot
2162 * of long-living MonoMethod structures.
2163 * Methods belonging to an interface are assigned a sequential slot starting
2166 * On failure this function sets klass->exception_type
2169 mono_class_setup_methods (MonoClass *klass)
2172 MonoMethod **methods;
2177 if (klass->generic_class) {
2179 MonoClass *gklass = klass->generic_class->container_class;
2181 mono_class_init (gklass);
2182 if (!mono_class_has_failure (gklass))
2183 mono_class_setup_methods (gklass);
2184 if (mono_class_has_failure (gklass)) {
2185 /* FIXME make exception_data less opaque so it's possible to dup it here */
2186 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2190 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2191 count = gklass->method.count;
2192 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2194 for (i = 0; i < count; i++) {
2195 methods [i] = mono_class_inflate_generic_method_full_checked (
2196 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2197 if (!mono_error_ok (&error)) {
2198 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2199 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)));
2202 mono_error_cleanup (&error);
2206 } else if (klass->rank) {
2208 MonoMethod *amethod;
2209 MonoMethodSignature *sig;
2210 int count_generic = 0, first_generic = 0;
2212 gboolean jagged_ctor = FALSE;
2214 count = 3 + (klass->rank > 1? 2: 1);
2216 mono_class_setup_interfaces (klass, &error);
2217 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2219 if (klass->rank == 1 && klass->element_class->rank) {
2221 klass->method.count ++;
2224 if (klass->interface_count) {
2225 count_generic = generic_array_methods (klass);
2226 first_generic = count;
2227 count += klass->interface_count * count_generic;
2230 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2232 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2233 sig->ret = &mono_defaults.void_class->byval_arg;
2234 sig->pinvoke = TRUE;
2235 sig->hasthis = TRUE;
2236 for (i = 0; i < klass->rank; ++i)
2237 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2239 amethod = create_array_method (klass, ".ctor", sig);
2240 methods [method_num++] = amethod;
2241 if (klass->rank > 1) {
2242 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2243 sig->ret = &mono_defaults.void_class->byval_arg;
2244 sig->pinvoke = TRUE;
2245 sig->hasthis = TRUE;
2246 for (i = 0; i < klass->rank * 2; ++i)
2247 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2249 amethod = create_array_method (klass, ".ctor", sig);
2250 methods [method_num++] = amethod;
2254 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2255 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2256 sig->ret = &mono_defaults.void_class->byval_arg;
2257 sig->pinvoke = TRUE;
2258 sig->hasthis = TRUE;
2259 for (i = 0; i < klass->rank + 1; ++i)
2260 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2261 amethod = create_array_method (klass, ".ctor", sig);
2262 methods [method_num++] = amethod;
2265 /* element Get (idx11, [idx2, ...]) */
2266 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2267 sig->ret = &klass->element_class->byval_arg;
2268 sig->pinvoke = TRUE;
2269 sig->hasthis = TRUE;
2270 for (i = 0; i < klass->rank; ++i)
2271 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2272 amethod = create_array_method (klass, "Get", sig);
2273 methods [method_num++] = amethod;
2274 /* element& Address (idx11, [idx2, ...]) */
2275 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2276 sig->ret = &klass->element_class->this_arg;
2277 sig->pinvoke = TRUE;
2278 sig->hasthis = TRUE;
2279 for (i = 0; i < klass->rank; ++i)
2280 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2281 amethod = create_array_method (klass, "Address", sig);
2282 methods [method_num++] = amethod;
2283 /* void Set (idx11, [idx2, ...], element) */
2284 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2285 sig->ret = &mono_defaults.void_class->byval_arg;
2286 sig->pinvoke = TRUE;
2287 sig->hasthis = TRUE;
2288 for (i = 0; i < klass->rank; ++i)
2289 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2290 sig->params [i] = &klass->element_class->byval_arg;
2291 amethod = create_array_method (klass, "Set", sig);
2292 methods [method_num++] = amethod;
2294 for (i = 0; i < klass->interface_count; i++)
2295 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2299 count = klass->method.count;
2300 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2301 for (i = 0; i < count; ++i) {
2302 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2303 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2305 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)));
2306 mono_error_cleanup (&error);
2311 if (MONO_CLASS_IS_INTERFACE (klass)) {
2313 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2314 for (i = 0; i < count; ++i) {
2315 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2316 methods [i]->slot = slot++;
2320 mono_image_lock (klass->image);
2322 if (!klass->methods) {
2323 klass->method.count = count;
2325 /* Needed because of the double-checking locking pattern */
2326 mono_memory_barrier ();
2328 klass->methods = methods;
2331 mono_image_unlock (klass->image);
2335 * mono_class_get_method_by_index:
2337 * Returns klass->methods [index], initializing klass->methods if neccesary.
2339 * LOCKING: Acquires the loader lock.
2342 mono_class_get_method_by_index (MonoClass *klass, int index)
2345 /* Avoid calling setup_methods () if possible */
2346 if (klass->generic_class && !klass->methods) {
2347 MonoClass *gklass = klass->generic_class->container_class;
2350 m = mono_class_inflate_generic_method_full_checked (
2351 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2352 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2354 * If setup_methods () is called later for this class, no duplicates are created,
2355 * since inflate_generic_method guarantees that only one instance of a method
2356 * is created for each context.
2359 mono_class_setup_methods (klass);
2360 g_assert (m == klass->methods [index]);
2364 mono_class_setup_methods (klass);
2365 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2367 g_assert (index >= 0 && index < klass->method.count);
2368 return klass->methods [index];
2373 * mono_class_get_inflated_method:
2375 * Given an inflated class CLASS and a method METHOD which should be a method of
2376 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2379 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2381 MonoClass *gklass = klass->generic_class->container_class;
2384 g_assert (method->klass == gklass);
2386 mono_class_setup_methods (gklass);
2387 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2389 for (i = 0; i < gklass->method.count; ++i) {
2390 if (gklass->methods [i] == method) {
2391 if (klass->methods) {
2392 return klass->methods [i];
2395 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2396 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2406 * mono_class_get_vtable_entry:
2408 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2409 * LOCKING: Acquires the loader lock.
2412 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2416 if (klass->rank == 1) {
2418 * szarrays do not overwrite any methods of Array, so we can avoid
2419 * initializing their vtables in some cases.
2421 mono_class_setup_vtable (klass->parent);
2422 if (offset < klass->parent->vtable_size)
2423 return klass->parent->vtable [offset];
2426 if (klass->generic_class) {
2428 MonoClass *gklass = klass->generic_class->container_class;
2429 mono_class_setup_vtable (gklass);
2430 m = gklass->vtable [offset];
2432 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2433 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2435 mono_class_setup_vtable (klass);
2436 if (mono_class_has_failure (klass))
2438 m = klass->vtable [offset];
2445 * mono_class_get_vtable_size:
2447 * Return the vtable size for KLASS.
2450 mono_class_get_vtable_size (MonoClass *klass)
2452 mono_class_setup_vtable (klass);
2454 return klass->vtable_size;
2458 * mono_class_setup_properties:
2460 * Initialize klass->ext.property and klass->ext.properties.
2462 * This method can fail the class.
2465 mono_class_setup_properties (MonoClass *klass)
2467 guint startm, endm, i, j;
2468 guint32 cols [MONO_PROPERTY_SIZE];
2469 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2470 MonoProperty *properties;
2474 if (klass->ext && klass->ext->properties)
2477 if (klass->generic_class) {
2478 MonoClass *gklass = klass->generic_class->container_class;
2480 mono_class_init (gklass);
2481 mono_class_setup_properties (gklass);
2482 if (mono_class_has_failure (gklass)) {
2483 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2487 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2489 for (i = 0; i < gklass->ext->property.count; i++) {
2491 MonoProperty *prop = &properties [i];
2493 *prop = gklass->ext->properties [i];
2496 prop->get = mono_class_inflate_generic_method_full_checked (
2497 prop->get, klass, mono_class_get_context (klass), &error);
2499 prop->set = mono_class_inflate_generic_method_full_checked (
2500 prop->set, klass, mono_class_get_context (klass), &error);
2502 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2503 prop->parent = klass;
2506 first = gklass->ext->property.first;
2507 count = gklass->ext->property.count;
2509 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2510 count = last - first;
2513 mono_class_setup_methods (klass);
2514 if (mono_class_has_failure (klass))
2518 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2519 for (i = first; i < last; ++i) {
2520 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2521 properties [i - first].parent = klass;
2522 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2523 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2525 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2526 for (j = startm; j < endm; ++j) {
2529 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2531 if (klass->image->uncompressed_metadata) {
2533 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2534 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2535 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2537 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2540 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2541 case METHOD_SEMANTIC_SETTER:
2542 properties [i - first].set = method;
2544 case METHOD_SEMANTIC_GETTER:
2545 properties [i - first].get = method;
2554 mono_class_alloc_ext (klass);
2556 mono_image_lock (klass->image);
2558 if (klass->ext->properties) {
2559 /* We leak 'properties' which was allocated from the image mempool */
2560 mono_image_unlock (klass->image);
2564 klass->ext->property.first = first;
2565 klass->ext->property.count = count;
2567 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2568 mono_memory_barrier ();
2570 /* Leave this assignment as the last op in the function */
2571 klass->ext->properties = properties;
2573 mono_image_unlock (klass->image);
2577 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2579 MonoMethod **om, **retval;
2582 for (om = methods, count = 0; *om; ++om, ++count)
2585 retval = g_new0 (MonoMethod*, count + 1);
2587 for (om = methods, count = 0; *om; ++om, ++count) {
2589 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2590 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2596 /*This method can fail the class.*/
2598 mono_class_setup_events (MonoClass *klass)
2601 guint startm, endm, i, j;
2602 guint32 cols [MONO_EVENT_SIZE];
2603 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2607 if (klass->ext && klass->ext->events)
2610 if (klass->generic_class) {
2611 MonoClass *gklass = klass->generic_class->container_class;
2612 MonoGenericContext *context = NULL;
2614 mono_class_setup_events (gklass);
2615 if (mono_class_has_failure (gklass)) {
2616 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2620 first = gklass->ext->event.first;
2621 count = gklass->ext->event.count;
2623 events = mono_class_new0 (klass, MonoEvent, count);
2626 context = mono_class_get_context (klass);
2628 for (i = 0; i < count; i++) {
2630 MonoEvent *event = &events [i];
2631 MonoEvent *gevent = &gklass->ext->events [i];
2633 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2635 event->parent = klass;
2636 event->name = gevent->name;
2637 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2638 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2639 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2640 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2641 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2642 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2644 #ifndef MONO_SMALL_CONFIG
2645 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2647 event->attrs = gevent->attrs;
2650 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2651 count = last - first;
2654 mono_class_setup_methods (klass);
2655 if (mono_class_has_failure (klass)) {
2656 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2661 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2662 for (i = first; i < last; ++i) {
2663 MonoEvent *event = &events [i - first];
2665 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2666 event->parent = klass;
2667 event->attrs = cols [MONO_EVENT_FLAGS];
2668 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2670 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2671 for (j = startm; j < endm; ++j) {
2674 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2676 if (klass->image->uncompressed_metadata) {
2678 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2679 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2680 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2682 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2685 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2686 case METHOD_SEMANTIC_ADD_ON:
2687 event->add = method;
2689 case METHOD_SEMANTIC_REMOVE_ON:
2690 event->remove = method;
2692 case METHOD_SEMANTIC_FIRE:
2693 event->raise = method;
2695 case METHOD_SEMANTIC_OTHER: {
2696 #ifndef MONO_SMALL_CONFIG
2699 if (event->other == NULL) {
2700 event->other = g_new0 (MonoMethod*, 2);
2702 while (event->other [n])
2704 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2706 event->other [n] = method;
2707 /* NULL terminated */
2708 event->other [n + 1] = NULL;
2719 mono_class_alloc_ext (klass);
2721 mono_image_lock (klass->image);
2723 if (klass->ext->events) {
2724 mono_image_unlock (klass->image);
2728 klass->ext->event.first = first;
2729 klass->ext->event.count = count;
2731 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2732 mono_memory_barrier ();
2734 /* Leave this assignment as the last op in the function */
2735 klass->ext->events = events;
2737 mono_image_unlock (klass->image);
2741 * Global pool of interface IDs, represented as a bitset.
2742 * LOCKING: Protected by the classes lock.
2744 static MonoBitSet *global_interface_bitset = NULL;
2747 * mono_unload_interface_ids:
2748 * @bitset: bit set of interface IDs
2750 * When an image is unloaded, the interface IDs associated with
2751 * the image are put back in the global pool of IDs so the numbers
2755 mono_unload_interface_ids (MonoBitSet *bitset)
2758 mono_bitset_sub (global_interface_bitset, bitset);
2763 mono_unload_interface_id (MonoClass *klass)
2765 if (global_interface_bitset && klass->interface_id) {
2767 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2773 * mono_get_unique_iid:
2776 * Assign a unique integer ID to the interface represented by @class.
2777 * The ID will positive and as small as possible.
2778 * LOCKING: Acquires the classes lock.
2779 * Returns: The new ID.
2782 mono_get_unique_iid (MonoClass *klass)
2786 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2790 if (!global_interface_bitset) {
2791 global_interface_bitset = mono_bitset_new (128, 0);
2794 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2796 int old_size = mono_bitset_size (global_interface_bitset);
2797 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2798 mono_bitset_free (global_interface_bitset);
2799 global_interface_bitset = new_set;
2802 mono_bitset_set (global_interface_bitset, iid);
2803 /* set the bit also in the per-image set */
2804 if (!klass->generic_class) {
2805 if (klass->image->interface_bitset) {
2806 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2807 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2808 mono_bitset_free (klass->image->interface_bitset);
2809 klass->image->interface_bitset = new_set;
2812 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2814 mono_bitset_set (klass->image->interface_bitset, iid);
2819 #ifndef MONO_SMALL_CONFIG
2820 if (mono_print_vtable) {
2822 char *type_name = mono_type_full_name (&klass->byval_arg);
2823 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2824 generic_id = klass->generic_class->context.class_inst->id;
2825 g_assert (generic_id != 0);
2829 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2834 g_assert (iid <= 65535);
2839 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2844 mono_class_setup_interfaces (klass, error);
2845 return_if_nok (error);
2847 for (i = 0; i < klass->interface_count; i++) {
2848 ic = klass->interfaces [i];
2851 *res = g_ptr_array_new ();
2852 g_ptr_array_add (*res, ic);
2853 mono_class_init (ic);
2854 if (mono_class_has_failure (ic)) {
2855 mono_error_set_type_load_class (error, ic, "Error Loading class");
2859 collect_implemented_interfaces_aux (ic, res, error);
2860 return_if_nok (error);
2865 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2867 GPtrArray *res = NULL;
2869 collect_implemented_interfaces_aux (klass, &res, error);
2870 if (!mono_error_ok (error)) {
2872 g_ptr_array_free (res, TRUE);
2879 compare_interface_ids (const void *p_key, const void *p_element) {
2880 const MonoClass *key = (const MonoClass *)p_key;
2881 const MonoClass *element = *(const MonoClass **)p_element;
2883 return (key->interface_id - element->interface_id);
2886 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2888 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2889 MonoClass **result = (MonoClass **)mono_binary_search (
2891 klass->interfaces_packed,
2892 klass->interface_offsets_count,
2893 sizeof (MonoClass *),
2894 compare_interface_ids);
2896 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2903 * mono_class_interface_offset_with_variance:
2905 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2906 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2908 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2910 * FIXME figure out MS disambiguation rules and fix this function.
2913 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2914 int i = mono_class_interface_offset (klass, itf);
2915 *non_exact_match = FALSE;
2919 if (!mono_class_has_variant_generic_params (itf))
2922 for (i = 0; i < klass->interface_offsets_count; i++) {
2923 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2924 *non_exact_match = TRUE;
2925 return klass->interface_offsets_packed [i];
2933 print_implemented_interfaces (MonoClass *klass) {
2936 GPtrArray *ifaces = NULL;
2938 int ancestor_level = 0;
2940 name = mono_type_get_full_name (klass);
2941 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2944 for (i = 0; i < klass->interface_offsets_count; i++)
2945 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2946 klass->interfaces_packed [i]->interface_id,
2947 klass->interface_offsets_packed [i],
2948 klass->interfaces_packed [i]->method.count,
2949 klass->interfaces_packed [i]->name_space,
2950 klass->interfaces_packed [i]->name );
2951 printf ("Interface flags: ");
2952 for (i = 0; i <= klass->max_interface_id; i++)
2953 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2954 printf ("(%d,T)", i);
2956 printf ("(%d,F)", i);
2958 printf ("Dump interface flags:");
2959 #ifdef COMPRESSED_INTERFACE_BITMAP
2961 const uint8_t* p = klass->interface_bitmap;
2962 i = klass->max_interface_id;
2964 printf (" %d x 00 %02X", p [0], p [1]);
2970 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2971 printf (" %02X", klass->interface_bitmap [i]);
2974 while (klass != NULL) {
2975 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2976 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2977 if (!mono_error_ok (&error)) {
2978 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2979 mono_error_cleanup (&error);
2980 } else if (ifaces) {
2981 for (i = 0; i < ifaces->len; i++) {
2982 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2983 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2984 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2986 mono_class_interface_offset (klass, ic),
2991 g_ptr_array_free (ifaces, TRUE);
2994 klass = klass->parent;
2999 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3002 args [0] = &arg0->byval_arg;
3004 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3008 array_class_get_if_rank (MonoClass *klass, guint rank)
3010 return rank ? mono_array_class_get (klass, rank) : klass;
3014 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3016 valuetype_types [0] = eclass;
3017 if (eclass == mono_defaults.int16_class)
3018 valuetype_types [1] = mono_defaults.uint16_class;
3019 else if (eclass == mono_defaults.uint16_class)
3020 valuetype_types [1] = mono_defaults.int16_class;
3021 else if (eclass == mono_defaults.int32_class)
3022 valuetype_types [1] = mono_defaults.uint32_class;
3023 else if (eclass == mono_defaults.uint32_class)
3024 valuetype_types [1] = mono_defaults.int32_class;
3025 else if (eclass == mono_defaults.int64_class)
3026 valuetype_types [1] = mono_defaults.uint64_class;
3027 else if (eclass == mono_defaults.uint64_class)
3028 valuetype_types [1] = mono_defaults.int64_class;
3029 else if (eclass == mono_defaults.byte_class)
3030 valuetype_types [1] = mono_defaults.sbyte_class;
3031 else if (eclass == mono_defaults.sbyte_class)
3032 valuetype_types [1] = mono_defaults.byte_class;
3033 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3034 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3037 /* this won't be needed once bug #325495 is completely fixed
3038 * though we'll need something similar to know which interfaces to allow
3039 * in arrays when they'll be lazyly created
3041 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3042 * MS returns diferrent types based on which instance is called. For example:
3043 * object obj = new byte[10][];
3044 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3045 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3048 * Fixing this should kill quite some code, save some bits and improve compatibility.
3051 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3053 MonoClass *eclass = klass->element_class;
3054 static MonoClass* generic_icollection_class = NULL;
3055 static MonoClass* generic_ienumerable_class = NULL;
3056 static MonoClass* generic_ienumerator_class = NULL;
3057 static MonoClass* generic_ireadonlylist_class = NULL;
3058 static MonoClass* generic_ireadonlycollection_class = NULL;
3059 MonoClass *valuetype_types[2] = { NULL, NULL };
3060 MonoClass **interfaces = NULL;
3061 int i, nifaces, interface_count, real_count, original_rank;
3063 gboolean internal_enumerator;
3064 gboolean eclass_is_valuetype;
3066 if (!mono_defaults.generic_ilist_class) {
3070 internal_enumerator = FALSE;
3071 eclass_is_valuetype = FALSE;
3072 original_rank = eclass->rank;
3073 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3074 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3076 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3078 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3079 original_rank = eclass->rank;
3081 eclass = eclass->element_class;
3082 internal_enumerator = TRUE;
3083 *is_enumerator = TRUE;
3091 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3092 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3094 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3096 if (!generic_icollection_class) {
3097 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3098 "System.Collections.Generic", "ICollection`1");
3099 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3100 "System.Collections.Generic", "IEnumerable`1");
3101 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3102 "System.Collections.Generic", "IEnumerator`1");
3103 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3104 "System.Collections.Generic", "IReadOnlyList`1");
3105 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3106 "System.Collections.Generic", "IReadOnlyCollection`1");
3109 mono_class_init (eclass);
3112 * Arrays in 2.0 need to implement a number of generic interfaces
3113 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3114 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3115 * We collect the types needed to build the
3116 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3117 * the generic interfaces needed to implement.
3119 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3120 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3122 if (eclass->valuetype) {
3123 nifaces = generic_ireadonlylist_class ? 5 : 3;
3124 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3126 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3127 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3128 if (internal_enumerator) {
3130 if (valuetype_types [1])
3134 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3135 interfaces [0] = valuetype_types [0];
3136 if (valuetype_types [1])
3137 interfaces [nifaces] = valuetype_types [1];
3139 eclass_is_valuetype = TRUE;
3142 int idepth = eclass->idepth;
3143 if (!internal_enumerator)
3145 nifaces = generic_ireadonlylist_class ? 2 : 3;
3147 // FIXME: This doesn't seem to work/required for generic params
3148 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3149 mono_class_setup_interface_offsets (eclass);
3151 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3152 /* we add object for interfaces and the supertypes for the other
3153 * types. The last of the supertypes is the element class itself which we
3154 * already created the explicit interfaces for (so we include it for IEnumerator
3155 * and exclude it for arrays).
3157 if (MONO_CLASS_IS_INTERFACE (eclass))
3160 interface_count += idepth;
3161 if (eclass->rank && eclass->element_class->valuetype) {
3162 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3163 if (valuetype_types [1])
3166 /* IList, ICollection, IEnumerable, IReadOnlyList */
3167 interface_count *= nifaces;
3168 real_count = interface_count;
3169 if (internal_enumerator) {
3170 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3171 if (valuetype_types [1])
3174 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3175 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3176 interfaces [0] = mono_defaults.object_class;
3180 for (i = 0; i < idepth; i++) {
3181 mono_class_init (eclass->supertypes [i]);
3182 interfaces [j] = eclass->supertypes [i];
3186 if (all_interfaces) {
3187 for (i = 0; i < eclass->interface_offsets_count; i++) {
3188 interfaces [j] = eclass->interfaces_packed [i];
3192 for (i = 0; i < eclass->interface_count; i++) {
3193 interfaces [j] = eclass->interfaces [i];
3197 if (valuetype_types [1]) {
3198 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3203 /* instantiate the generic interfaces */
3204 for (i = 0; i < interface_count; i += nifaces) {
3205 MonoClass *iface = interfaces [i];
3207 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3208 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3210 if (eclass->valuetype) {
3211 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3212 if (generic_ireadonlylist_class) {
3213 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3214 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3217 if (!generic_ireadonlylist_class)
3218 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3221 if (internal_enumerator) {
3223 /* instantiate IEnumerator<iface> */
3224 for (i = 0; i < interface_count; i++) {
3225 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3227 j = interface_count;
3228 if (!eclass_is_valuetype) {
3229 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3230 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3233 for (i = 0; i < eclass->idepth; i++) {
3234 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3238 for (i = 0; i < eclass->interface_offsets_count; i++) {
3239 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3243 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3245 if (valuetype_types [1])
3246 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3250 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3251 for (i = 0; i < real_count; ++i) {
3252 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3253 g_print ("%s implements %s\n", type_name, name);
3264 find_array_interface (MonoClass *klass, const char *name)
3267 for (i = 0; i < klass->interface_count; ++i) {
3268 if (strcmp (klass->interfaces [i]->name, name) == 0)
3275 * Return the number of virtual methods.
3276 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3277 * Return -1 on failure.
3278 * FIXME It would be nice if this information could be cached somewhere.
3281 count_virtual_methods (MonoClass *klass)
3285 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3287 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3288 mono_class_setup_methods (klass);
3289 if (mono_class_has_failure (klass))
3292 for (i = 0; i < klass->method.count; ++i) {
3293 flags = klass->methods [i]->flags;
3294 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3298 for (i = 0; i < klass->method.count; ++i) {
3299 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3301 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3309 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3317 m = (l + num_ifaces) / 2;
3318 if (interfaces_full [m] == ic)
3320 if (l == num_ifaces)
3322 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3331 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3333 int i = find_interface (num_ifaces, interfaces_full, ic);
3335 return interface_offsets_full [i];
3340 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3342 int i = find_interface (num_ifaces, interfaces_full, ic);
3346 interface_offsets_full [i] = offset;
3349 for (i = 0; i < num_ifaces; ++i) {
3350 if (interfaces_full [i]) {
3352 if (interfaces_full [i]->interface_id < ic->interface_id)
3355 while (end < num_ifaces && interfaces_full [end]) end++;
3356 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3357 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3359 interfaces_full [i] = ic;
3360 interface_offsets_full [i] = offset;
3366 #ifdef COMPRESSED_INTERFACE_BITMAP
3369 * Compressed interface bitmap design.
3371 * Interface bitmaps take a large amount of memory, because their size is
3372 * linear with the maximum interface id assigned in the process (each interface
3373 * is assigned a unique id as it is loaded). The number of interface classes
3374 * is high because of the many implicit interfaces implemented by arrays (we'll
3375 * need to lazy-load them in the future).
3376 * Most classes implement a very small number of interfaces, so the bitmap is
3377 * sparse. This bitmap needs to be checked by interface casts, so access to the
3378 * needed bit must be fast and doable with few jit instructions.
3380 * The current compression format is as follows:
3381 * *) it is a sequence of one or more two-byte elements
3382 * *) the first byte in the element is the count of empty bitmap bytes
3383 * at the current bitmap position
3384 * *) the second byte in the element is an actual bitmap byte at the current
3387 * As an example, the following compressed bitmap bytes:
3388 * 0x07 0x01 0x00 0x7
3389 * correspond to the following bitmap:
3390 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3392 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3393 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3394 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3398 * mono_compress_bitmap:
3399 * @dest: destination buffer
3400 * @bitmap: bitmap buffer
3401 * @size: size of @bitmap in bytes
3403 * This is a mono internal function.
3404 * The @bitmap data is compressed into a format that is small but
3405 * still searchable in few instructions by the JIT and runtime.
3406 * The compressed data is stored in the buffer pointed to by the
3407 * @dest array. Passing a #NULL value for @dest allows to just compute
3408 * the size of the buffer.
3409 * This compression algorithm assumes the bits set in the bitmap are
3410 * few and far between, like in interface bitmaps.
3411 * Returns: The size of the compressed bitmap in bytes.
3414 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3418 const uint8_t *end = bitmap + size;
3419 while (bitmap < end) {
3420 if (*bitmap || numz == 255) {
3444 * mono_class_interface_match:
3445 * @bitmap: a compressed bitmap buffer
3446 * @id: the index to check in the bitmap
3448 * This is a mono internal function.
3449 * Checks if a bit is set in a compressed interface bitmap. @id must
3450 * be already checked for being smaller than the maximum id encoded in the
3453 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3457 mono_class_interface_match (const uint8_t *bitmap, int id)
3460 id -= bitmap [0] * 8;
3464 return bitmap [1] & (1 << id);
3473 * LOCKING: this is supposed to be called with the loader lock held.
3474 * Return -1 on failure and set exception_type
3477 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3481 int i, j, max_iid, num_ifaces;
3482 MonoClass **interfaces_full = NULL;
3483 int *interface_offsets_full = NULL;
3485 GPtrArray **ifaces_array = NULL;
3486 int interface_offsets_count;
3487 MonoClass **array_interfaces = NULL;
3488 int num_array_interfaces;
3489 int is_enumerator = FALSE;
3491 mono_class_setup_supertypes (klass);
3493 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3494 * implicit interfaces have the property that they are assigned the same slot in the
3495 * vtables for compatible interfaces
3497 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3499 /* compute maximum number of slots and maximum interface id */
3501 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3502 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3503 for (j = 0; j < klass->idepth; j++) {
3504 k = klass->supertypes [j];
3505 num_ifaces += k->interface_count;
3506 for (i = 0; i < k->interface_count; i++) {
3507 ic = k->interfaces [i];
3510 mono_class_init (ic);
3512 if (max_iid < ic->interface_id)
3513 max_iid = ic->interface_id;
3515 ifaces = mono_class_get_implemented_interfaces (k, &error);
3516 if (!mono_error_ok (&error)) {
3517 char *name = mono_type_get_full_name (k);
3518 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)));
3520 mono_error_cleanup (&error);
3525 num_ifaces += ifaces->len;
3526 for (i = 0; i < ifaces->len; ++i) {
3527 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3528 if (max_iid < ic->interface_id)
3529 max_iid = ic->interface_id;
3531 ifaces_array [j] = ifaces;
3535 for (i = 0; i < num_array_interfaces; ++i) {
3536 ic = array_interfaces [i];
3537 mono_class_init (ic);
3538 if (max_iid < ic->interface_id)
3539 max_iid = ic->interface_id;
3542 if (MONO_CLASS_IS_INTERFACE (klass)) {
3544 if (max_iid < klass->interface_id)
3545 max_iid = klass->interface_id;
3547 klass->max_interface_id = max_iid;
3548 /* compute vtable offset for interfaces */
3549 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3550 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3552 for (i = 0; i < num_ifaces; i++) {
3553 interface_offsets_full [i] = -1;
3556 /* skip the current class */
3557 for (j = 0; j < klass->idepth - 1; j++) {
3558 k = klass->supertypes [j];
3559 ifaces = ifaces_array [j];
3562 for (i = 0; i < ifaces->len; ++i) {
3564 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3566 /*Force the sharing of interface offsets between parent and subtypes.*/
3567 io = mono_class_interface_offset (k, ic);
3569 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3574 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3575 ifaces = ifaces_array [klass->idepth - 1];
3577 for (i = 0; i < ifaces->len; ++i) {
3579 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3580 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3582 count = count_virtual_methods (ic);
3584 char *name = mono_type_get_full_name (ic);
3585 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3594 if (MONO_CLASS_IS_INTERFACE (klass))
3595 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3597 if (num_array_interfaces) {
3598 if (is_enumerator) {
3599 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3600 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3601 g_assert (ienumerator_offset >= 0);
3602 for (i = 0; i < num_array_interfaces; ++i) {
3603 ic = array_interfaces [i];
3604 if (strcmp (ic->name, "IEnumerator`1") == 0)
3605 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3607 g_assert_not_reached ();
3608 /*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);*/
3611 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3612 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3613 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3614 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3615 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3616 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3617 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3618 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3619 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3620 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3621 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3622 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3623 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3624 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3625 for (i = 0; i < num_array_interfaces; ++i) {
3627 ic = array_interfaces [i];
3628 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3629 offset = ilist_offset;
3630 else if (strcmp (ic->name, "ICollection`1") == 0)
3631 offset = icollection_offset;
3632 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3633 offset = ienumerable_offset;
3634 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3635 offset = ireadonlylist_offset;
3636 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3637 offset = ireadonlycollection_offset;
3639 g_assert_not_reached ();
3640 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3641 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3646 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3647 if (interface_offsets_full [i] != -1) {
3648 interface_offsets_count ++;
3653 * We might get called multiple times:
3654 * - mono_class_init ()
3655 * - mono_class_setup_vtable ().
3656 * - mono_class_setup_interface_offsets ().
3657 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3658 * means we have to overwrite those when called from other places (#4440).
3660 if (klass->interfaces_packed) {
3662 g_assert (klass->interface_offsets_count == interface_offsets_count);
3666 klass->interface_offsets_count = interface_offsets_count;
3667 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3668 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3669 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3670 #ifdef COMPRESSED_INTERFACE_BITMAP
3671 bitmap = g_malloc0 (bsize);
3673 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3675 for (i = 0; i < interface_offsets_count; i++) {
3676 int id = interfaces_full [i]->interface_id;
3677 bitmap [id >> 3] |= (1 << (id & 7));
3678 klass->interfaces_packed [i] = interfaces_full [i];
3679 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3680 /*if (num_array_interfaces)
3681 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]);*/
3683 #ifdef COMPRESSED_INTERFACE_BITMAP
3684 i = mono_compress_bitmap (NULL, bitmap, bsize);
3685 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3686 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3689 klass->interface_bitmap = bitmap;
3694 g_free (interfaces_full);
3695 g_free (interface_offsets_full);
3696 g_free (array_interfaces);
3697 for (i = 0; i < klass->idepth; i++) {
3698 ifaces = ifaces_array [i];
3700 g_ptr_array_free (ifaces, TRUE);
3702 g_free (ifaces_array);
3704 //printf ("JUST DONE: ");
3705 //print_implemented_interfaces (klass);
3711 * Setup interface offsets for interfaces.
3713 * - klass->max_interface_id
3714 * - klass->interface_offsets_count
3715 * - klass->interfaces_packed
3716 * - klass->interface_offsets_packed
3717 * - klass->interface_bitmap
3719 * This function can fail @class.
3722 mono_class_setup_interface_offsets (MonoClass *klass)
3724 mono_loader_lock ();
3726 setup_interface_offsets (klass, 0, FALSE);
3728 mono_loader_unlock ();
3731 /*Checks if @klass has @parent as one of it's parents type gtd
3735 * Bar<T> : Foo<Bar<Bar<T>>>
3739 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3741 klass = mono_class_get_generic_type_definition (klass);
3742 parent = mono_class_get_generic_type_definition (parent);
3743 mono_class_setup_supertypes (klass);
3744 mono_class_setup_supertypes (parent);
3746 return klass->idepth >= parent->idepth &&
3747 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3751 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3753 MonoGenericInst *ginst;
3755 if (!klass->generic_class) {
3756 mono_class_setup_vtable_full (klass, in_setup);
3757 return !mono_class_has_failure (klass);
3760 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3761 if (mono_class_has_failure (klass->generic_class->container_class)) {
3762 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3766 ginst = klass->generic_class->context.class_inst;
3767 for (i = 0; i < ginst->type_argc; ++i) {
3769 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3771 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3772 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3773 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3775 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3776 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3784 * mono_class_setup_vtable:
3786 * Creates the generic vtable of CLASS.
3787 * Initializes the following fields in MonoClass:
3790 * Plus all the fields initialized by setup_interface_offsets ().
3791 * If there is an error during vtable construction, klass->exception_type is set.
3793 * LOCKING: Acquires the loader lock.
3796 mono_class_setup_vtable (MonoClass *klass)
3798 mono_class_setup_vtable_full (klass, NULL);
3802 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3805 MonoMethod **overrides;
3806 MonoGenericContext *context;
3814 if (MONO_CLASS_IS_INTERFACE (klass)) {
3815 /* This sets method->slot for all methods if this is an interface */
3816 mono_class_setup_methods (klass);
3820 if (mono_class_has_failure (klass))
3823 if (g_list_find (in_setup, klass))
3826 mono_loader_lock ();
3828 if (klass->vtable) {
3829 mono_loader_unlock ();
3833 mono_stats.generic_vtable_count ++;
3834 in_setup = g_list_prepend (in_setup, klass);
3836 if (klass->generic_class) {
3837 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3838 mono_loader_unlock ();
3839 g_list_remove (in_setup, klass);
3843 context = mono_class_get_context (klass);
3844 type_token = klass->generic_class->container_class->type_token;
3846 context = (MonoGenericContext *) klass->generic_container;
3847 type_token = klass->type_token;
3850 if (image_is_dynamic (klass->image)) {
3851 /* Generic instances can have zero method overrides without causing any harm.
3852 * This is true since we don't do layout all over again for them, we simply inflate
3853 * the layout of the parent.
3855 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3856 if (!is_ok (&error)) {
3857 mono_loader_unlock ();
3858 g_list_remove (in_setup, klass);
3859 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
3860 mono_error_cleanup (&error);
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_create_from_typedef:
5739 * @image: image where the token is valid
5740 * @type_token: typedef token
5741 * @error: used to return any error found while creating the type
5743 * Create the MonoClass* representing the specified type token.
5744 * @type_token must be a TypeDef token.
5746 * FIXME: don't return NULL on failure, just the the caller figure it out.
5749 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5751 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5752 MonoClass *klass, *parent = NULL;
5753 guint32 cols [MONO_TYPEDEF_SIZE];
5754 guint32 cols_next [MONO_TYPEDEF_SIZE];
5755 guint tidx = mono_metadata_token_index (type_token);
5756 MonoGenericContext *context = NULL;
5757 const char *name, *nspace;
5759 MonoClass **interfaces;
5760 guint32 field_last, method_last;
5761 guint32 nesting_tokeen;
5763 mono_error_init (error);
5765 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5766 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5767 mono_loader_assert_no_error ();
5771 mono_loader_lock ();
5773 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5774 mono_loader_unlock ();
5775 mono_loader_assert_no_error ();
5779 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5781 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5782 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5784 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5787 klass->name_space = nspace;
5789 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5791 klass->image = image;
5792 klass->type_token = type_token;
5793 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5795 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5797 classes_size += sizeof (MonoClass);
5800 * Check whether we're a generic type definition.
5802 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5803 if (klass->generic_container) {
5804 klass->is_generic = 1;
5805 klass->generic_container->owner.klass = klass;
5806 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5807 context = &klass->generic_container->context;
5810 if (klass->generic_container)
5811 enable_gclass_recording ();
5813 if (cols [MONO_TYPEDEF_EXTENDS]) {
5815 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5817 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5818 /*WARNING: this must satisfy mono_metadata_type_hash*/
5819 klass->this_arg.byref = 1;
5820 klass->this_arg.data.klass = klass;
5821 klass->this_arg.type = MONO_TYPE_CLASS;
5822 klass->byval_arg.data.klass = klass;
5823 klass->byval_arg.type = MONO_TYPE_CLASS;
5825 parent = mono_class_get_checked (image, parent_token, error);
5826 if (parent && context) /* Always inflate */
5827 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5829 if (parent == NULL) {
5830 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5831 goto parent_failure;
5834 for (tmp = parent; tmp; tmp = tmp->parent) {
5836 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5837 goto parent_failure;
5839 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5840 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5841 goto parent_failure;
5846 mono_class_setup_parent (klass, parent);
5848 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5849 mono_class_setup_mono_type (klass);
5851 if (klass->generic_container)
5852 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5855 * This might access klass->byval_arg for recursion generated by generic constraints,
5856 * so it has to come after setup_mono_type ().
5858 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5859 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5860 if (!mono_error_ok (error)) {
5861 /*FIXME implement a mono_class_set_failure_from_mono_error */
5862 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5863 mono_loader_unlock ();
5864 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5865 mono_loader_assert_no_error ();
5870 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5874 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5878 klass->cast_class = klass->element_class = klass;
5880 if (!klass->enumtype) {
5881 if (!mono_metadata_interfaces_from_typedef_full (
5882 image, type_token, &interfaces, &icount, FALSE, context, error)){
5884 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5885 mono_loader_unlock ();
5886 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5890 klass->interfaces = interfaces;
5891 klass->interface_count = icount;
5892 klass->interfaces_inited = 1;
5895 /*g_print ("Load class %s\n", name);*/
5898 * Compute the field and method lists
5900 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5901 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5903 if (tt->rows > tidx){
5904 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5905 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5906 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5908 field_last = image->tables [MONO_TABLE_FIELD].rows;
5909 method_last = image->tables [MONO_TABLE_METHOD].rows;
5912 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5913 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5914 klass->field.count = field_last - klass->field.first;
5916 klass->field.count = 0;
5918 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5919 klass->method.count = method_last - klass->method.first;
5921 klass->method.count = 0;
5923 /* reserve space to store vector pointer in arrays */
5924 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5925 klass->instance_size += 2 * sizeof (gpointer);
5926 g_assert (klass->field.count == 0);
5929 if (klass->enumtype) {
5930 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5931 if (!enum_basetype) {
5932 /*set it to a default value as the whole runtime can't handle this to be null*/
5933 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5934 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5935 mono_loader_unlock ();
5936 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5937 mono_loader_assert_no_error ();
5940 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5944 * If we're a generic type definition, load the constraints.
5945 * We must do this after the class has been constructed to make certain recursive scenarios
5948 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5949 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)));
5950 mono_loader_unlock ();
5951 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5952 mono_loader_assert_no_error ();
5956 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5957 if (!strncmp (name, "Vector", 6))
5958 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");
5961 mono_loader_unlock ();
5963 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5964 mono_loader_assert_no_error ();
5969 mono_class_setup_mono_type (klass);
5970 mono_loader_unlock ();
5971 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5972 mono_loader_assert_no_error ();
5976 /** Is klass a Nullable<T> ginst? */
5978 mono_class_is_nullable (MonoClass *klass)
5980 return klass->generic_class != NULL &&
5981 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5985 /** if klass is T? return T */
5987 mono_class_get_nullable_param (MonoClass *klass)
5989 g_assert (mono_class_is_nullable (klass));
5990 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5994 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5998 MonoGenericClass *gclass = klass->generic_class;
6000 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6001 if (!mono_error_ok (&error)) {
6002 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6003 klass->parent = mono_defaults.object_class;
6004 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6005 mono_error_cleanup (&error);
6009 mono_class_setup_parent (klass, klass->parent);
6011 if (klass->enumtype) {
6012 klass->cast_class = gtd->cast_class;
6013 klass->element_class = gtd->element_class;
6019 * Create the `MonoClass' for an instantiation of a generic type.
6020 * We only do this if we actually need it.
6023 mono_generic_class_get_class (MonoGenericClass *gclass)
6025 MonoClass *klass, *gklass;
6027 if (gclass->cached_class)
6028 return gclass->cached_class;
6030 mono_loader_lock ();
6031 if (gclass->cached_class) {
6032 mono_loader_unlock ();
6033 return gclass->cached_class;
6036 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6038 gklass = gclass->container_class;
6040 if (record_gclass_instantiation > 0)
6041 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6043 if (gklass->nested_in) {
6044 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6045 klass->nested_in = gklass->nested_in;
6048 klass->name = gklass->name;
6049 klass->name_space = gklass->name_space;
6051 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6053 klass->image = gklass->image;
6054 klass->flags = gklass->flags;
6055 klass->type_token = gklass->type_token;
6056 klass->field.count = gklass->field.count;
6058 klass->is_inflated = 1;
6059 klass->generic_class = gclass;
6061 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6062 klass->this_arg.type = klass->byval_arg.type;
6063 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6064 klass->this_arg.byref = TRUE;
6065 klass->enumtype = gklass->enumtype;
6066 klass->valuetype = gklass->valuetype;
6068 klass->cast_class = klass->element_class = klass;
6070 if (mono_class_is_nullable (klass))
6071 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6074 * We're not interested in the nested classes of a generic instance.
6075 * We use the generic type definition to look for nested classes.
6078 mono_generic_class_setup_parent (klass, gklass);
6080 if (gclass->is_dynamic) {
6082 * 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.
6083 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6084 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6086 if (!gklass->wastypebuilder)
6089 mono_class_setup_supertypes (klass);
6091 if (klass->enumtype) {
6093 * For enums, gklass->fields might not been set, but instance_size etc. is
6094 * already set in mono_reflection_create_internal_class (). For non-enums,
6095 * these will be computed normally in mono_class_layout_fields ().
6097 klass->instance_size = gklass->instance_size;
6098 klass->sizes.class_size = gklass->sizes.class_size;
6099 mono_memory_barrier ();
6100 klass->size_inited = 1;
6104 mono_memory_barrier ();
6105 gclass->cached_class = klass;
6107 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6109 inflated_classes ++;
6110 inflated_classes_size += sizeof (MonoClass);
6112 mono_loader_unlock ();
6118 get_image_for_container (MonoGenericContainer *container)
6121 if (container->is_anonymous) {
6122 result = container->owner.image;
6125 if (container->is_method) {
6126 MonoMethod *method = container->owner.method;
6127 g_assert_checked (method);
6128 klass = method->klass;
6130 klass = container->owner.klass;
6132 g_assert_checked (klass);
6133 result = klass->image;
6140 get_image_for_generic_param (MonoGenericParam *param)
6142 MonoGenericContainer *container = mono_generic_param_owner (param);
6143 g_assert_checked (container);
6144 return get_image_for_container (container);
6147 // Make a string in the designated image consisting of a single integer.
6148 #define INT_STRING_SIZE 16
6150 make_generic_name_string (MonoImage *image, int num)
6152 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6153 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6157 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6158 // pinfo is derived from param by the caller for us.
6160 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6162 MonoClass *klass, **ptr;
6164 MonoGenericContainer *container = mono_generic_param_owner (param);
6165 g_assert_checked (container);
6167 MonoImage *image = get_image_for_container (container);
6168 gboolean is_mvar = container->is_method;
6169 gboolean is_anonymous = container->is_anonymous;
6171 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6172 classes_size += sizeof (MonoClass);
6175 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6177 int n = mono_generic_param_num (param);
6178 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6182 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6183 } else if (is_mvar) {
6184 MonoMethod *omethod = container->owner.method;
6185 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6187 MonoClass *oklass = container->owner.klass;
6188 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6191 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6193 // Count non-NULL items in pinfo->constraints
6196 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6200 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6201 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6203 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6204 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6206 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6209 if (count - pos > 0) {
6210 klass->interface_count = count - pos;
6211 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6212 klass->interfaces_inited = TRUE;
6213 for (i = pos; i < count; i++)
6214 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6217 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6219 klass->inited = TRUE;
6220 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6221 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6222 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6224 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6225 klass->this_arg.type = klass->byval_arg.type;
6226 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6227 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6228 klass->this_arg.byref = TRUE;
6230 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6231 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6233 /*Init these fields to sane values*/
6234 klass->min_align = 1;
6236 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6237 * constrained to, the JIT depends on this.
6239 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6240 mono_memory_barrier ();
6241 klass->size_inited = 1;
6242 klass->setup_fields_called = 1;
6244 mono_class_setup_supertypes (klass);
6246 if (count - pos > 0) {
6247 mono_class_setup_vtable (klass->parent);
6248 if (mono_class_has_failure (klass->parent))
6249 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6251 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6257 #define FAST_CACHE_SIZE 16
6260 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6261 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6262 * we cache the MonoClasses.
6263 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6264 * LOCKING: Takes the image lock depending on @take_lock.
6267 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6269 int n = mono_generic_param_num (param);
6270 MonoImage *image = get_image_for_generic_param (param);
6271 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6272 MonoClass *klass = NULL;
6277 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6278 // For high numbers or constraints we have to use pointer hashes.
6279 if (param->gshared_constraint) {
6280 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6283 mono_image_lock (image);
6284 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6286 mono_image_unlock (image);
6291 if (n < FAST_CACHE_SIZE) {
6293 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6295 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6297 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6300 mono_image_lock (image);
6301 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6303 mono_image_unlock (image);
6310 * LOCKING: Image lock (param->image) must be held
6313 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6315 int n = mono_generic_param_num (param);
6316 MonoImage *image = get_image_for_generic_param (param);
6317 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6321 if (param->gshared_constraint) {
6322 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6324 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6325 mono_memory_barrier ();
6327 image->mvar_cache_constrained = ht;
6329 image->var_cache_constrained = ht;
6331 g_hash_table_insert (ht, param, klass);
6332 } else if (n < FAST_CACHE_SIZE) {
6334 /* Requires locking to avoid droping an already published class */
6335 if (!image->mvar_cache_fast)
6336 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6337 image->mvar_cache_fast [n] = klass;
6339 if (!image->var_cache_fast)
6340 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6341 image->var_cache_fast [n] = klass;
6344 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6346 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6348 ht = g_hash_table_new (NULL, NULL);
6349 mono_memory_barrier ();
6351 image->mvar_cache_slow = ht;
6353 image->var_cache_slow = ht;
6356 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6361 * LOCKING: Acquires the image lock (@image).
6364 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6366 MonoImage *image = get_image_for_generic_param (param);
6367 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6368 MonoClass *klass, *klass2;
6370 // If a klass already exists for this object and is cached, return it.
6371 if (pinfo) // Non-anonymous
6372 klass = pinfo->pklass;
6374 klass = get_anon_gparam_class (param, TRUE);
6379 // Create a new klass
6380 klass = make_generic_param_class (param, pinfo);
6382 // Now we need to cache the klass we created.
6383 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6384 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6385 // and allow our newly-created klass object to just leak.
6386 mono_memory_barrier ();
6388 mono_image_lock (image);
6390 // Here "klass2" refers to the klass potentially created by the other thread.
6391 if (pinfo) // Repeat check from above
6392 klass2 = pinfo->pklass;
6394 klass2 = get_anon_gparam_class (param, FALSE);
6401 pinfo->pklass = klass;
6403 set_anon_gparam_class (param, klass);
6405 mono_image_unlock (image);
6407 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6409 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6411 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6417 * mono_class_from_generic_parameter:
6418 * @param: Parameter to find/construct a class for.
6419 * @arg2: Is ignored.
6420 * @arg3: Is ignored.
6423 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6425 return mono_class_from_generic_parameter_internal (param);
6430 mono_ptr_class_get (MonoType *type)
6433 MonoClass *el_class;
6437 el_class = mono_class_from_mono_type (type);
6438 image = el_class->image;
6440 mono_image_lock (image);
6441 if (image->ptr_cache) {
6442 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6443 mono_image_unlock (image);
6447 mono_image_unlock (image);
6449 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6451 classes_size += sizeof (MonoClass);
6453 result->parent = NULL; /* no parent for PTR types */
6454 result->name_space = el_class->name_space;
6455 name = g_strdup_printf ("%s*", el_class->name);
6456 result->name = mono_image_strdup (image, name);
6459 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6461 result->image = el_class->image;
6462 result->inited = TRUE;
6463 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6464 /* Can pointers get boxed? */
6465 result->instance_size = sizeof (gpointer);
6466 result->cast_class = result->element_class = el_class;
6467 result->blittable = TRUE;
6469 result->byval_arg.type = MONO_TYPE_PTR;
6470 result->this_arg.type = result->byval_arg.type;
6471 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6472 result->this_arg.byref = TRUE;
6474 mono_class_setup_supertypes (result);
6476 mono_image_lock (image);
6477 if (image->ptr_cache) {
6479 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6480 mono_image_unlock (image);
6481 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6485 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6487 g_hash_table_insert (image->ptr_cache, el_class, result);
6488 mono_image_unlock (image);
6490 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6496 mono_fnptr_class_get (MonoMethodSignature *sig)
6499 static GHashTable *ptr_hash = NULL;
6501 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6503 mono_loader_lock ();
6506 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6508 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6509 mono_loader_unlock ();
6512 result = g_new0 (MonoClass, 1);
6514 result->parent = NULL; /* no parent for PTR types */
6515 result->name_space = "System";
6516 result->name = "MonoFNPtrFakeClass";
6518 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6520 result->image = mono_defaults.corlib; /* need to fix... */
6521 result->inited = TRUE;
6522 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6523 /* Can pointers get boxed? */
6524 result->instance_size = sizeof (gpointer);
6525 result->cast_class = result->element_class = result;
6526 result->blittable = TRUE;
6528 result->byval_arg.type = MONO_TYPE_FNPTR;
6529 result->this_arg.type = result->byval_arg.type;
6530 result->this_arg.data.method = result->byval_arg.data.method = sig;
6531 result->this_arg.byref = TRUE;
6532 result->blittable = TRUE;
6534 mono_class_setup_supertypes (result);
6536 g_hash_table_insert (ptr_hash, sig, result);
6538 mono_loader_unlock ();
6540 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6546 * mono_class_from_mono_type:
6547 * @type: describes the type to return
6549 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6552 mono_class_from_mono_type (MonoType *type)
6554 switch (type->type) {
6555 case MONO_TYPE_OBJECT:
6556 return type->data.klass? type->data.klass: mono_defaults.object_class;
6557 case MONO_TYPE_VOID:
6558 return type->data.klass? type->data.klass: mono_defaults.void_class;
6559 case MONO_TYPE_BOOLEAN:
6560 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6561 case MONO_TYPE_CHAR:
6562 return type->data.klass? type->data.klass: mono_defaults.char_class;
6564 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6566 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6568 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6570 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6572 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6574 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6576 return type->data.klass? type->data.klass: mono_defaults.int_class;
6578 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6580 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6582 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6584 return type->data.klass? type->data.klass: mono_defaults.single_class;
6586 return type->data.klass? type->data.klass: mono_defaults.double_class;
6587 case MONO_TYPE_STRING:
6588 return type->data.klass? type->data.klass: mono_defaults.string_class;
6589 case MONO_TYPE_TYPEDBYREF:
6590 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6591 case MONO_TYPE_ARRAY:
6592 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6594 return mono_ptr_class_get (type->data.type);
6595 case MONO_TYPE_FNPTR:
6596 return mono_fnptr_class_get (type->data.method);
6597 case MONO_TYPE_SZARRAY:
6598 return mono_array_class_get (type->data.klass, 1);
6599 case MONO_TYPE_CLASS:
6600 case MONO_TYPE_VALUETYPE:
6601 return type->data.klass;
6602 case MONO_TYPE_GENERICINST:
6603 return mono_generic_class_get_class (type->data.generic_class);
6604 case MONO_TYPE_MVAR:
6606 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6608 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6609 g_assert_not_reached ();
6612 // Yes, this returns NULL, even if it is documented as not doing so, but there
6613 // is no way for the code to make it this far, due to the assert above.
6618 * mono_type_retrieve_from_typespec
6619 * @image: context where the image is created
6620 * @type_spec: typespec token
6621 * @context: the generic context used to evaluate generic instantiations in
6624 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6626 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6628 *did_inflate = FALSE;
6633 if (context && (context->class_inst || context->method_inst)) {
6634 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6636 if (!mono_error_ok (error)) {
6637 mono_loader_assert_no_error ();
6643 *did_inflate = TRUE;
6650 * mono_class_create_from_typespec
6651 * @image: context where the image is created
6652 * @type_spec: typespec token
6653 * @context: the generic context used to evaluate generic instantiations in
6656 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6659 gboolean inflated = FALSE;
6660 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6661 return_val_if_nok (error, NULL);
6662 ret = mono_class_from_mono_type (t);
6664 mono_metadata_free_type (t);
6669 * mono_bounded_array_class_get:
6670 * @element_class: element class
6671 * @rank: the dimension of the array class
6672 * @bounded: whenever the array has non-zero bounds
6674 * Returns: A class object describing the array with element type @element_type and
6678 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6682 MonoClass *parent = NULL;
6683 GSList *list, *rootlist = NULL;
6686 gboolean corlib_type = FALSE;
6688 g_assert (rank <= 255);
6691 /* bounded only matters for one-dimensional arrays */
6694 image = eclass->image;
6696 if (rank == 1 && !bounded) {
6698 * This case is very frequent not just during compilation because of calls
6699 * from mono_class_from_mono_type (), mono_array_new (),
6700 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6702 mono_os_mutex_lock (&image->szarray_cache_lock);
6703 if (!image->szarray_cache)
6704 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6705 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6706 mono_os_mutex_unlock (&image->szarray_cache_lock);
6710 mono_loader_lock ();
6712 mono_loader_lock ();
6714 if (!image->array_cache)
6715 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6717 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6718 for (; list; list = list->next) {
6719 klass = (MonoClass *)list->data;
6720 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6721 mono_loader_unlock ();
6728 /* for the building corlib use System.Array from it */
6729 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6730 parent = mono_class_load_from_name (image, "System", "Array");
6733 parent = mono_defaults.array_class;
6734 if (!parent->inited)
6735 mono_class_init (parent);
6738 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6740 klass->image = image;
6741 klass->name_space = eclass->name_space;
6742 nsize = strlen (eclass->name);
6743 name = (char *)g_malloc (nsize + 2 + rank + 1);
6744 memcpy (name, eclass->name, nsize);
6747 memset (name + nsize + 1, ',', rank - 1);
6749 name [nsize + rank] = '*';
6750 name [nsize + rank + bounded] = ']';
6751 name [nsize + rank + bounded + 1] = 0;
6752 klass->name = mono_image_strdup (image, name);
6755 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6757 classes_size += sizeof (MonoClass);
6759 klass->type_token = 0;
6760 /* all arrays are marked serializable and sealed, bug #42779 */
6761 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6762 klass->parent = parent;
6763 klass->instance_size = mono_class_instance_size (klass->parent);
6765 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6766 /*Arrays of those two types are invalid.*/
6767 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6768 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6769 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6770 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6771 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6773 /* element_size -1 is ok as this is not an instantitable type*/
6774 klass->sizes.element_size = -1;
6776 klass->sizes.element_size = mono_class_array_element_size (eclass);
6778 mono_class_setup_supertypes (klass);
6780 if (eclass->generic_class)
6781 mono_class_init (eclass);
6782 if (!eclass->size_inited)
6783 mono_class_setup_fields (eclass);
6784 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6785 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6787 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6791 if (eclass->enumtype)
6792 klass->cast_class = eclass->element_class;
6794 klass->cast_class = eclass;
6796 switch (klass->cast_class->byval_arg.type) {
6798 klass->cast_class = mono_defaults.byte_class;
6801 klass->cast_class = mono_defaults.int16_class;
6804 #if SIZEOF_VOID_P == 4
6808 klass->cast_class = mono_defaults.int32_class;
6811 #if SIZEOF_VOID_P == 8
6815 klass->cast_class = mono_defaults.int64_class;
6821 klass->element_class = eclass;
6823 if ((rank > 1) || bounded) {
6824 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6825 klass->byval_arg.type = MONO_TYPE_ARRAY;
6826 klass->byval_arg.data.array = at;
6827 at->eklass = eclass;
6829 /* FIXME: complete.... */
6831 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6832 klass->byval_arg.data.klass = eclass;
6834 klass->this_arg = klass->byval_arg;
6835 klass->this_arg.byref = 1;
6840 klass->generic_container = eclass->generic_container;
6842 if (rank == 1 && !bounded) {
6843 MonoClass *prev_class;
6845 mono_os_mutex_lock (&image->szarray_cache_lock);
6846 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6848 /* Someone got in before us */
6851 g_hash_table_insert (image->szarray_cache, eclass, klass);
6852 mono_os_mutex_unlock (&image->szarray_cache_lock);
6854 list = g_slist_append (rootlist, klass);
6855 g_hash_table_insert (image->array_cache, eclass, list);
6858 mono_loader_unlock ();
6860 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6866 * mono_array_class_get:
6867 * @element_class: element class
6868 * @rank: the dimension of the array class
6870 * Returns: A class object describing the array with element type @element_type and
6874 mono_array_class_get (MonoClass *eclass, guint32 rank)
6876 return mono_bounded_array_class_get (eclass, rank, FALSE);
6880 * mono_class_instance_size:
6883 * Use to get the size of a class in bytes.
6885 * Returns: The size of an object instance
6888 mono_class_instance_size (MonoClass *klass)
6890 if (!klass->size_inited)
6891 mono_class_init (klass);
6893 return klass->instance_size;
6897 * mono_class_min_align:
6900 * Use to get the computed minimum alignment requirements for the specified class.
6902 * Returns: minimm alignment requirements
6905 mono_class_min_align (MonoClass *klass)
6907 if (!klass->size_inited)
6908 mono_class_init (klass);
6910 return klass->min_align;
6914 * mono_class_value_size:
6917 * This function is used for value types, and return the
6918 * space and the alignment to store that kind of value object.
6920 * Returns: the size of a value of kind @klass
6923 mono_class_value_size (MonoClass *klass, guint32 *align)
6927 /* fixme: check disable, because we still have external revereces to
6928 * mscorlib and Dummy Objects
6930 /*g_assert (klass->valuetype);*/
6932 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6935 *align = klass->min_align;
6941 * mono_class_data_size:
6944 * Returns: The size of the static class data
6947 mono_class_data_size (MonoClass *klass)
6950 mono_class_init (klass);
6951 /* This can happen with dynamically created types */
6952 if (!klass->fields_inited)
6953 mono_class_setup_fields_locking (klass);
6955 /* in arrays, sizes.class_size is unioned with element_size
6956 * and arrays have no static fields
6960 return klass->sizes.class_size;
6964 * Auxiliary routine to mono_class_get_field
6966 * Takes a field index instead of a field token.
6968 static MonoClassField *
6969 mono_class_get_field_idx (MonoClass *klass, int idx)
6971 mono_class_setup_fields_locking (klass);
6972 if (mono_class_has_failure (klass))
6976 if (klass->image->uncompressed_metadata) {
6978 * klass->field.first points to the FieldPtr table, while idx points into the
6979 * Field table, so we have to do a search.
6981 /*FIXME this is broken for types with multiple fields with the same name.*/
6982 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6985 for (i = 0; i < klass->field.count; ++i)
6986 if (mono_field_get_name (&klass->fields [i]) == name)
6987 return &klass->fields [i];
6988 g_assert_not_reached ();
6990 if (klass->field.count) {
6991 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6992 return &klass->fields [idx - klass->field.first];
6996 klass = klass->parent;
7002 * mono_class_get_field:
7003 * @class: the class to lookup the field.
7004 * @field_token: the field token
7006 * Returns: A MonoClassField representing the type and offset of
7007 * the field, or a NULL value if the field does not belong to this
7011 mono_class_get_field (MonoClass *klass, guint32 field_token)
7013 int idx = mono_metadata_token_index (field_token);
7015 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7017 return mono_class_get_field_idx (klass, idx - 1);
7021 * mono_class_get_field_from_name:
7022 * @klass: the class to lookup the field.
7023 * @name: the field name
7025 * Search the class @klass and it's parents for a field with the name @name.
7027 * Returns: The MonoClassField pointer of the named field or NULL
7030 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7032 return mono_class_get_field_from_name_full (klass, name, NULL);
7036 * mono_class_get_field_from_name_full:
7037 * @klass: the class to lookup the field.
7038 * @name: the field name
7039 * @type: the type of the fields. This optional.
7041 * Search the class @klass and it's parents for a field with the name @name and type @type.
7043 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7044 * of its generic type definition.
7046 * Returns: The MonoClassField pointer of the named field or NULL
7049 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7053 mono_class_setup_fields_locking (klass);
7054 if (mono_class_has_failure (klass))
7058 for (i = 0; i < klass->field.count; ++i) {
7059 MonoClassField *field = &klass->fields [i];
7061 if (strcmp (name, mono_field_get_name (field)) != 0)
7065 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7066 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7071 klass = klass->parent;
7077 * mono_class_get_field_token:
7078 * @field: the field we need the token of
7080 * Get the token of a field. Note that the tokesn is only valid for the image
7081 * the field was loaded from. Don't use this function for fields in dynamic types.
7083 * Returns: The token representing the field in the image it was loaded from.
7086 mono_class_get_field_token (MonoClassField *field)
7088 MonoClass *klass = field->parent;
7091 mono_class_setup_fields_locking (klass);
7096 for (i = 0; i < klass->field.count; ++i) {
7097 if (&klass->fields [i] == field) {
7098 int idx = klass->field.first + i + 1;
7100 if (klass->image->uncompressed_metadata)
7101 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7102 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7105 klass = klass->parent;
7108 g_assert_not_reached ();
7113 mono_field_get_index (MonoClassField *field)
7115 int index = field - field->parent->fields;
7117 g_assert (index >= 0 && index < field->parent->field.count);
7123 * mono_class_get_field_default_value:
7125 * Return the default value of the field as a pointer into the metadata blob.
7128 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7131 guint32 constant_cols [MONO_CONSTANT_SIZE];
7133 MonoClass *klass = field->parent;
7135 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7137 if (!klass->ext || !klass->ext->field_def_values) {
7138 MonoFieldDefaultValue *def_values;
7140 mono_class_alloc_ext (klass);
7142 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7144 mono_image_lock (klass->image);
7145 mono_memory_barrier ();
7146 if (!klass->ext->field_def_values)
7147 klass->ext->field_def_values = def_values;
7148 mono_image_unlock (klass->image);
7151 field_index = mono_field_get_index (field);
7153 if (!klass->ext->field_def_values [field_index].data) {
7154 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7158 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7160 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7161 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7162 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7165 *def_type = klass->ext->field_def_values [field_index].def_type;
7166 return klass->ext->field_def_values [field_index].data;
7170 mono_property_get_index (MonoProperty *prop)
7172 int index = prop - prop->parent->ext->properties;
7174 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7180 * mono_class_get_property_default_value:
7182 * Return the default value of the field as a pointer into the metadata blob.
7185 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7188 guint32 constant_cols [MONO_CONSTANT_SIZE];
7189 MonoClass *klass = property->parent;
7191 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7193 * We don't cache here because it is not used by C# so it's quite rare, but
7194 * we still do the lookup in klass->ext because that is where the data
7195 * is stored for dynamic assemblies.
7198 if (image_is_dynamic (klass->image)) {
7199 int prop_index = mono_property_get_index (property);
7200 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7201 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7202 return klass->ext->prop_def_values [prop_index].data;
7206 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7210 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7211 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7212 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7216 mono_class_get_event_token (MonoEvent *event)
7218 MonoClass *klass = event->parent;
7223 for (i = 0; i < klass->ext->event.count; ++i) {
7224 if (&klass->ext->events [i] == event)
7225 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7228 klass = klass->parent;
7231 g_assert_not_reached ();
7236 * mono_class_get_property_from_name:
7238 * @name: name of the property to lookup in the specified class
7240 * Use this method to lookup a property in a class
7241 * Returns: the MonoProperty with the given name, or NULL if the property
7242 * does not exist on the @klass.
7245 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7249 gpointer iter = NULL;
7250 while ((p = mono_class_get_properties (klass, &iter))) {
7251 if (! strcmp (name, p->name))
7254 klass = klass->parent;
7260 * mono_class_get_property_token:
7261 * @prop: MonoProperty to query
7263 * Returns: The ECMA token for the specified property.
7266 mono_class_get_property_token (MonoProperty *prop)
7268 MonoClass *klass = prop->parent;
7272 gpointer iter = NULL;
7273 while ((p = mono_class_get_properties (klass, &iter))) {
7274 if (&klass->ext->properties [i] == prop)
7275 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7279 klass = klass->parent;
7282 g_assert_not_reached ();
7287 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7289 const char *name, *nspace;
7290 if (image_is_dynamic (image))
7291 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7293 switch (type_token & 0xff000000){
7294 case MONO_TOKEN_TYPE_DEF: {
7295 guint32 cols [MONO_TYPEDEF_SIZE];
7296 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7297 guint tidx = mono_metadata_token_index (type_token);
7299 if (tidx > tt->rows)
7300 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7302 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7303 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7304 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7305 if (strlen (nspace) == 0)
7306 return g_strdup_printf ("%s", name);
7308 return g_strdup_printf ("%s.%s", nspace, name);
7311 case MONO_TOKEN_TYPE_REF: {
7313 guint32 cols [MONO_TYPEREF_SIZE];
7314 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7315 guint tidx = mono_metadata_token_index (type_token);
7318 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7320 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7321 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7322 mono_error_cleanup (&error);
7326 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7327 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7328 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7329 if (strlen (nspace) == 0)
7330 return g_strdup_printf ("%s", name);
7332 return g_strdup_printf ("%s.%s", nspace, name);
7335 case MONO_TOKEN_TYPE_SPEC:
7336 return g_strdup_printf ("Typespec 0x%08x", type_token);
7338 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7343 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7345 if (image_is_dynamic (image))
7346 return g_strdup_printf ("DynamicAssembly %s", image->name);
7348 switch (type_token & 0xff000000){
7349 case MONO_TOKEN_TYPE_DEF:
7350 if (image->assembly)
7351 return mono_stringify_assembly_name (&image->assembly->aname);
7352 else if (image->assembly_name)
7353 return g_strdup (image->assembly_name);
7354 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7355 case MONO_TOKEN_TYPE_REF: {
7357 MonoAssemblyName aname;
7358 guint32 cols [MONO_TYPEREF_SIZE];
7359 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7360 guint32 idx = mono_metadata_token_index (type_token);
7363 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7365 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7366 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7367 mono_error_cleanup (&error);
7370 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7372 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7373 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7374 case MONO_RESOLUTION_SCOPE_MODULE:
7376 return g_strdup ("");
7377 case MONO_RESOLUTION_SCOPE_MODULEREF:
7379 return g_strdup ("");
7380 case MONO_RESOLUTION_SCOPE_TYPEREF:
7382 return g_strdup ("");
7383 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7384 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7385 return mono_stringify_assembly_name (&aname);
7387 g_assert_not_reached ();
7391 case MONO_TOKEN_TYPE_SPEC:
7393 return g_strdup ("");
7395 g_assert_not_reached ();
7402 * mono_class_get_full:
7403 * @image: the image where the class resides
7404 * @type_token: the token for the class
7405 * @context: the generic context used to evaluate generic instantiations in
7406 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7408 * Returns: The MonoClass that represents @type_token in @image
7411 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7415 klass = mono_class_get_checked (image, type_token, &error);
7417 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7418 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7420 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7426 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7430 mono_error_init (error);
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);
7439 * mono_class_get_checked:
7440 * @image: the image where the class resides
7441 * @type_token: the token for the class
7442 * @error: error object to return any error
7444 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7447 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7449 MonoClass *klass = NULL;
7451 mono_error_init (error);
7453 if (image_is_dynamic (image)) {
7454 int table = mono_metadata_token_table (type_token);
7456 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7457 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7460 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7464 switch (type_token & 0xff000000){
7465 case MONO_TOKEN_TYPE_DEF:
7466 klass = mono_class_create_from_typedef (image, type_token, error);
7468 case MONO_TOKEN_TYPE_REF:
7469 klass = mono_class_from_typeref_checked (image, type_token, error);
7471 case MONO_TOKEN_TYPE_SPEC:
7472 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7475 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7479 /* Generic case, should be avoided for when a better error is possible. */
7480 if (!klass && mono_error_ok (error)) {
7481 char *name = mono_class_name_from_token (image, type_token);
7482 char *assembly = mono_assembly_name_from_token (image, type_token);
7483 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7491 * mono_type_get_checked:
7492 * @image: the image where the type resides
7493 * @type_token: the token for the type
7494 * @context: the generic context used to evaluate generic instantiations in
7495 * @error: Error handling context
7497 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7499 * Returns: The MonoType that represents @type_token in @image
7502 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7504 MonoType *type = NULL;
7505 gboolean inflated = FALSE;
7507 mono_error_init (error);
7509 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7510 if (image_is_dynamic (image))
7511 return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
7513 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7514 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7517 mono_loader_assert_no_error ();
7522 return mono_class_get_type (klass);
7525 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7528 mono_loader_assert_no_error ();
7533 MonoType *tmp = type;
7534 type = mono_class_get_type (mono_class_from_mono_type (type));
7535 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7536 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7537 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7539 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7541 if (type->type != tmp->type)
7544 mono_metadata_free_type (tmp);
7551 * @image: image where the class token will be looked up.
7552 * @type_token: a type token from the image
7554 * Returns the MonoClass with the given @type_token on the @image
7557 mono_class_get (MonoImage *image, guint32 type_token)
7559 return mono_class_get_full (image, type_token, NULL);
7563 * mono_image_init_name_cache:
7565 * Initializes the class name cache stored in image->name_cache.
7567 * LOCKING: Acquires the corresponding image lock.
7570 mono_image_init_name_cache (MonoImage *image)
7572 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7573 guint32 cols [MONO_TYPEDEF_SIZE];
7576 guint32 i, visib, nspace_index;
7577 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7579 if (image->name_cache)
7582 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7584 if (image_is_dynamic (image)) {
7585 mono_image_lock (image);
7586 if (image->name_cache) {
7587 /* Somebody initialized it before us */
7588 g_hash_table_destroy (the_name_cache);
7590 mono_atomic_store_release (&image->name_cache, the_name_cache);
7592 mono_image_unlock (image);
7596 /* Temporary hash table to avoid lookups in the nspace_table */
7597 name_cache2 = g_hash_table_new (NULL, NULL);
7599 for (i = 1; i <= t->rows; ++i) {
7600 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7601 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7603 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7604 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7606 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7608 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7609 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7611 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7612 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7613 if (!nspace_table) {
7614 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7615 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7616 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7619 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7622 /* Load type names from EXPORTEDTYPES table */
7624 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7625 guint32 cols [MONO_EXP_TYPE_SIZE];
7628 for (i = 0; i < t->rows; ++i) {
7629 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7631 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7632 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7636 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7637 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7639 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7640 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7641 if (!nspace_table) {
7642 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7643 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7644 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7647 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7651 g_hash_table_destroy (name_cache2);
7653 mono_image_lock (image);
7654 if (image->name_cache) {
7655 /* Somebody initialized it before us */
7656 g_hash_table_destroy (the_name_cache);
7658 mono_atomic_store_release (&image->name_cache, the_name_cache);
7660 mono_image_unlock (image);
7663 /*FIXME Only dynamic assemblies should allow this operation.*/
7665 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7666 const char *name, guint32 index)
7668 GHashTable *nspace_table;
7669 GHashTable *name_cache;
7672 mono_image_init_name_cache (image);
7673 mono_image_lock (image);
7675 name_cache = image->name_cache;
7676 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7677 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7678 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7681 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7682 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7684 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7686 mono_image_unlock (image);
7695 find_nocase (gpointer key, gpointer value, gpointer user_data)
7697 char *name = (char*)key;
7698 FindUserData *data = (FindUserData*)user_data;
7700 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7701 data->value = value;
7705 * mono_class_from_name_case:
7706 * @image: The MonoImage where the type is looked up in
7707 * @name_space: the type namespace
7708 * @name: the type short name.
7709 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7711 * Obtains a MonoClass with a given namespace and a given name which
7712 * is located in the given MonoImage. The namespace and name
7713 * lookups are case insensitive.
7716 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7719 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7720 mono_error_cleanup (&error);
7726 * mono_class_from_name_case:
7727 * @image: The MonoImage where the type is looked up in
7728 * @name_space: the type namespace
7729 * @name: the type short name.
7732 * Obtains a MonoClass with a given namespace and a given name which
7733 * is located in the given MonoImage. The namespace and name
7734 * lookups are case insensitive.
7736 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7737 * was not found. The @error object will contain information about the problem
7741 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7743 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7744 guint32 cols [MONO_TYPEDEF_SIZE];
7749 mono_error_init (error);
7751 if (image_is_dynamic (image)) {
7753 FindUserData user_data;
7755 mono_image_init_name_cache (image);
7756 mono_image_lock (image);
7758 user_data.key = name_space;
7759 user_data.value = NULL;
7760 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7762 if (user_data.value) {
7763 GHashTable *nspace_table = (GHashTable*)user_data.value;
7765 user_data.key = name;
7766 user_data.value = NULL;
7768 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7770 if (user_data.value)
7771 token = GPOINTER_TO_UINT (user_data.value);
7774 mono_image_unlock (image);
7777 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7783 /* add a cache if needed */
7784 for (i = 1; i <= t->rows; ++i) {
7785 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7786 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7788 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7789 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7791 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7793 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7794 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7795 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7796 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7802 return_nested_in (MonoClass *klass, char *nested)
7805 char *s = strchr (nested, '/');
7806 gpointer iter = NULL;
7813 while ((found = mono_class_get_nested_types (klass, &iter))) {
7814 if (strcmp (found->name, nested) == 0) {
7816 return return_nested_in (found, s);
7824 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7826 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7827 MonoImage *file_image;
7831 mono_error_init (error);
7834 * The EXPORTEDTYPES table only contains public types, so have to search the
7836 * Note: image->modules contains the contents of the MODULEREF table, while
7837 * the real module list is in the FILE table.
7839 for (i = 0; i < file_table->rows; i++) {
7840 guint32 cols [MONO_FILE_SIZE];
7841 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7842 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7845 file_image = mono_image_load_file_for_image (image, i + 1);
7847 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7848 if (klass || !is_ok (error))
7857 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7859 GHashTable *nspace_table;
7860 MonoImage *loaded_image;
7867 mono_error_init (error);
7869 // Checking visited images avoids stack overflows when cyclic references exist.
7870 if (g_hash_table_lookup (visited_images, image))
7873 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7875 if ((nested = strchr (name, '/'))) {
7876 int pos = nested - name;
7877 int len = strlen (name);
7880 memcpy (buf, name, len + 1);
7882 nested = buf + pos + 1;
7886 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7887 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7888 gboolean res = get_class_from_name (image, name_space, name, &klass);
7891 klass = search_modules (image, name_space, name, error);
7896 return klass ? return_nested_in (klass, nested) : NULL;
7902 mono_image_init_name_cache (image);
7903 mono_image_lock (image);
7905 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7908 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7910 mono_image_unlock (image);
7912 if (!token && image_is_dynamic (image) && image->modules) {
7913 /* Search modules as well */
7914 for (i = 0; i < image->module_count; ++i) {
7915 MonoImage *module = image->modules [i];
7917 klass = mono_class_from_name_checked (module, name_space, name, error);
7918 if (klass || !is_ok (error))
7924 klass = search_modules (image, name_space, name, error);
7925 if (klass || !is_ok (error))
7932 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7933 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7934 guint32 cols [MONO_EXP_TYPE_SIZE];
7937 idx = mono_metadata_token_index (token);
7939 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7941 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7942 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7943 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7946 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7948 return klass ? return_nested_in (klass, nested) : NULL;
7950 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7951 guint32 assembly_idx;
7953 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7955 mono_assembly_load_reference (image, assembly_idx - 1);
7956 g_assert (image->references [assembly_idx - 1]);
7957 if (image->references [assembly_idx - 1] == (gpointer)-1)
7959 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7961 return klass ? return_nested_in (klass, nested) : NULL;
7964 g_assert_not_reached ();
7968 token = MONO_TOKEN_TYPE_DEF | token;
7970 klass = mono_class_get_checked (image, token, error);
7972 return return_nested_in (klass, nested);
7977 * mono_class_from_name_checked:
7978 * @image: The MonoImage where the type is looked up in
7979 * @name_space: the type namespace
7980 * @name: the type short name.
7982 * Obtains a MonoClass with a given namespace and a given name which
7983 * is located in the given MonoImage.
7985 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7986 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7989 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7992 GHashTable *visited_images;
7994 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7996 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7998 g_hash_table_destroy (visited_images);
8004 * mono_class_from_name:
8005 * @image: The MonoImage where the type is looked up in
8006 * @name_space: the type namespace
8007 * @name: the type short name.
8009 * Obtains a MonoClass with a given namespace and a given name which
8010 * is located in the given MonoImage.
8012 * To reference nested classes, use the "/" character as a separator.
8013 * For example use "Foo/Bar" to reference the class Bar that is nested
8014 * inside Foo, like this: "class Foo { class Bar {} }".
8017 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8022 klass = mono_class_from_name_checked (image, name_space, name, &error);
8023 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8029 * mono_class_load_from_name:
8030 * @image: The MonoImage where the type is looked up in
8031 * @name_space: the type namespace
8032 * @name: the type short name.
8034 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8035 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8036 * If they are missing. Thing of System.Object or System.String.
8039 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8044 klass = mono_class_from_name_checked (image, name_space, name, &error);
8046 g_error ("Runtime critical type %s.%s not found", name_space, name);
8047 if (!mono_error_ok (&error))
8048 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8053 * mono_class_try_load_from_name:
8054 * @image: The MonoImage where the type is looked up in
8055 * @name_space: the type namespace
8056 * @name: the type short name.
8058 * This function tries to load a type, returning the class was found or NULL otherwise.
8059 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8061 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8062 * a type that we would otherwise assume to be available but was not due some error.
8066 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8071 klass = mono_class_from_name_checked (image, name_space, name, &error);
8072 if (!mono_error_ok (&error))
8073 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8079 * mono_class_is_subclass_of:
8080 * @klass: class to probe if it is a subclass of another one
8081 * @klassc: the class we suspect is the base class
8082 * @check_interfaces: whether we should perform interface checks
8084 * This method determines whether @klass is a subclass of @klassc.
8086 * If the @check_interfaces flag is set, then if @klassc is an interface
8087 * this method return TRUE if the @klass implements the interface or
8088 * if @klass is an interface, if one of its base classes is @klass.
8090 * If @check_interfaces is false then, then if @klass is not an interface
8091 * then it returns TRUE if the @klass is a subclass of @klassc.
8093 * if @klass is an interface and @klassc is System.Object, then this function
8098 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8099 gboolean check_interfaces)
8101 /*FIXME test for interfaces with variant generic arguments*/
8103 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8104 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8106 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8109 for (i = 0; i < klass->interface_count; i ++) {
8110 MonoClass *ic = klass->interfaces [i];
8115 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8120 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8123 if (klassc == mono_defaults.object_class)
8130 mono_type_is_generic_argument (MonoType *type)
8132 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8136 mono_class_has_variant_generic_params (MonoClass *klass)
8139 MonoGenericContainer *container;
8141 if (!klass->generic_class)
8144 container = klass->generic_class->container_class->generic_container;
8146 for (i = 0; i < container->type_argc; ++i)
8147 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8154 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8156 if (target == candidate)
8159 if (check_for_reference_conv &&
8160 mono_type_is_generic_argument (&target->byval_arg) &&
8161 mono_type_is_generic_argument (&candidate->byval_arg)) {
8162 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8163 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8165 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8168 if (!mono_class_is_assignable_from (target, candidate))
8174 * @container the generic container from the GTD
8175 * @klass: the class to be assigned to
8176 * @oklass: the source class
8178 * Both @klass and @oklass must be instances of the same generic interface.
8180 * Returns: TRUE if @klass can be assigned to a @klass variable
8183 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8186 MonoType **klass_argv, **oklass_argv;
8187 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8188 MonoGenericContainer *container = klass_gtd->generic_container;
8190 if (klass == oklass)
8193 /*Viable candidates are instances of the same generic interface*/
8194 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8197 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8198 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8200 for (j = 0; j < container->type_argc; ++j) {
8201 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8202 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8204 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8208 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8209 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8211 if (param1_class != param2_class) {
8212 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8213 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8215 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8216 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8226 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8228 MonoGenericParam *gparam, *ogparam;
8229 MonoGenericParamInfo *tinfo, *cinfo;
8230 MonoClass **candidate_class;
8231 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8234 if (target == candidate)
8236 if (target->byval_arg.type != candidate->byval_arg.type)
8239 gparam = target->byval_arg.data.generic_param;
8240 ogparam = candidate->byval_arg.data.generic_param;
8241 tinfo = mono_generic_param_info (gparam);
8242 cinfo = mono_generic_param_info (ogparam);
8244 class_constraint_satisfied = FALSE;
8245 valuetype_constraint_satisfied = FALSE;
8247 /*candidate must have a super set of target's special constraints*/
8248 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8249 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8251 if (cinfo->constraints) {
8252 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8253 MonoClass *cc = *candidate_class;
8255 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8256 class_constraint_satisfied = TRUE;
8257 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8258 valuetype_constraint_satisfied = TRUE;
8261 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8262 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8264 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8266 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8268 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8269 valuetype_constraint_satisfied)) {
8274 /*candidate type constraints must be a superset of target's*/
8275 if (tinfo->constraints) {
8276 MonoClass **target_class;
8277 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8278 MonoClass *tc = *target_class;
8281 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8282 * check it's constraints since it satisfy the constraint by itself.
8284 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8287 if (!cinfo->constraints)
8290 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8291 MonoClass *cc = *candidate_class;
8293 if (mono_class_is_assignable_from (tc, cc))
8297 * This happens when we have the following:
8299 * Bar<K> where K : IFace
8300 * Foo<T, U> where T : U where U : IFace
8302 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8305 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8306 if (mono_gparam_is_assignable_from (target, cc))
8310 if (!*candidate_class)
8315 /*candidate itself must have a constraint that satisfy target*/
8316 if (cinfo->constraints) {
8317 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8318 MonoClass *cc = *candidate_class;
8319 if (mono_class_is_assignable_from (target, cc))
8327 * mono_class_is_assignable_from:
8328 * @klass: the class to be assigned to
8329 * @oklass: the source class
8331 * Returns: TRUE if an instance of object oklass can be assigned to an
8332 * instance of object @klass
8335 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8338 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8340 mono_class_init (klass);
8342 if (!oklass->inited)
8343 mono_class_init (oklass);
8345 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8348 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8349 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8351 return mono_gparam_is_assignable_from (klass, oklass);
8354 if (MONO_CLASS_IS_INTERFACE (klass)) {
8355 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8356 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8357 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8361 for (i = 0; constraints [i]; ++i) {
8362 if (mono_class_is_assignable_from (klass, constraints [i]))
8370 /* interface_offsets might not be set for dynamic classes */
8371 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8373 * oklass might be a generic type parameter but they have
8374 * interface_offsets set.
8376 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8377 if (!is_ok (&error)) {
8378 mono_error_cleanup (&error);
8383 if (!oklass->interface_bitmap)
8384 /* Happens with generic instances of not-yet created dynamic types */
8386 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8389 if (mono_class_has_variant_generic_params (klass)) {
8391 mono_class_setup_interfaces (oklass, &error);
8392 if (!mono_error_ok (&error)) {
8393 mono_error_cleanup (&error);
8397 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8398 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8399 MonoClass *iface = oklass->interfaces_packed [i];
8401 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8406 } else if (klass->delegate) {
8407 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8409 }else if (klass->rank) {
8410 MonoClass *eclass, *eoclass;
8412 if (oklass->rank != klass->rank)
8415 /* vectors vs. one dimensional arrays */
8416 if (oklass->byval_arg.type != klass->byval_arg.type)
8419 eclass = klass->cast_class;
8420 eoclass = oklass->cast_class;
8423 * a is b does not imply a[] is b[] when a is a valuetype, and
8424 * b is a reference type.
8427 if (eoclass->valuetype) {
8428 if ((eclass == mono_defaults.enum_class) ||
8429 (eclass == mono_defaults.enum_class->parent) ||
8430 (eclass == mono_defaults.object_class))
8434 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8435 } else if (mono_class_is_nullable (klass)) {
8436 if (mono_class_is_nullable (oklass))
8437 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8439 return mono_class_is_assignable_from (klass->cast_class, oklass);
8440 } else if (klass == mono_defaults.object_class)
8443 return mono_class_has_parent (oklass, klass);
8446 /*Check if @oklass is variant compatible with @klass.*/
8448 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8451 MonoType **klass_argv, **oklass_argv;
8452 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8453 MonoGenericContainer *container = klass_gtd->generic_container;
8455 /*Viable candidates are instances of the same generic interface*/
8456 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8459 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8460 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8462 for (j = 0; j < container->type_argc; ++j) {
8463 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8464 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8466 if (param1_class->valuetype != param2_class->valuetype)
8470 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8471 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8473 if (param1_class != param2_class) {
8474 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8475 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8477 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8478 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8486 /*Check if @candidate implements the interface @target*/
8488 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8492 gboolean is_variant = mono_class_has_variant_generic_params (target);
8494 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8495 if (mono_class_is_variant_compatible_slow (target, candidate))
8500 if (candidate == target)
8503 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8504 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8505 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8507 if (tb && tb->interfaces) {
8508 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8509 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8510 MonoClass *iface_class;
8512 /* we can't realize the type here since it can do pretty much anything. */
8515 iface_class = mono_class_from_mono_type (iface->type);
8516 if (iface_class == target)
8518 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8520 if (mono_class_implement_interface_slow (target, iface_class))
8525 /*setup_interfaces don't mono_class_init anything*/
8526 /*FIXME this doesn't handle primitive type arrays.
8527 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8528 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8530 mono_class_setup_interfaces (candidate, &error);
8531 if (!mono_error_ok (&error)) {
8532 mono_error_cleanup (&error);
8536 for (i = 0; i < candidate->interface_count; ++i) {
8537 if (candidate->interfaces [i] == target)
8540 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8543 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8547 candidate = candidate->parent;
8548 } while (candidate);
8554 * Check if @oklass can be assigned to @klass.
8555 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8558 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8560 if (candidate == target)
8562 if (target == mono_defaults.object_class)
8565 if (mono_class_has_parent (candidate, target))
8568 /*If target is not an interface there is no need to check them.*/
8569 if (MONO_CLASS_IS_INTERFACE (target))
8570 return mono_class_implement_interface_slow (target, candidate);
8572 if (target->delegate && mono_class_has_variant_generic_params (target))
8573 return mono_class_is_variant_compatible (target, candidate, FALSE);
8576 MonoClass *eclass, *eoclass;
8578 if (target->rank != candidate->rank)
8581 /* vectors vs. one dimensional arrays */
8582 if (target->byval_arg.type != candidate->byval_arg.type)
8585 eclass = target->cast_class;
8586 eoclass = candidate->cast_class;
8589 * a is b does not imply a[] is b[] when a is a valuetype, and
8590 * b is a reference type.
8593 if (eoclass->valuetype) {
8594 if ((eclass == mono_defaults.enum_class) ||
8595 (eclass == mono_defaults.enum_class->parent) ||
8596 (eclass == mono_defaults.object_class))
8600 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8602 /*FIXME properly handle nullables */
8603 /*FIXME properly handle (M)VAR */
8608 * mono_class_get_cctor:
8609 * @klass: A MonoClass pointer
8611 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8614 mono_class_get_cctor (MonoClass *klass)
8616 MonoCachedClassInfo cached_info;
8618 if (image_is_dynamic (klass->image)) {
8620 * has_cctor is not set for these classes because mono_class_init () is
8623 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8626 if (!klass->has_cctor)
8629 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8631 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8632 if (!mono_error_ok (&error))
8633 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8637 if (klass->generic_class && !klass->methods)
8638 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8640 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8644 * mono_class_get_finalizer:
8645 * @klass: The MonoClass pointer
8647 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8650 mono_class_get_finalizer (MonoClass *klass)
8652 MonoCachedClassInfo cached_info;
8655 mono_class_init (klass);
8656 if (!mono_class_has_finalizer (klass))
8659 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8661 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8662 if (!mono_error_ok (&error))
8663 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8666 mono_class_setup_vtable (klass);
8667 return klass->vtable [finalize_slot];
8672 * mono_class_needs_cctor_run:
8673 * @klass: the MonoClass pointer
8674 * @caller: a MonoMethod describing the caller
8676 * Determines whenever the class has a static constructor and whenever it
8677 * needs to be called when executing CALLER.
8680 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8684 method = mono_class_get_cctor (klass);
8686 return (method == caller) ? FALSE : TRUE;
8692 * mono_class_array_element_size:
8695 * Returns: The number of bytes an element of type @klass
8696 * uses when stored into an array.
8699 mono_class_array_element_size (MonoClass *klass)
8701 MonoType *type = &klass->byval_arg;
8704 switch (type->type) {
8707 case MONO_TYPE_BOOLEAN:
8711 case MONO_TYPE_CHAR:
8720 case MONO_TYPE_CLASS:
8721 case MONO_TYPE_STRING:
8722 case MONO_TYPE_OBJECT:
8723 case MONO_TYPE_SZARRAY:
8724 case MONO_TYPE_ARRAY:
8725 return sizeof (gpointer);
8730 case MONO_TYPE_VALUETYPE:
8731 if (type->data.klass->enumtype) {
8732 type = mono_class_enum_basetype (type->data.klass);
8733 klass = klass->element_class;
8736 return mono_class_instance_size (klass) - sizeof (MonoObject);
8737 case MONO_TYPE_GENERICINST:
8738 type = &type->data.generic_class->container_class->byval_arg;
8741 case MONO_TYPE_MVAR: {
8744 return mono_type_size (type, &align);
8746 case MONO_TYPE_VOID:
8750 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8756 * mono_array_element_size:
8757 * @ac: pointer to a #MonoArrayClass
8759 * Returns: The size of single array element.
8762 mono_array_element_size (MonoClass *ac)
8764 g_assert (ac->rank);
8765 return ac->sizes.element_size;
8769 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8770 MonoGenericContext *context)
8773 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8774 g_assert (mono_error_ok (&error));
8779 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8780 MonoGenericContext *context, MonoError *error)
8782 mono_error_init (error);
8784 if (image_is_dynamic (image)) {
8785 MonoClass *tmp_handle_class;
8786 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8788 g_assert (tmp_handle_class);
8790 *handle_class = tmp_handle_class;
8792 if (tmp_handle_class == mono_defaults.typehandle_class)
8793 return &((MonoClass*)obj)->byval_arg;
8798 switch (token & 0xff000000) {
8799 case MONO_TOKEN_TYPE_DEF:
8800 case MONO_TOKEN_TYPE_REF:
8801 case MONO_TOKEN_TYPE_SPEC: {
8804 *handle_class = mono_defaults.typehandle_class;
8805 type = mono_type_get_checked (image, token, context, error);
8809 mono_class_init (mono_class_from_mono_type (type));
8810 /* We return a MonoType* as handle */
8813 case MONO_TOKEN_FIELD_DEF: {
8815 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8817 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8821 *handle_class = mono_defaults.fieldhandle_class;
8822 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8826 mono_class_init (klass);
8827 return mono_class_get_field (klass, token);
8829 case MONO_TOKEN_METHOD_DEF:
8830 case MONO_TOKEN_METHOD_SPEC: {
8832 meth = mono_get_method_checked (image, token, NULL, context, error);
8834 *handle_class = mono_defaults.methodhandle_class;
8840 case MONO_TOKEN_MEMBER_REF: {
8841 guint32 cols [MONO_MEMBERREF_SIZE];
8843 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8844 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8845 mono_metadata_decode_blob_size (sig, &sig);
8846 if (*sig == 0x6) { /* it's a field */
8848 MonoClassField *field;
8849 field = mono_field_from_token_checked (image, token, &klass, context, error);
8851 *handle_class = mono_defaults.fieldhandle_class;
8855 meth = mono_get_method_checked (image, token, NULL, context, error);
8857 *handle_class = mono_defaults.methodhandle_class;
8862 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8868 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8871 MonoClass *handle_class;
8873 gpointer result = mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, &error);
8874 mono_error_raise_exception (&error); /* FIXME don't raise here */
8880 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8883 gpointer result = mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, &error);
8884 mono_error_raise_exception (&error); /* FIXME don't raise here */
8889 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8892 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8894 get_cached_class_info = func;
8898 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8900 if (!get_cached_class_info)
8903 return get_cached_class_info (klass, res);
8907 mono_install_get_class_from_name (MonoGetClassFromName func)
8909 get_class_from_name = func;
8913 * mono_class_get_image:
8915 * Use this method to get the `MonoImage*` where this class came from.
8917 * Returns: The image where this class is defined.
8920 mono_class_get_image (MonoClass *klass)
8922 return klass->image;
8926 * mono_class_get_element_class:
8927 * @klass: the MonoClass to act on
8929 * Use this function to get the element class of an array.
8931 * Returns: The element class of an array.
8934 mono_class_get_element_class (MonoClass *klass)
8936 return klass->element_class;
8940 * mono_class_is_valuetype:
8941 * @klass: the MonoClass to act on
8943 * Use this method to determine if the provided `MonoClass*` represents a value type,
8944 * or a reference type.
8946 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8949 mono_class_is_valuetype (MonoClass *klass)
8951 return klass->valuetype;
8955 * mono_class_is_enum:
8956 * @klass: the MonoClass to act on
8958 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8960 * Returns: TRUE if the MonoClass represents an enumeration.
8963 mono_class_is_enum (MonoClass *klass)
8965 return klass->enumtype;
8969 * mono_class_enum_basetype:
8970 * @klass: the MonoClass to act on
8972 * Use this function to get the underlying type for an enumeration value.
8974 * Returns: The underlying type representation for an enumeration.
8977 mono_class_enum_basetype (MonoClass *klass)
8979 if (klass->element_class == klass)
8980 /* SRE or broken types */
8983 return &klass->element_class->byval_arg;
8987 * mono_class_get_parent
8988 * @klass: the MonoClass to act on
8990 * Returns: The parent class for this class.
8993 mono_class_get_parent (MonoClass *klass)
8995 return klass->parent;
8999 * mono_class_get_nesting_type:
9000 * @klass: the MonoClass to act on
9002 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9004 * If the return is NULL, this indicates that this class is not nested.
9006 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9009 mono_class_get_nesting_type (MonoClass *klass)
9011 return klass->nested_in;
9015 * mono_class_get_rank:
9016 * @klass: the MonoClass to act on
9018 * Returns: The rank for the array (the number of dimensions).
9021 mono_class_get_rank (MonoClass *klass)
9027 * mono_class_get_flags:
9028 * @klass: the MonoClass to act on
9030 * The type flags from the TypeDef table from the metadata.
9031 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9034 * Returns: The flags from the TypeDef table.
9037 mono_class_get_flags (MonoClass *klass)
9039 return klass->flags;
9043 * mono_class_get_name
9044 * @klass: the MonoClass to act on
9046 * Returns: The name of the class.
9049 mono_class_get_name (MonoClass *klass)
9055 * mono_class_get_namespace:
9056 * @klass: the MonoClass to act on
9058 * Returns: The namespace of the class.
9061 mono_class_get_namespace (MonoClass *klass)
9063 return klass->name_space;
9067 * mono_class_get_type:
9068 * @klass: the MonoClass to act on
9070 * This method returns the internal Type representation for the class.
9072 * Returns: The MonoType from the class.
9075 mono_class_get_type (MonoClass *klass)
9077 return &klass->byval_arg;
9081 * mono_class_get_type_token:
9082 * @klass: the MonoClass to act on
9084 * This method returns type token for the class.
9086 * Returns: The type token for the class.
9089 mono_class_get_type_token (MonoClass *klass)
9091 return klass->type_token;
9095 * mono_class_get_byref_type:
9096 * @klass: the MonoClass to act on
9101 mono_class_get_byref_type (MonoClass *klass)
9103 return &klass->this_arg;
9107 * mono_class_num_fields:
9108 * @klass: the MonoClass to act on
9110 * Returns: The number of static and instance fields in the class.
9113 mono_class_num_fields (MonoClass *klass)
9115 return klass->field.count;
9119 * mono_class_num_methods:
9120 * @klass: the MonoClass to act on
9122 * Returns: The number of methods in the class.
9125 mono_class_num_methods (MonoClass *klass)
9127 return klass->method.count;
9131 * mono_class_num_properties
9132 * @klass: the MonoClass to act on
9134 * Returns: The number of properties in the class.
9137 mono_class_num_properties (MonoClass *klass)
9139 mono_class_setup_properties (klass);
9141 return klass->ext->property.count;
9145 * mono_class_num_events:
9146 * @klass: the MonoClass to act on
9148 * Returns: The number of events in the class.
9151 mono_class_num_events (MonoClass *klass)
9153 mono_class_setup_events (klass);
9155 return klass->ext->event.count;
9159 * mono_class_get_fields:
9160 * @klass: the MonoClass to act on
9162 * This routine is an iterator routine for retrieving the fields in a class.
9164 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9165 * iterate over all of the elements. When no more values are
9166 * available, the return value is NULL.
9168 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9171 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9173 MonoClassField* field;
9177 mono_class_setup_fields_locking (klass);
9178 if (mono_class_has_failure (klass))
9180 /* start from the first */
9181 if (klass->field.count) {
9182 *iter = &klass->fields [0];
9183 return &klass->fields [0];
9189 field = (MonoClassField *)*iter;
9191 if (field < &klass->fields [klass->field.count]) {
9199 * mono_class_get_methods
9200 * @klass: the MonoClass to act on
9202 * This routine is an iterator routine for retrieving the fields in a class.
9204 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9205 * iterate over all of the elements. When no more values are
9206 * available, the return value is NULL.
9208 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9211 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9213 MonoMethod** method;
9217 mono_class_setup_methods (klass);
9220 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9221 * FIXME we should better report this error to the caller
9223 if (!klass->methods)
9225 /* start from the first */
9226 if (klass->method.count) {
9227 *iter = &klass->methods [0];
9228 return klass->methods [0];
9234 method = (MonoMethod **)*iter;
9236 if (method < &klass->methods [klass->method.count]) {
9244 * mono_class_get_virtual_methods:
9246 * Iterate over the virtual methods of KLASS.
9248 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9251 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9253 MonoMethod** method;
9256 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9258 mono_class_setup_methods (klass);
9260 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9261 * FIXME we should better report this error to the caller
9263 if (!klass->methods)
9265 /* start from the first */
9266 method = &klass->methods [0];
9268 method = (MonoMethod **)*iter;
9271 while (method < &klass->methods [klass->method.count]) {
9272 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9276 if (method < &klass->methods [klass->method.count]) {
9283 /* Search directly in metadata to avoid calling setup_methods () */
9284 MonoMethod *res = NULL;
9290 start_index = GPOINTER_TO_UINT (*iter);
9293 for (i = start_index; i < klass->method.count; ++i) {
9296 /* klass->method.first points into the methodptr table */
9297 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9299 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9303 if (i < klass->method.count) {
9305 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9306 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9308 /* Add 1 here so the if (*iter) check fails */
9309 *iter = GUINT_TO_POINTER (i + 1);
9318 * mono_class_get_properties:
9319 * @klass: the MonoClass to act on
9321 * This routine is an iterator routine for retrieving the properties in a class.
9323 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9324 * iterate over all of the elements. When no more values are
9325 * available, the return value is NULL.
9327 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9330 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9332 MonoProperty* property;
9336 mono_class_setup_properties (klass);
9337 /* start from the first */
9338 if (klass->ext->property.count) {
9339 *iter = &klass->ext->properties [0];
9340 return (MonoProperty *)*iter;
9346 property = (MonoProperty *)*iter;
9348 if (property < &klass->ext->properties [klass->ext->property.count]) {
9350 return (MonoProperty *)*iter;
9356 * mono_class_get_events:
9357 * @klass: the MonoClass to act on
9359 * This routine is an iterator routine for retrieving the properties in a class.
9361 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9362 * iterate over all of the elements. When no more values are
9363 * available, the return value is NULL.
9365 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9368 mono_class_get_events (MonoClass* klass, gpointer *iter)
9374 mono_class_setup_events (klass);
9375 /* start from the first */
9376 if (klass->ext->event.count) {
9377 *iter = &klass->ext->events [0];
9378 return (MonoEvent *)*iter;
9384 event = (MonoEvent *)*iter;
9386 if (event < &klass->ext->events [klass->ext->event.count]) {
9388 return (MonoEvent *)*iter;
9394 * mono_class_get_interfaces
9395 * @klass: the MonoClass to act on
9397 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9399 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9400 * iterate over all of the elements. When no more values are
9401 * available, the return value is NULL.
9403 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9406 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9414 mono_class_init (klass);
9415 if (!klass->interfaces_inited) {
9416 mono_class_setup_interfaces (klass, &error);
9417 if (!mono_error_ok (&error)) {
9418 mono_error_cleanup (&error);
9422 /* start from the first */
9423 if (klass->interface_count) {
9424 *iter = &klass->interfaces [0];
9425 return klass->interfaces [0];
9431 iface = (MonoClass **)*iter;
9433 if (iface < &klass->interfaces [klass->interface_count]) {
9441 setup_nested_types (MonoClass *klass)
9444 GList *classes, *nested_classes, *l;
9447 if (klass->nested_classes_inited)
9450 if (!klass->type_token)
9451 klass->nested_classes_inited = TRUE;
9453 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9457 guint32 cols [MONO_NESTED_CLASS_SIZE];
9458 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9459 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9460 if (!mono_error_ok (&error)) {
9461 /*FIXME don't swallow the error message*/
9462 mono_error_cleanup (&error);
9464 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9468 classes = g_list_prepend (classes, nclass);
9470 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9473 mono_class_alloc_ext (klass);
9475 nested_classes = NULL;
9476 for (l = classes; l; l = l->next)
9477 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9478 g_list_free (classes);
9480 mono_image_lock (klass->image);
9482 mono_memory_barrier ();
9483 if (!klass->nested_classes_inited) {
9484 klass->ext->nested_classes = nested_classes;
9485 mono_memory_barrier ();
9486 klass->nested_classes_inited = TRUE;
9489 mono_image_unlock (klass->image);
9493 * mono_class_get_nested_types
9494 * @klass: the MonoClass to act on
9496 * This routine is an iterator routine for retrieving the nested types of a class.
9497 * This works only if @klass is non-generic, or a generic type definition.
9499 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9500 * iterate over all of the elements. When no more values are
9501 * available, the return value is NULL.
9503 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9506 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9512 if (!klass->nested_classes_inited)
9513 setup_nested_types (klass);
9516 /* start from the first */
9517 if (klass->ext && klass->ext->nested_classes) {
9518 *iter = klass->ext->nested_classes;
9519 return (MonoClass *)klass->ext->nested_classes->data;
9521 /* no nested types */
9525 item = (GList *)*iter;
9529 return (MonoClass *)item->data;
9536 * mono_class_is_delegate
9537 * @klass: the MonoClass to act on
9539 * Returns: TRUE if the MonoClass represents a System.Delegate.
9542 mono_class_is_delegate (MonoClass *klass)
9544 return klass->delegate;
9548 * mono_class_implements_interface
9549 * @klass: The MonoClass to act on
9550 * @interface: The interface to check if @klass implements.
9552 * Returns: TRUE if @klass implements @interface.
9555 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9557 return mono_class_is_assignable_from (iface, klass);
9561 * mono_field_get_name:
9562 * @field: the MonoClassField to act on
9564 * Returns: The name of the field.
9567 mono_field_get_name (MonoClassField *field)
9573 * mono_field_get_type:
9574 * @field: the MonoClassField to act on
9576 * Returns: MonoType of the field.
9579 mono_field_get_type (MonoClassField *field)
9582 MonoType *type = mono_field_get_type_checked (field, &error);
9583 if (!mono_error_ok (&error)) {
9584 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9585 mono_error_cleanup (&error);
9592 * mono_field_get_type_checked:
9593 * @field: the MonoClassField to act on
9594 * @error: used to return any erro found while retrieving @field type
9596 * Returns: MonoType of the field.
9599 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9601 mono_error_init (error);
9603 mono_field_resolve_type (field, error);
9608 * mono_field_get_parent:
9609 * @field: the MonoClassField to act on
9611 * Returns: MonoClass where the field was defined.
9614 mono_field_get_parent (MonoClassField *field)
9616 return field->parent;
9620 * mono_field_get_flags;
9621 * @field: the MonoClassField to act on
9623 * The metadata flags for a field are encoded using the
9624 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9626 * Returns: The flags for the field.
9629 mono_field_get_flags (MonoClassField *field)
9632 return mono_field_resolve_flags (field);
9633 return field->type->attrs;
9637 * mono_field_get_offset:
9638 * @field: the MonoClassField to act on
9640 * Returns: The field offset.
9643 mono_field_get_offset (MonoClassField *field)
9645 return field->offset;
9649 mono_field_get_rva (MonoClassField *field)
9653 MonoClass *klass = field->parent;
9654 MonoFieldDefaultValue *field_def_values;
9656 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9658 if (!klass->ext || !klass->ext->field_def_values) {
9659 mono_class_alloc_ext (klass);
9661 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9663 mono_image_lock (klass->image);
9664 if (!klass->ext->field_def_values)
9665 klass->ext->field_def_values = field_def_values;
9666 mono_image_unlock (klass->image);
9669 field_index = mono_field_get_index (field);
9671 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9672 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9674 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9675 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9678 return klass->ext->field_def_values [field_index].data;
9682 * mono_field_get_data:
9683 * @field: the MonoClassField to act on
9685 * Returns: A pointer to the metadata constant value or to the field
9686 * data if it has an RVA flag.
9689 mono_field_get_data (MonoClassField *field)
9691 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9692 MonoTypeEnum def_type;
9694 return mono_class_get_field_default_value (field, &def_type);
9695 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9696 return mono_field_get_rva (field);
9703 * mono_property_get_name:
9704 * @prop: the MonoProperty to act on
9706 * Returns: The name of the property
9709 mono_property_get_name (MonoProperty *prop)
9715 * mono_property_get_set_method
9716 * @prop: the MonoProperty to act on.
9718 * Returns: The setter method of the property (A MonoMethod)
9721 mono_property_get_set_method (MonoProperty *prop)
9727 * mono_property_get_get_method
9728 * @prop: the MonoProperty to act on.
9730 * Returns: The setter method of the property (A MonoMethod)
9733 mono_property_get_get_method (MonoProperty *prop)
9739 * mono_property_get_parent:
9740 * @prop: the MonoProperty to act on.
9742 * Returns: The MonoClass where the property was defined.
9745 mono_property_get_parent (MonoProperty *prop)
9747 return prop->parent;
9751 * mono_property_get_flags:
9752 * @prop: the MonoProperty to act on.
9754 * The metadata flags for a property are encoded using the
9755 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9757 * Returns: The flags for the property.
9760 mono_property_get_flags (MonoProperty *prop)
9766 * mono_event_get_name:
9767 * @event: the MonoEvent to act on
9769 * Returns: The name of the event.
9772 mono_event_get_name (MonoEvent *event)
9778 * mono_event_get_add_method:
9779 * @event: The MonoEvent to act on.
9781 * Returns: The @add' method for the event (a MonoMethod).
9784 mono_event_get_add_method (MonoEvent *event)
9790 * mono_event_get_remove_method:
9791 * @event: The MonoEvent to act on.
9793 * Returns: The @remove method for the event (a MonoMethod).
9796 mono_event_get_remove_method (MonoEvent *event)
9798 return event->remove;
9802 * mono_event_get_raise_method:
9803 * @event: The MonoEvent to act on.
9805 * Returns: The @raise method for the event (a MonoMethod).
9808 mono_event_get_raise_method (MonoEvent *event)
9810 return event->raise;
9814 * mono_event_get_parent:
9815 * @event: the MonoEvent to act on.
9817 * Returns: The MonoClass where the event is defined.
9820 mono_event_get_parent (MonoEvent *event)
9822 return event->parent;
9826 * mono_event_get_flags
9827 * @event: the MonoEvent to act on.
9829 * The metadata flags for an event are encoded using the
9830 * EVENT_* constants. See the tabledefs.h file for details.
9832 * Returns: The flags for the event.
9835 mono_event_get_flags (MonoEvent *event)
9837 return event->attrs;
9841 * mono_class_get_method_from_name:
9842 * @klass: where to look for the method
9843 * @name: name of the method
9844 * @param_count: number of parameters. -1 for any number.
9846 * Obtains a MonoMethod with a given name and number of parameters.
9847 * It only works if there are no multiple signatures for any given method name.
9850 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9852 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9856 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9858 MonoMethod *res = NULL;
9861 /* Search directly in the metadata to avoid calling setup_methods () */
9862 for (i = 0; i < klass->method.count; ++i) {
9864 guint32 cols [MONO_METHOD_SIZE];
9866 MonoMethodSignature *sig;
9868 /* klass->method.first points into the methodptr table */
9869 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9871 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9872 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9874 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9877 if (param_count == -1) {
9881 sig = mono_method_signature_checked (method, &error);
9883 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9886 if (sig->param_count == param_count) {
9897 * mono_class_get_method_from_name_flags:
9898 * @klass: where to look for the method
9899 * @name_space: name of the method
9900 * @param_count: number of parameters. -1 for any number.
9901 * @flags: flags which must be set in the method
9903 * Obtains a MonoMethod with a given name and number of parameters.
9904 * It only works if there are no multiple signatures for any given method name.
9907 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9909 MonoMethod *res = NULL;
9912 mono_class_init (klass);
9914 if (klass->generic_class && !klass->methods) {
9915 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9918 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9919 if (!mono_error_ok (&error))
9920 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9925 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9926 mono_class_setup_methods (klass);
9928 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9929 See mono/tests/array_load_exception.il
9930 FIXME we should better report this error to the caller
9932 if (!klass->methods)
9934 for (i = 0; i < klass->method.count; ++i) {
9935 MonoMethod *method = klass->methods [i];
9937 if (method->name[0] == name [0] &&
9938 !strcmp (name, method->name) &&
9939 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9940 ((method->flags & flags) == flags)) {
9947 res = find_method_in_metadata (klass, name, param_count, flags);
9954 * mono_class_set_failure:
9955 * @klass: class in which the failure was detected
9956 * @ex_type: the kind of exception/error to be thrown (later)
9957 * @ex_data: exception data (specific to each type of exception/error)
9959 * Keep a detected failure informations in the class for later processing.
9960 * Note that only the first failure is kept.
9962 * LOCKING: Acquires the loader lock.
9965 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9967 if (mono_class_has_failure (klass))
9970 mono_loader_lock ();
9971 klass->exception_type = ex_type;
9973 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9974 mono_loader_unlock ();
9980 * mono_class_get_exception_data:
9982 * Return the exception_data property of KLASS.
9984 * LOCKING: Acquires the loader lock.
9987 mono_class_get_exception_data (MonoClass *klass)
9989 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9993 * mono_classes_init:
9995 * Initialize the resources used by this module.
9998 mono_classes_init (void)
10000 mono_os_mutex_init (&classes_mutex);
10002 mono_counters_register ("Inflated methods size",
10003 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10004 mono_counters_register ("Inflated classes",
10005 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
10006 mono_counters_register ("Inflated classes size",
10007 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10008 mono_counters_register ("MonoClass size",
10009 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10010 mono_counters_register ("MonoClassExt size",
10011 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10015 * mono_classes_cleanup:
10017 * Free the resources used by this module.
10020 mono_classes_cleanup (void)
10022 if (global_interface_bitset)
10023 mono_bitset_free (global_interface_bitset);
10024 global_interface_bitset = NULL;
10025 mono_os_mutex_destroy (&classes_mutex);
10029 * mono_class_get_exception_for_failure:
10030 * @klass: class in which the failure was detected
10032 * Return a constructed MonoException than the caller can then throw
10033 * using mono_raise_exception - or NULL if no failure is present (or
10034 * doesn't result in an exception).
10037 mono_class_get_exception_for_failure (MonoClass *klass)
10039 gpointer exception_data = mono_class_get_exception_data (klass);
10041 switch (mono_class_get_failure(klass)) {
10042 case MONO_EXCEPTION_TYPE_LOAD: {
10045 char *str = mono_type_get_full_name (klass);
10046 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10047 name = mono_string_new (mono_domain_get (), str);
10049 ex = mono_get_exception_type_load (name, astr);
10053 case MONO_EXCEPTION_MISSING_METHOD: {
10054 char *class_name = (char *)exception_data;
10055 char *assembly_name = class_name + strlen (class_name) + 1;
10057 return mono_get_exception_missing_method (class_name, assembly_name);
10059 case MONO_EXCEPTION_MISSING_FIELD: {
10060 char *class_name = (char *)exception_data;
10061 char *member_name = class_name + strlen (class_name) + 1;
10063 return mono_get_exception_missing_field (class_name, member_name);
10065 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10066 char *msg_format = (char *)exception_data;
10067 char *assembly_name = msg_format + strlen (msg_format) + 1;
10068 char *msg = g_strdup_printf (msg_format, assembly_name);
10071 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10077 case MONO_EXCEPTION_BAD_IMAGE: {
10078 return mono_get_exception_bad_image_format ((const char *)exception_data);
10080 case MONO_EXCEPTION_INVALID_PROGRAM: {
10081 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10084 MonoLoaderError *error;
10087 error = mono_loader_get_last_error ();
10088 if (error != NULL){
10089 ex = mono_loader_error_prepare_exception (error);
10093 /* TODO - handle other class related failures */
10100 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10102 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10103 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10105 if (outer_klass == inner_klass)
10107 inner_klass = inner_klass->nested_in;
10108 } while (inner_klass);
10113 mono_class_get_generic_type_definition (MonoClass *klass)
10115 return klass->generic_class ? klass->generic_class->container_class : klass;
10119 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10121 * Generic instantiations are ignored for all super types of @klass.
10123 * Visibility checks ignoring generic instantiations.
10126 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10129 klass = mono_class_get_generic_type_definition (klass);
10130 parent = mono_class_get_generic_type_definition (parent);
10131 mono_class_setup_supertypes (klass);
10133 for (i = 0; i < klass->idepth; ++i) {
10134 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10140 * Subtype can only access parent members with family protection if the site object
10141 * is subclass of Subtype. For example:
10142 * class A { protected int x; }
10144 * void valid_access () {
10148 * void invalid_access () {
10155 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10157 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10160 if (context_klass == NULL)
10162 /*if access_klass is not member_klass context_klass must be type compat*/
10163 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10169 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10172 if (accessing == accessed)
10174 if (!accessed || !accessing)
10177 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10178 * anywhere so untrusted friends are not safe to access platform's code internals */
10179 if (mono_security_core_clr_enabled ()) {
10180 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10184 mono_assembly_load_friends (accessed);
10185 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10186 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10187 /* Be conservative with checks */
10188 if (!friend_->name)
10190 if (strcmp (accessing->aname.name, friend_->name))
10192 if (friend_->public_key_token [0]) {
10193 if (!accessing->aname.public_key_token [0])
10195 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10204 * If klass is a generic type or if it is derived from a generic type, return the
10205 * MonoClass of the generic definition
10206 * Returns NULL if not found
10209 get_generic_definition_class (MonoClass *klass)
10212 if (klass->generic_class && klass->generic_class->container_class)
10213 return klass->generic_class->container_class;
10214 klass = klass->parent;
10220 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10223 for (i = 0; i < ginst->type_argc; ++i) {
10224 MonoType *type = ginst->type_argv[i];
10225 switch (type->type) {
10226 case MONO_TYPE_SZARRAY:
10227 if (!can_access_type (access_klass, type->data.klass))
10230 case MONO_TYPE_ARRAY:
10231 if (!can_access_type (access_klass, type->data.array->eklass))
10234 case MONO_TYPE_PTR:
10235 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10238 case MONO_TYPE_CLASS:
10239 case MONO_TYPE_VALUETYPE:
10240 case MONO_TYPE_GENERICINST:
10241 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10251 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10255 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10258 if (access_klass->element_class && !access_klass->enumtype)
10259 access_klass = access_klass->element_class;
10261 if (member_klass->element_class && !member_klass->enumtype)
10262 member_klass = member_klass->element_class;
10264 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10266 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10269 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10272 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10275 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10278 /*Non nested type with nested visibility. We just fail it.*/
10279 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10282 switch (access_level) {
10283 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10284 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10286 case TYPE_ATTRIBUTE_PUBLIC:
10289 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10292 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10293 return is_nesting_type (member_klass, access_klass);
10295 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10296 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10298 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10299 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10301 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10302 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10303 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10305 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10306 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10307 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10312 /* FIXME: check visibility of type, too */
10314 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10316 MonoClass *member_generic_def;
10317 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10320 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10321 access_klass->generic_container) &&
10322 (member_generic_def = get_generic_definition_class (member_klass))) {
10323 MonoClass *access_container;
10325 if (access_klass->generic_container)
10326 access_container = access_klass;
10328 access_container = access_klass->generic_class->container_class;
10330 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10334 /* Partition I 8.5.3.2 */
10335 /* the access level values are the same for fields and methods */
10336 switch (access_level) {
10337 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10338 /* same compilation unit */
10339 return access_klass->image == member_klass->image;
10340 case FIELD_ATTRIBUTE_PRIVATE:
10341 return access_klass == member_klass;
10342 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10343 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10344 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10347 case FIELD_ATTRIBUTE_ASSEMBLY:
10348 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10349 case FIELD_ATTRIBUTE_FAMILY:
10350 if (is_valid_family_access (access_klass, member_klass, context_klass))
10353 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10354 if (is_valid_family_access (access_klass, member_klass, context_klass))
10356 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10357 case FIELD_ATTRIBUTE_PUBLIC:
10364 * mono_method_can_access_field:
10365 * @method: Method that will attempt to access the field
10366 * @field: the field to access
10368 * Used to determine if a method is allowed to access the specified field.
10370 * Returns: TRUE if the given @method is allowed to access the @field while following
10371 * the accessibility rules of the CLI.
10374 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10376 /* FIXME: check all overlapping fields */
10377 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10379 MonoClass *nested = method->klass->nested_in;
10381 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10384 nested = nested->nested_in;
10391 * mono_method_can_access_method:
10392 * @method: Method that will attempt to access the other method
10393 * @called: the method that we want to probe for accessibility.
10395 * Used to determine if the @method is allowed to access the specified @called method.
10397 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10398 * the accessibility rules of the CLI.
10401 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10403 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10405 MonoClass *nested = method->klass->nested_in;
10407 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10410 nested = nested->nested_in;
10415 * with generics calls to explicit interface implementations can be expressed
10416 * directly: the method is private, but we must allow it. This may be opening
10417 * a hole or the generics code should handle this differently.
10418 * Maybe just ensure the interface type is public.
10420 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10426 * mono_method_can_access_method_full:
10427 * @method: The caller method
10428 * @called: The called method
10429 * @context_klass: The static type on stack of the owner @called object used
10431 * This function must be used with instance calls, as they have more strict family accessibility.
10432 * It can be used with static methods, but context_klass should be NULL.
10434 * Returns: TRUE if caller have proper visibility and acessibility to @called
10437 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10439 MonoClass *access_class = method->klass;
10440 MonoClass *member_class = called->klass;
10441 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10443 MonoClass *nested = access_class->nested_in;
10445 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10448 nested = nested->nested_in;
10455 can = can_access_type (access_class, member_class);
10457 MonoClass *nested = access_class->nested_in;
10459 can = can_access_type (nested, member_class);
10462 nested = nested->nested_in;
10469 if (called->is_inflated) {
10470 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10471 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10480 * mono_method_can_access_field_full:
10481 * @method: The caller method
10482 * @field: The accessed field
10483 * @context_klass: The static type on stack of the owner @field object used
10485 * This function must be used with instance fields, as they have more strict family accessibility.
10486 * It can be used with static fields, but context_klass should be NULL.
10488 * Returns: TRUE if caller have proper visibility and acessibility to @field
10491 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10493 MonoClass *access_class = method->klass;
10494 MonoClass *member_class = field->parent;
10495 /* FIXME: check all overlapping fields */
10496 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10498 MonoClass *nested = access_class->nested_in;
10500 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10503 nested = nested->nested_in;
10510 can = can_access_type (access_class, member_class);
10512 MonoClass *nested = access_class->nested_in;
10514 can = can_access_type (nested, member_class);
10517 nested = nested->nested_in;
10527 * mono_class_can_access_class:
10528 * @source_class: The source class
10529 * @target_class: The accessed class
10531 * This function returns is @target_class is visible to @source_class
10533 * Returns: TRUE if source have proper visibility and acessibility to target
10536 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10538 return can_access_type (source_class, target_class);
10542 * mono_type_is_valid_enum_basetype:
10543 * @type: The MonoType to check
10545 * Returns: TRUE if the type can be used as the basetype of an enum
10547 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10548 switch (type->type) {
10551 case MONO_TYPE_BOOLEAN:
10554 case MONO_TYPE_CHAR:
10568 * mono_class_is_valid_enum:
10569 * @klass: An enum class to be validated
10571 * This method verify the required properties an enum should have.
10573 * Returns: TRUE if the informed enum class is valid
10575 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10576 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10577 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10579 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10580 MonoClassField * field;
10581 gpointer iter = NULL;
10582 gboolean found_base_field = FALSE;
10584 g_assert (klass->enumtype);
10585 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10586 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10590 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10593 while ((field = mono_class_get_fields (klass, &iter))) {
10594 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10595 if (found_base_field)
10597 found_base_field = TRUE;
10598 if (!mono_type_is_valid_enum_basetype (field->type))
10603 if (!found_base_field)
10606 if (klass->method.count > 0)
10613 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10615 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10619 * mono_class_setup_interface_id:
10621 * Initializes MonoClass::interface_id if required.
10623 * LOCKING: Acquires the loader lock.
10626 mono_class_setup_interface_id (MonoClass *klass)
10628 mono_loader_lock ();
10629 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10630 klass->interface_id = mono_get_unique_iid (klass);
10631 mono_loader_unlock ();
10635 * mono_class_alloc_ext:
10637 * Allocate klass->ext if not already done.
10640 mono_class_alloc_ext (MonoClass *klass)
10647 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10648 mono_image_lock (klass->image);
10649 mono_memory_barrier ();
10652 class_ext_size += sizeof (MonoClassExt);
10653 mono_image_unlock (klass->image);
10657 * mono_class_setup_interfaces:
10659 * Initialize klass->interfaces/interfaces_count.
10660 * LOCKING: Acquires the loader lock.
10661 * This function can fail the type.
10664 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10666 int i, interface_count;
10667 MonoClass **interfaces;
10669 mono_error_init (error);
10671 if (klass->interfaces_inited)
10674 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10675 MonoType *args [1];
10677 /* generic IList, ICollection, IEnumerable */
10678 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10679 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10681 args [0] = &klass->element_class->byval_arg;
10682 interfaces [0] = mono_class_bind_generic_parameters (
10683 mono_defaults.generic_ilist_class, 1, args, FALSE);
10684 if (interface_count > 1)
10685 interfaces [1] = mono_class_bind_generic_parameters (
10686 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10687 } else if (klass->generic_class) {
10688 MonoClass *gklass = klass->generic_class->container_class;
10690 mono_class_setup_interfaces (gklass, error);
10691 if (!mono_error_ok (error)) {
10692 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10696 interface_count = gklass->interface_count;
10697 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10698 for (i = 0; i < interface_count; i++) {
10699 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10700 if (!mono_error_ok (error)) {
10701 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10706 interface_count = 0;
10710 mono_image_lock (klass->image);
10712 if (!klass->interfaces_inited) {
10713 klass->interface_count = interface_count;
10714 klass->interfaces = interfaces;
10716 mono_memory_barrier ();
10718 klass->interfaces_inited = TRUE;
10721 mono_image_unlock (klass->image);
10725 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10727 MonoClass *klass = field->parent;
10728 MonoImage *image = klass->image;
10729 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10730 int field_idx = field - klass->fields;
10732 mono_error_init (error);
10735 MonoClassField *gfield = >d->fields [field_idx];
10736 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10737 if (!mono_error_ok (error)) {
10738 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10739 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10742 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10743 if (!mono_error_ok (error)) {
10744 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10745 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10749 guint32 cols [MONO_FIELD_SIZE];
10750 MonoGenericContainer *container = NULL;
10751 int idx = klass->field.first + field_idx;
10753 /*FIXME, in theory we do not lazy load SRE fields*/
10754 g_assert (!image_is_dynamic (image));
10756 if (klass->generic_container) {
10757 container = klass->generic_container;
10759 container = gtd->generic_container;
10760 g_assert (container);
10763 /* klass->field.first and idx points into the fieldptr table */
10764 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10766 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10767 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10768 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10772 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10774 mono_metadata_decode_value (sig, &sig);
10775 /* FIELD signature == 0x06 */
10776 g_assert (*sig == 0x06);
10778 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10779 if (!field->type) {
10780 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10781 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10787 mono_field_resolve_flags (MonoClassField *field)
10789 MonoClass *klass = field->parent;
10790 MonoImage *image = klass->image;
10791 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10792 int field_idx = field - klass->fields;
10796 MonoClassField *gfield = >d->fields [field_idx];
10797 return mono_field_get_flags (gfield);
10799 int idx = klass->field.first + field_idx;
10801 /*FIXME, in theory we do not lazy load SRE fields*/
10802 g_assert (!image_is_dynamic (image));
10804 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10809 * mono_class_setup_basic_field_info:
10810 * @class: The class to initialize
10812 * Initializes the klass->fields array of fields.
10813 * Aquires the loader lock.
10816 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10818 mono_loader_lock ();
10819 mono_class_setup_basic_field_info (klass);
10820 mono_loader_unlock ();
10824 * mono_class_get_fields_lazy:
10825 * @klass: the MonoClass to act on
10827 * This routine is an iterator routine for retrieving the fields in a class.
10828 * Only minimal information about fields are loaded. Accessors must be used
10829 * for all MonoClassField returned.
10831 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10832 * iterate over all of the elements. When no more values are
10833 * available, the return value is NULL.
10835 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10838 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10840 MonoClassField* field;
10844 mono_class_setup_basic_field_info_locking (klass);
10845 if (!klass->fields)
10847 /* start from the first */
10848 if (klass->field.count) {
10849 *iter = &klass->fields [0];
10850 return (MonoClassField *)*iter;
10856 field = (MonoClassField *)*iter;
10858 if (field < &klass->fields [klass->field.count]) {
10860 return (MonoClassField *)*iter;
10866 mono_class_full_name (MonoClass *klass)
10868 return mono_type_full_name (&klass->byval_arg);
10871 /* Declare all shared lazy type lookup functions */
10872 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)