2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size, class_ext_count;
59 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
61 /* Low level lock which protects data structures in this module */
62 static mono_mutex_t classes_mutex;
64 /* Function supplied by the runtime to find classes by name using information from the AOT file */
65 static MonoGetClassFromName get_class_from_name = NULL;
67 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
68 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
69 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
70 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
71 static int generic_array_methods (MonoClass *klass);
72 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
74 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
75 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
76 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
77 static guint32 mono_field_resolve_flags (MonoClassField *field);
78 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
79 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
81 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
82 static gpointer mono_class_get_exception_data (const MonoClass *klass);
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
88 Given the following type hierarchy:
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
115 static MonoNativeTlsKey init_pending_tls_id;
120 mono_locks_os_acquire (&classes_mutex, ClassesLock);
124 classes_unlock (void)
126 mono_locks_os_release (&classes_mutex, ClassesLock);
130 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
133 enable_gclass_recording (void)
135 ++record_gclass_instantiation;
139 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
142 disable_gclass_recording (gclass_record_func func, void *user_data)
144 GSList **head = &gclass_recorded_list;
146 g_assert (record_gclass_instantiation > 0);
147 --record_gclass_instantiation;
150 GSList *node = *head;
151 if (func ((MonoClass*)node->data, user_data)) {
153 g_slist_free_1 (node);
159 /* We automatically discard all recorded gclasses when disabled. */
160 if (!record_gclass_instantiation && gclass_recorded_list) {
161 g_slist_free (gclass_recorded_list);
162 gclass_recorded_list = NULL;
167 * mono_class_from_typeref:
168 * @image: a MonoImage
169 * @type_token: a TypeRef token
171 * Creates the MonoClass* structure representing the type defined by
172 * the typeref token valid inside @image.
173 * Returns: The MonoClass* representing the typeref token, NULL ifcould
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
180 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 * mono_class_from_typeref_checked:
187 * @image: a MonoImage
188 * @type_token: a TypeRef token
189 * @error: error return code, if any.
191 * Creates the MonoClass* structure representing the type defined by
192 * the typeref token valid inside @image.
194 * Returns: The MonoClass* representing the typeref token, NULL if it could
195 * not be loaded with the @error value filled with the information about the
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 guint32 cols [MONO_TYPEREF_SIZE];
202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
204 const char *name, *nspace;
205 MonoClass *res = NULL;
208 mono_error_init (error);
210 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
213 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220 case MONO_RESOLUTION_SCOPE_MODULE:
222 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223 This is not the observed behavior of existing implementations.
224 The defacto behavior is that it's just a typedef in disguise.
226 /* a typedef in disguise */
227 res = mono_class_from_name_checked (image, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_MODULEREF:
231 module = mono_image_load_module_checked (image, idx, error);
233 res = mono_class_from_name_checked (module, nspace, name, error);
236 case MONO_RESOLUTION_SCOPE_TYPEREF: {
237 MonoClass *enclosing;
240 if (idx == mono_metadata_token_index (type_token)) {
241 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
245 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
246 return_val_if_nok (error, NULL);
248 MonoClassExt *ext = mono_class_get_ext (enclosing);
249 if (enclosing->nested_classes_inited && ext) {
250 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
251 for (tmp = ext->nested_classes; tmp; tmp = tmp->next) {
252 res = (MonoClass *)tmp->data;
253 if (strcmp (res->name, name) == 0)
257 /* Don't call mono_class_init as we might've been called by it recursively */
258 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
260 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
261 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
262 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
264 if (strcmp (nname, name) == 0)
265 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
267 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
270 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
273 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
277 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
278 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
282 if (!image->references || !image->references [idx - 1])
283 mono_assembly_load_reference (image, idx - 1);
284 g_assert (image->references [idx - 1]);
286 /* If the assembly did not load, register this as a type load exception */
287 if (image->references [idx - 1] == REFERENCE_MISSING){
288 MonoAssemblyName aname;
291 mono_assembly_get_assemblyref (image, idx - 1, &aname);
292 human_name = mono_stringify_assembly_name (&aname);
293 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
297 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
300 /* Generic case, should be avoided for when a better error is possible. */
301 if (!res && mono_error_ok (error)) {
302 char *name = mono_class_name_from_token (image, type_token);
303 char *assembly = mono_assembly_name_from_token (image, type_token);
304 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
311 mono_image_memdup (MonoImage *image, void *data, guint size)
313 void *res = mono_image_alloc (image, size);
314 memcpy (res, data, size);
318 /* Copy everything mono_metadata_free_array free. */
320 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
323 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
325 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
327 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
329 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
331 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
333 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
338 /* Copy everything mono_metadata_free_method_signature free. */
340 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
344 sig = mono_metadata_signature_dup_full (image, sig);
346 sig->ret = mono_metadata_type_dup (image, sig->ret);
347 for (i = 0; i < sig->param_count; ++i)
348 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
354 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
356 MonoAssembly *ta = klass->image->assembly;
359 name = mono_stringify_assembly_name (&ta->aname);
360 g_string_append_printf (str, ", %s", name);
365 mono_type_name_check_byref (MonoType *type, GString *str)
368 g_string_append_c (str, '&');
372 * mono_identifier_escape_type_name_chars:
373 * @str: a destination string
374 * @identifier: an IDENTIFIER in internal form
378 * The displayed form of the identifier is appended to str.
380 * The displayed form of an identifier has the characters ,+&*[]\
381 * that have special meaning in type names escaped with a preceeding
382 * backslash (\) character.
385 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
391 // reserve space for common case: there will be no escaped characters.
392 g_string_set_size(str, n + strlen(identifier));
393 g_string_set_size(str, n);
395 for (const char* s = identifier; *s != 0 ; s++) {
404 g_string_append_c (str, '\\');
405 g_string_append_c (str, *s);
408 g_string_append_c (str, *s);
416 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
417 MonoTypeNameFormat format)
421 switch (type->type) {
422 case MONO_TYPE_ARRAY: {
423 int i, rank = type->data.array->rank;
424 MonoTypeNameFormat nested_format;
426 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
427 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
429 mono_type_get_name_recurse (
430 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
431 g_string_append_c (str, '[');
433 g_string_append_c (str, '*');
434 for (i = 1; i < rank; i++)
435 g_string_append_c (str, ',');
436 g_string_append_c (str, ']');
438 mono_type_name_check_byref (type, str);
440 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
441 _mono_type_get_assembly_name (type->data.array->eklass, str);
444 case MONO_TYPE_SZARRAY: {
445 MonoTypeNameFormat nested_format;
447 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
448 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
450 mono_type_get_name_recurse (
451 &type->data.klass->byval_arg, str, FALSE, nested_format);
452 g_string_append (str, "[]");
454 mono_type_name_check_byref (type, str);
456 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
457 _mono_type_get_assembly_name (type->data.klass, str);
460 case MONO_TYPE_PTR: {
461 MonoTypeNameFormat nested_format;
463 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
464 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
466 mono_type_get_name_recurse (
467 type->data.type, str, FALSE, nested_format);
468 g_string_append_c (str, '*');
470 mono_type_name_check_byref (type, str);
472 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
473 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
478 if (!mono_generic_param_info (type->data.generic_param))
479 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
481 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
483 mono_type_name_check_byref (type, str);
487 klass = mono_class_from_mono_type (type);
488 if (klass->nested_in) {
489 mono_type_get_name_recurse (
490 &klass->nested_in->byval_arg, str, TRUE, format);
491 if (format == MONO_TYPE_NAME_FORMAT_IL)
492 g_string_append_c (str, '.');
494 g_string_append_c (str, '+');
495 } else if (*klass->name_space) {
496 if (format == MONO_TYPE_NAME_FORMAT_IL)
497 g_string_append (str, klass->name_space);
499 mono_identifier_escape_type_name_chars (str, klass->name_space);
500 g_string_append_c (str, '.');
502 if (format == MONO_TYPE_NAME_FORMAT_IL) {
503 char *s = strchr (klass->name, '`');
504 int len = s ? s - klass->name : strlen (klass->name);
505 g_string_append_len (str, klass->name, len);
507 mono_identifier_escape_type_name_chars (str, klass->name);
511 if (mono_class_is_ginst (klass)) {
512 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
513 MonoGenericInst *inst = gclass->context.class_inst;
514 MonoTypeNameFormat nested_format;
517 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
518 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
520 if (format == MONO_TYPE_NAME_FORMAT_IL)
521 g_string_append_c (str, '<');
523 g_string_append_c (str, '[');
524 for (i = 0; i < inst->type_argc; i++) {
525 MonoType *t = inst->type_argv [i];
528 g_string_append_c (str, ',');
529 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
530 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
531 g_string_append_c (str, '[');
532 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
533 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
534 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
535 g_string_append_c (str, ']');
537 if (format == MONO_TYPE_NAME_FORMAT_IL)
538 g_string_append_c (str, '>');
540 g_string_append_c (str, ']');
541 } else if (mono_class_is_gtd (klass) &&
542 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
543 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
546 if (format == MONO_TYPE_NAME_FORMAT_IL)
547 g_string_append_c (str, '<');
549 g_string_append_c (str, '[');
550 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
552 g_string_append_c (str, ',');
553 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
555 if (format == MONO_TYPE_NAME_FORMAT_IL)
556 g_string_append_c (str, '>');
558 g_string_append_c (str, ']');
561 mono_type_name_check_byref (type, str);
563 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
564 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
565 _mono_type_get_assembly_name (klass, str);
571 * mono_type_get_name_full:
573 * @format: the format for the return string.
576 * Returns: The string representation in a number of formats:
578 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
579 * returned in the formatrequired by System.Reflection, this is the
580 * inverse of mono_reflection_parse_type ().
582 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
583 * be used by the IL assembler.
585 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
587 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
590 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
594 result = g_string_new ("");
596 mono_type_get_name_recurse (type, result, FALSE, format);
598 return g_string_free (result, FALSE);
602 * mono_type_get_full_name:
605 * Returns: The string representation for type as required by System.Reflection.
606 * The inverse of mono_reflection_parse_type ().
609 mono_type_get_full_name (MonoClass *klass)
611 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
615 * mono_type_get_name:
618 * Returns: The string representation for type as it would be represented in IL code.
621 mono_type_get_name (MonoType *type)
623 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
627 * mono_type_get_underlying_type:
630 * Returns: The MonoType for the underlying integer type if @type
631 * is an enum and byref is false, otherwise the type itself.
634 mono_type_get_underlying_type (MonoType *type)
636 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
637 return mono_class_enum_basetype (type->data.klass);
638 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
639 return mono_class_enum_basetype (type->data.generic_class->container_class);
644 * mono_class_is_open_constructed_type:
647 * Returns: TRUE if type represents a generics open constructed type.
648 * IOW, not all type parameters required for the instantiation have
649 * been provided or it's a generic type definition.
651 * An open constructed type means it's a non realizable type. Not to
652 * be mixed up with an abstract type - we can't cast or dispatch to
653 * an open type, for example.
656 mono_class_is_open_constructed_type (MonoType *t)
662 case MONO_TYPE_SZARRAY:
663 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
664 case MONO_TYPE_ARRAY:
665 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
667 return mono_class_is_open_constructed_type (t->data.type);
668 case MONO_TYPE_GENERICINST:
669 return t->data.generic_class->context.class_inst->is_open;
670 case MONO_TYPE_CLASS:
671 case MONO_TYPE_VALUETYPE:
672 return mono_class_is_gtd (t->data.klass);
679 This is a simple function to catch the most common bad instances of generic types.
680 Specially those that might lead to further failures in the runtime.
683 is_valid_generic_argument (MonoType *type)
685 switch (type->type) {
687 //case MONO_TYPE_TYPEDBYREF:
695 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
697 mono_error_init (error);
699 switch (type->type) {
700 case MONO_TYPE_MVAR: {
702 int num = mono_type_get_generic_param_num (type);
703 MonoGenericInst *inst = context->method_inst;
706 if (num >= inst->type_argc) {
707 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
708 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
709 num, info ? info->name : "", inst->type_argc);
713 if (!is_valid_generic_argument (inst->type_argv [num])) {
714 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
715 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
716 num, info ? info->name : "", inst->type_argv [num]->type);
720 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
721 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
722 * ->byref and ->attrs from @type are propagated to the returned type.
724 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
725 nt->byref = type->byref;
726 nt->attrs = type->attrs;
729 case MONO_TYPE_VAR: {
731 int num = mono_type_get_generic_param_num (type);
732 MonoGenericInst *inst = context->class_inst;
735 if (num >= inst->type_argc) {
736 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
737 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
738 num, info ? info->name : "", inst->type_argc);
741 if (!is_valid_generic_argument (inst->type_argv [num])) {
742 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
743 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
744 num, info ? info->name : "", inst->type_argv [num]->type);
747 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
748 nt->byref = type->byref;
749 nt->attrs = type->attrs;
752 case MONO_TYPE_SZARRAY: {
753 MonoClass *eclass = type->data.klass;
754 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
755 if (!inflated || !mono_error_ok (error))
757 nt = mono_metadata_type_dup (image, type);
758 nt->data.klass = mono_class_from_mono_type (inflated);
759 mono_metadata_free_type (inflated);
762 case MONO_TYPE_ARRAY: {
763 MonoClass *eclass = type->data.array->eklass;
764 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
765 if (!inflated || !mono_error_ok (error))
767 nt = mono_metadata_type_dup (image, type);
768 nt->data.array->eklass = mono_class_from_mono_type (inflated);
769 mono_metadata_free_type (inflated);
772 case MONO_TYPE_GENERICINST: {
773 MonoGenericClass *gclass = type->data.generic_class;
774 MonoGenericInst *inst;
776 if (!gclass->context.class_inst->is_open)
779 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
780 return_val_if_nok (error, NULL);
782 if (inst != gclass->context.class_inst)
783 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
785 if (gclass == type->data.generic_class)
788 nt = mono_metadata_type_dup (image, type);
789 nt->data.generic_class = gclass;
792 case MONO_TYPE_CLASS:
793 case MONO_TYPE_VALUETYPE: {
794 MonoClass *klass = type->data.klass;
795 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
796 MonoGenericInst *inst;
797 MonoGenericClass *gclass = NULL;
803 /* We can't use context->class_inst directly, since it can have more elements */
804 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
805 return_val_if_nok (error, NULL);
807 if (inst == container->context.class_inst)
810 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
812 nt = mono_metadata_type_dup (image, type);
813 nt->type = MONO_TYPE_GENERICINST;
814 nt->data.generic_class = gclass;
824 mono_generic_class_get_context (MonoGenericClass *gclass)
826 return &gclass->context;
830 mono_class_get_context (MonoClass *klass)
832 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
833 return gklass ? mono_generic_class_get_context (gklass) : NULL;
837 * mono_class_inflate_generic_type_with_mempool:
838 * @mempool: a mempool
840 * @context: a generics context
841 * @error: error context
843 * The same as mono_class_inflate_generic_type, but allocates the MonoType
844 * from mempool if it is non-NULL. If it is NULL, the MonoType is
845 * allocated on the heap and is owned by the caller.
846 * The returned type can potentially be the same as TYPE, so it should not be
847 * modified by the caller, and it should be freed using mono_metadata_free_type ().
850 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
852 MonoType *inflated = NULL;
853 mono_error_init (error);
856 inflated = inflate_generic_type (image, type, context, error);
857 return_val_if_nok (error, NULL);
860 MonoType *shared = mono_metadata_get_shared_type (type);
865 return mono_metadata_type_dup (image, type);
869 mono_stats.inflated_type_count++;
874 * mono_class_inflate_generic_type:
876 * @context: a generics context
878 * If @type is a generic type and @context is not NULL, instantiate it using the
879 * generics context @context.
881 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
882 * on the heap and is owned by the caller. Returns NULL on error.
884 * @deprecated Please use mono_class_inflate_generic_type_checked instead
887 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
891 result = mono_class_inflate_generic_type_checked (type, context, &error);
892 mono_error_cleanup (&error);
897 * mono_class_inflate_generic_type:
899 * @context: a generics context
900 * @error: error context to use
902 * If @type is a generic type and @context is not NULL, instantiate it using the
903 * generics context @context.
905 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
906 * on the heap and is owned by the caller.
909 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
911 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
915 * mono_class_inflate_generic_type_no_copy:
917 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
921 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
923 MonoType *inflated = NULL;
925 mono_error_init (error);
927 inflated = inflate_generic_type (image, type, context, error);
928 return_val_if_nok (error, NULL);
934 mono_stats.inflated_type_count++;
939 * mono_class_inflate_generic_class:
941 * Inflate the class @gklass with @context. Set @error on failure.
944 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
949 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
950 return_val_if_nok (error, NULL);
952 res = mono_class_from_mono_type (inflated);
953 mono_metadata_free_type (inflated);
958 static MonoGenericContext
959 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
961 MonoGenericInst *class_inst = NULL;
962 MonoGenericInst *method_inst = NULL;
963 MonoGenericContext res = { NULL, NULL };
965 mono_error_init (error);
967 if (context->class_inst) {
968 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
969 if (!mono_error_ok (error))
973 if (context->method_inst) {
974 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
975 if (!mono_error_ok (error))
979 res.class_inst = class_inst;
980 res.method_inst = method_inst;
986 * mono_class_inflate_generic_method:
987 * @method: a generic method
988 * @context: a generics context
990 * Instantiate the generic method @method using the generics context @context.
992 * Returns: The new instantiated method
995 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
997 return mono_class_inflate_generic_method_full (method, NULL, context);
1001 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1003 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1007 * mono_class_inflate_generic_method_full:
1009 * Instantiate method @method with the generic context @context.
1010 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1011 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1014 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1017 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1018 if (!mono_error_ok (&error))
1019 /*FIXME do proper error handling - on this case, kill this function. */
1020 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1026 * mono_class_inflate_generic_method_full_checked:
1027 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1030 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1033 MonoMethodInflated *iresult, *cached;
1034 MonoMethodSignature *sig;
1035 MonoGenericContext tmp_context;
1037 mono_error_init (error);
1039 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1040 while (method->is_inflated) {
1041 MonoGenericContext *method_context = mono_method_get_context (method);
1042 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1044 tmp_context = inflate_generic_context (method_context, context, error);
1045 return_val_if_nok (error, NULL);
1047 context = &tmp_context;
1049 if (mono_metadata_generic_context_equal (method_context, context))
1052 method = imethod->declaring;
1056 * A method only needs to be inflated if the context has argument for which it is
1059 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1060 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1063 if (!((method->is_generic && context->method_inst) ||
1064 (mono_class_is_gtd (method->klass) && context->class_inst)))
1067 iresult = g_new0 (MonoMethodInflated, 1);
1068 iresult->context = *context;
1069 iresult->declaring = method;
1071 if (!context->method_inst && method->is_generic)
1072 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1074 if (!context->class_inst) {
1075 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1076 if (mono_class_is_gtd (iresult->declaring->klass))
1077 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1079 /* This can happen with some callers like mono_object_get_virtual_method () */
1080 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1081 iresult->context.class_inst = NULL;
1083 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1086 mono_image_set_lock (set);
1087 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1088 mono_image_set_unlock (set);
1092 return (MonoMethod*)cached;
1095 mono_stats.inflated_method_count++;
1097 inflated_methods_size += sizeof (MonoMethodInflated);
1099 sig = mono_method_signature (method);
1101 char *name = mono_type_get_full_name (method->klass);
1102 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1108 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1110 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1113 result = (MonoMethod *) iresult;
1114 result->is_inflated = TRUE;
1115 result->is_generic = FALSE;
1116 result->sre_method = FALSE;
1117 result->signature = NULL;
1119 if (method->wrapper_type) {
1120 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1121 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1122 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1124 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1125 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1128 if (iresult->context.method_inst) {
1129 /* Set the generic_container of the result to the generic_container of method */
1130 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1132 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1133 result->is_generic = 1;
1134 mono_method_set_generic_container (result, generic_container);
1139 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1140 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1144 if (mono_class_is_gtd (method->klass))
1145 result->klass = klass_hint;
1147 if (!result->klass) {
1148 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1149 if (!mono_error_ok (error))
1152 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1154 mono_metadata_free_type (inflated);
1158 * FIXME: This should hold, but it doesn't:
1160 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1161 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1162 * g_assert (result->is_generic);
1165 * Fixing this here causes other things to break, hence a very
1166 * ugly hack in mini-trampolines.c - see
1167 * is_generic_method_definition().
1171 mono_image_set_lock (set);
1172 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1174 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1175 iresult->owner = set;
1178 mono_image_set_unlock (set);
1180 return (MonoMethod*)cached;
1188 * mono_get_inflated_method:
1190 * Obsolete. We keep it around since it's mentioned in the public API.
1193 mono_get_inflated_method (MonoMethod *method)
1199 * mono_method_get_context_general:
1201 * @uninflated: handle uninflated methods?
1203 * Returns the generic context of a method or NULL if it doesn't have
1204 * one. For an inflated method that's the context stored in the
1205 * method. Otherwise it's in the method's generic container or in the
1206 * generic container of the method's class.
1209 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1211 if (method->is_inflated) {
1212 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1213 return &imethod->context;
1217 if (method->is_generic)
1218 return &(mono_method_get_generic_container (method)->context);
1219 if (mono_class_is_gtd (method->klass))
1220 return &mono_class_get_generic_container (method->klass)->context;
1225 * mono_method_get_context:
1228 * Returns the generic context for method if it's inflated, otherwise
1232 mono_method_get_context (MonoMethod *method)
1234 return mono_method_get_context_general (method, FALSE);
1238 * mono_method_get_generic_container:
1240 * Returns the generic container of METHOD, which should be a generic method definition.
1241 * Returns NULL if METHOD is not a generic method definition.
1242 * LOCKING: Acquires the loader lock.
1244 MonoGenericContainer*
1245 mono_method_get_generic_container (MonoMethod *method)
1247 MonoGenericContainer *container;
1249 if (!method->is_generic)
1252 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1253 g_assert (container);
1259 * mono_method_set_generic_container:
1261 * Sets the generic container of METHOD to CONTAINER.
1262 * LOCKING: Acquires the image lock.
1265 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1267 g_assert (method->is_generic);
1269 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1273 * mono_class_find_enum_basetype:
1274 * @class: The enum class
1276 * Determine the basetype of an enum by iterating through its fields. We do this
1277 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1280 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1282 MonoGenericContainer *container = NULL;
1283 MonoImage *m = klass->image;
1284 const int top = mono_class_get_field_count (klass);
1285 int i, first_field_idx;
1287 g_assert (klass->enumtype);
1289 mono_error_init (error);
1291 container = mono_class_try_get_generic_container (klass);
1292 if (mono_class_is_ginst (klass)) {
1293 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1295 container = mono_class_get_generic_container (gklass);
1296 g_assert (container);
1300 * Fetch all the field information.
1302 first_field_idx = mono_class_get_first_field_idx (klass);
1303 for (i = 0; i < top; i++){
1305 guint32 cols [MONO_FIELD_SIZE];
1306 int idx = first_field_idx + i;
1309 /* first_field_idx and idx points into the fieldptr table */
1310 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1312 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1315 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1316 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1320 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1321 mono_metadata_decode_value (sig, &sig);
1322 /* FIELD signature == 0x06 */
1324 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1328 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1332 if (mono_class_is_ginst (klass)) {
1333 //FIXME do we leak here?
1334 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1335 if (!mono_error_ok (error))
1337 ftype->attrs = cols [MONO_FIELD_FLAGS];
1342 mono_error_set_type_load_class (error, klass, "Could not find base type");
1349 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1352 mono_type_has_exceptions (MonoType *type)
1354 switch (type->type) {
1355 case MONO_TYPE_CLASS:
1356 case MONO_TYPE_VALUETYPE:
1357 case MONO_TYPE_SZARRAY:
1358 return mono_class_has_failure (type->data.klass);
1359 case MONO_TYPE_ARRAY:
1360 return mono_class_has_failure (type->data.array->eklass);
1361 case MONO_TYPE_GENERICINST:
1362 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1369 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1371 g_assert (mono_class_has_failure (klass));
1372 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1373 mono_error_set_from_boxed (oerror, box);
1380 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1384 mono_class_alloc (MonoClass *klass, int size)
1386 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1388 return mono_image_set_alloc (gklass->owner, size);
1390 return mono_image_alloc (klass->image, size);
1394 mono_class_alloc0 (MonoClass *klass, int size)
1398 res = mono_class_alloc (klass, size);
1399 memset (res, 0, size);
1403 #define mono_class_new0(klass,struct_type, n_structs) \
1404 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1407 * mono_class_setup_basic_field_info:
1408 * @class: The class to initialize
1410 * Initializes the following fields in MonoClass:
1411 * * klass->fields (only field->parent and field->name)
1412 * * klass->field.count
1413 * * klass->first_field_idx
1414 * LOCKING: Acquires the loader lock
1417 mono_class_setup_basic_field_info (MonoClass *klass)
1419 MonoGenericClass *gklass;
1420 MonoClassField *field;
1421 MonoClassField *fields;
1429 gklass = mono_class_try_get_generic_class (klass);
1430 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1431 image = klass->image;
1434 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1436 * This happens when a generic instance of an unfinished generic typebuilder
1437 * is used as an element type for creating an array type. We can't initialize
1438 * the fields of this class using the fields of gklass, since gklass is not
1439 * finished yet, fields could be added to it later.
1445 mono_class_setup_basic_field_info (gtd);
1447 mono_loader_lock ();
1448 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1449 mono_loader_unlock ();
1452 top = mono_class_get_field_count (klass);
1454 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1457 * Fetch all the field information.
1459 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1460 for (i = 0; i < top; i++) {
1461 field = &fields [i];
1462 field->parent = klass;
1465 field->name = mono_field_get_name (>d->fields [i]);
1467 int idx = first_field_idx + i;
1468 /* first_field_idx and idx points into the fieldptr table */
1469 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1470 /* The name is needed for fieldrefs */
1471 field->name = mono_metadata_string_heap (image, name_idx);
1475 mono_memory_barrier ();
1477 mono_loader_lock ();
1479 klass->fields = fields;
1480 mono_loader_unlock ();
1484 * mono_class_set_failure_causedby_class:
1485 * @klass: the class that is failing
1486 * @caused_by: the class that caused the failure
1487 * @msg: Why @klass is failing.
1489 * If @caused_by has a failure, sets a TypeLoadException failure on
1490 * @klass with message "@msg, due to: {@caused_by message}".
1492 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1495 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1497 if (mono_class_has_failure (caused_by)) {
1498 MonoError cause_error;
1499 mono_error_init (&cause_error);
1500 mono_error_set_for_class_failure (&cause_error, caused_by);
1501 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1502 mono_error_cleanup (&cause_error);
1511 * mono_class_setup_fields:
1512 * @klass: The class to initialize
1514 * Initializes klass->fields, computes class layout and sizes.
1515 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1516 * Sets the following fields in @klass:
1517 * - all the fields initialized by mono_class_init_sizes ()
1518 * - element_class/cast_class (for enums)
1519 * - field->type/offset for all fields
1522 * LOCKING: Acquires the loader lock.
1525 mono_class_setup_fields (MonoClass *klass)
1528 MonoImage *m = klass->image;
1530 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1532 guint32 real_size = 0;
1533 guint32 packing_size = 0;
1535 gboolean explicit_size;
1536 MonoClassField *field;
1537 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1538 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1540 if (klass->fields_inited)
1543 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1545 * This happens when a generic instance of an unfinished generic typebuilder
1546 * is used as an element type for creating an array type. We can't initialize
1547 * the fields of this class using the fields of gklass, since gklass is not
1548 * finished yet, fields could be added to it later.
1553 mono_class_setup_basic_field_info (klass);
1554 top = mono_class_get_field_count (klass);
1557 mono_class_setup_fields (gtd);
1558 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1563 if (klass->parent) {
1564 /* For generic instances, klass->parent might not have been initialized */
1565 mono_class_init (klass->parent);
1566 mono_class_setup_fields (klass->parent);
1567 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1569 instance_size = klass->parent->instance_size;
1571 instance_size = sizeof (MonoObject);
1574 /* Get the real size */
1575 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1577 instance_size += real_size;
1580 * This function can recursively call itself.
1581 * Prevent infinite recursion by using a list in TLS.
1583 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1584 if (g_slist_find (init_list, klass))
1586 init_list = g_slist_prepend (init_list, klass);
1587 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1590 * Fetch all the field information.
1592 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1593 for (i = 0; i < top; i++) {
1594 int idx = first_field_idx + i;
1595 field = &klass->fields [i];
1598 mono_field_resolve_type (field, &error);
1599 if (!mono_error_ok (&error)) {
1600 /*mono_field_resolve_type already failed class*/
1601 mono_error_cleanup (&error);
1605 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1606 g_assert (field->type);
1609 if (mono_field_is_deleted (field))
1611 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1613 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1614 int offset = uoffset;
1616 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1617 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1620 if (offset < -1) { /*-1 is used to encode special static fields */
1621 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1624 if (mono_class_is_gtd (klass)) {
1625 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1629 if (mono_type_has_exceptions (field->type)) {
1630 char *class_name = mono_type_get_full_name (klass);
1631 char *type_name = mono_type_full_name (field->type);
1633 mono_class_set_type_load_failure (klass, "");
1634 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1635 g_free (class_name);
1639 /* The def_value of fields is compute lazily during vtable creation */
1642 if (!mono_class_has_failure (klass))
1643 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1645 init_list = g_slist_remove (init_list, klass);
1646 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1650 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1653 klass->instance_size = cached_info->instance_size;
1654 klass->sizes.class_size = cached_info->class_size;
1655 klass->packing_size = cached_info->packing_size;
1656 klass->min_align = cached_info->min_align;
1657 klass->blittable = cached_info->blittable;
1658 klass->has_references = cached_info->has_references;
1659 klass->has_static_refs = cached_info->has_static_refs;
1660 klass->no_special_static_fields = cached_info->no_special_static_fields;
1663 if (!klass->size_inited)
1664 mono_class_setup_fields (klass);
1669 * mono_class_init_sizes:
1671 * Initializes the size related fields of @klass without loading all field data if possible.
1672 * Sets the following fields in @klass:
1674 * - sizes.class_size
1681 * Can fail the class.
1683 * LOCKING: Acquires the loader lock.
1686 mono_class_init_sizes (MonoClass *klass)
1688 MonoCachedClassInfo cached_info;
1689 gboolean has_cached_info;
1691 if (klass->size_inited)
1694 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1696 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1700 * mono_type_get_basic_type_from_generic:
1703 * Returns a closed type corresponding to the possibly open type
1707 mono_type_get_basic_type_from_generic (MonoType *type)
1709 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1710 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1711 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1712 return &mono_defaults.object_class->byval_arg;
1717 class_has_references (MonoClass *klass)
1719 mono_class_init_sizes (klass);
1722 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1723 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1726 return klass->has_references;
1730 type_has_references (MonoClass *klass, MonoType *ftype)
1732 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1734 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1735 MonoGenericParam *gparam = ftype->data.generic_param;
1737 if (gparam->gshared_constraint)
1738 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1744 * mono_class_layout_fields:
1746 * @base_instance_size: base instance size
1749 * This contains the common code for computing the layout of classes and sizes.
1750 * This should only be called from mono_class_setup_fields () and
1751 * typebuilder_setup_fields ().
1753 * LOCKING: Acquires the loader lock
1756 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1759 const int top = mono_class_get_field_count (klass);
1760 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1761 guint32 pass, passes, real_size;
1762 gboolean gc_aware_layout = FALSE;
1763 gboolean has_static_fields = FALSE;
1764 gboolean has_references = FALSE;
1765 gboolean has_static_refs = FALSE;
1766 MonoClassField *field;
1768 int instance_size = base_instance_size;
1769 int class_size, min_align;
1773 * We want to avoid doing complicated work inside locks, so we compute all the required
1774 * information and write it to @klass inside a lock.
1776 if (klass->fields_inited)
1779 if ((packing_size & 0xffffff00) != 0) {
1780 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1784 if (klass->parent) {
1785 min_align = klass->parent->min_align;
1786 /* we use | since it may have been set already */
1787 has_references = klass->has_references | klass->parent->has_references;
1791 /* We can't really enable 16 bytes alignment until the GC supports it.
1792 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1793 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1794 Bug #506144 is an example of this issue.
1796 if (klass->simd_type)
1801 * When we do generic sharing we need to have layout
1802 * information for open generic classes (either with a generic
1803 * context containing type variables or with a generic
1804 * container), so we don't return in that case anymore.
1807 if (klass->enumtype) {
1808 for (i = 0; i < top; i++) {
1809 field = &klass->fields [i];
1810 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1811 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1816 if (!mono_class_enum_basetype (klass)) {
1817 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1823 * Enable GC aware auto layout: in this mode, reference
1824 * fields are grouped together inside objects, increasing collector
1826 * Requires that all classes whose layout is known to native code be annotated
1827 * with [StructLayout (LayoutKind.Sequential)]
1828 * Value types have gc_aware_layout disabled by default, as per
1829 * what the default is for other runtimes.
1831 /* corlib is missing [StructLayout] directives in many places */
1832 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1833 if (!klass->valuetype)
1834 gc_aware_layout = TRUE;
1837 /* Compute klass->blittable */
1840 blittable = klass->parent->blittable;
1841 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1843 for (i = 0; i < top; i++) {
1844 field = &klass->fields [i];
1846 if (mono_field_is_deleted (field))
1848 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1851 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1854 MonoClass *field_class = mono_class_from_mono_type (field->type);
1856 mono_class_setup_fields (field_class);
1857 if (mono_class_has_failure (field_class)) {
1858 MonoError field_error;
1859 mono_error_init (&field_error);
1860 mono_error_set_for_class_failure (&field_error, field_class);
1861 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1862 mono_error_cleanup (&field_error);
1866 if (!field_class || !field_class->blittable)
1870 if (klass->enumtype)
1871 blittable = klass->element_class->blittable;
1873 if (mono_class_has_failure (klass))
1875 if (klass == mono_defaults.string_class)
1878 /* Compute klass->has_references */
1880 * Process non-static fields first, since static fields might recursively
1881 * refer to the class itself.
1883 for (i = 0; i < top; i++) {
1886 field = &klass->fields [i];
1888 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1889 ftype = mono_type_get_underlying_type (field->type);
1890 ftype = mono_type_get_basic_type_from_generic (ftype);
1891 if (type_has_references (klass, ftype))
1892 has_references = TRUE;
1897 * Compute field layout and total size (not considering static fields)
1899 field_offsets = g_new0 (int, top);
1900 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1902 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1903 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1904 if (gc_aware_layout)
1909 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1912 if (klass->parent) {
1913 mono_class_setup_fields (klass->parent);
1914 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1916 real_size = klass->parent->instance_size;
1918 real_size = sizeof (MonoObject);
1921 for (pass = 0; pass < passes; ++pass) {
1922 for (i = 0; i < top; i++){
1927 field = &klass->fields [i];
1929 if (mono_field_is_deleted (field))
1931 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1934 ftype = mono_type_get_underlying_type (field->type);
1935 ftype = mono_type_get_basic_type_from_generic (ftype);
1936 if (gc_aware_layout) {
1937 if (type_has_references (klass, ftype)) {
1946 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1947 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1948 /* This field is a hack inserted by MCS to empty structures */
1952 size = mono_type_size (field->type, &align);
1954 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1955 align = packing_size ? MIN (packing_size, align): align;
1956 /* if the field has managed references, we need to force-align it
1959 if (type_has_references (klass, ftype))
1960 align = MAX (align, sizeof (gpointer));
1962 min_align = MAX (align, min_align);
1963 field_offsets [i] = real_size;
1965 field_offsets [i] += align - 1;
1966 field_offsets [i] &= ~(align - 1);
1968 /*TypeBuilders produce all sort of weird things*/
1969 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1970 real_size = field_offsets [i] + size;
1973 instance_size = MAX (real_size, instance_size);
1975 if (instance_size & (min_align - 1)) {
1976 instance_size += min_align - 1;
1977 instance_size &= ~(min_align - 1);
1981 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1985 for (i = 0; i < top; i++) {
1990 field = &klass->fields [i];
1993 * There must be info about all the fields in a type if it
1994 * uses explicit layout.
1996 if (mono_field_is_deleted (field))
1998 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2001 size = mono_type_size (field->type, &align);
2002 align = packing_size ? MIN (packing_size, align): align;
2003 min_align = MAX (align, min_align);
2006 /* Already set by typebuilder_setup_fields () */
2007 field_offsets [i] = field->offset + sizeof (MonoObject);
2009 int idx = first_field_idx + i;
2011 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2012 field_offsets [i] = offset + sizeof (MonoObject);
2014 ftype = mono_type_get_underlying_type (field->type);
2015 ftype = mono_type_get_basic_type_from_generic (ftype);
2016 if (type_has_references (klass, ftype)) {
2017 if (field_offsets [i] % sizeof (gpointer)) {
2018 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2025 real_size = MAX (real_size, size + field_offsets [i]);
2028 if (klass->has_references) {
2029 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2031 /* Check for overlapping reference and non-reference fields */
2032 for (i = 0; i < top; i++) {
2035 field = &klass->fields [i];
2037 if (mono_field_is_deleted (field))
2039 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2041 ftype = mono_type_get_underlying_type (field->type);
2042 if (MONO_TYPE_IS_REFERENCE (ftype))
2043 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2045 for (i = 0; i < top; i++) {
2046 field = &klass->fields [i];
2048 if (mono_field_is_deleted (field))
2050 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2053 // FIXME: Too much code does this
2055 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2056 mono_class_set_type_load_failure (klass, "Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field_offsets [i]);
2060 g_free (ref_bitmap);
2063 instance_size = MAX (real_size, instance_size);
2064 if (instance_size & (min_align - 1)) {
2065 instance_size += min_align - 1;
2066 instance_size &= ~(min_align - 1);
2072 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2074 * This leads to all kinds of problems with nested structs, so only
2075 * enable it when a MONO_DEBUG property is set.
2077 * For small structs, set min_align to at least the struct size to improve
2078 * performance, and since the JIT memset/memcpy code assumes this and generates
2079 * unaligned accesses otherwise. See #78990 for a testcase.
2081 if (mono_align_small_structs && top) {
2082 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2083 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2087 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2088 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2089 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2090 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2092 /* Publish the data */
2093 mono_loader_lock ();
2094 if (klass->instance_size && !klass->image->dynamic) {
2095 /* Might be already set using cached info */
2096 if (klass->instance_size != instance_size) {
2097 /* Emit info to help debugging */
2098 g_print ("%s %s\n", klass->name_space, klass->name);
2099 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2100 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2101 g_print ("%d %d\n", klass->min_align, min_align);
2102 for (i = 0; i < top; ++i) {
2103 field = &klass->fields [i];
2104 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2105 printf (" %s %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i]);
2108 g_assert (klass->instance_size == instance_size);
2110 klass->instance_size = instance_size;
2112 klass->blittable = blittable;
2113 klass->has_references = has_references;
2114 klass->packing_size = packing_size;
2115 klass->min_align = min_align;
2116 for (i = 0; i < top; ++i) {
2117 field = &klass->fields [i];
2118 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2119 klass->fields [i].offset = field_offsets [i];
2122 mono_memory_barrier ();
2123 klass->size_inited = 1;
2124 mono_loader_unlock ();
2127 * Compute static field layout and size
2128 * Static fields can reference the class itself, so this has to be
2129 * done after instance_size etc. are initialized.
2132 for (i = 0; i < top; i++) {
2136 field = &klass->fields [i];
2138 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2140 if (mono_field_is_deleted (field))
2143 if (mono_type_has_exceptions (field->type)) {
2144 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2148 has_static_fields = TRUE;
2150 size = mono_type_size (field->type, &align);
2151 field_offsets [i] = class_size;
2152 /*align is always non-zero here*/
2153 field_offsets [i] += align - 1;
2154 field_offsets [i] &= ~(align - 1);
2155 class_size = field_offsets [i] + size;
2158 if (has_static_fields && class_size == 0)
2159 /* Simplify code which depends on class_size != 0 if the class has static fields */
2162 /* Compute klass->has_static_refs */
2163 has_static_refs = FALSE;
2164 for (i = 0; i < top; i++) {
2167 field = &klass->fields [i];
2169 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2170 ftype = mono_type_get_underlying_type (field->type);
2171 ftype = mono_type_get_basic_type_from_generic (ftype);
2172 if (type_has_references (klass, ftype))
2173 has_static_refs = TRUE;
2177 /*valuetypes can't be neither bigger than 1Mb or empty. */
2178 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2179 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2181 /* Publish the data */
2182 mono_loader_lock ();
2184 klass->sizes.class_size = class_size;
2185 klass->has_static_refs = has_static_refs;
2186 for (i = 0; i < top; ++i) {
2187 field = &klass->fields [i];
2189 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2190 field->offset = field_offsets [i];
2193 mono_memory_barrier ();
2194 klass->fields_inited = 1;
2195 mono_loader_unlock ();
2197 g_free (field_offsets);
2201 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2205 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2206 method->klass = klass;
2207 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2208 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2209 method->signature = sig;
2210 method->name = name;
2213 if (name [0] == '.') {
2214 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2216 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2222 * mono_class_setup_methods:
2225 * Initializes the 'methods' array in CLASS.
2226 * Calling this method should be avoided if possible since it allocates a lot
2227 * of long-living MonoMethod structures.
2228 * Methods belonging to an interface are assigned a sequential slot starting
2231 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2234 mono_class_setup_methods (MonoClass *klass)
2237 MonoMethod **methods;
2242 if (mono_class_is_ginst (klass)) {
2244 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2246 mono_class_init (gklass);
2247 if (!mono_class_has_failure (gklass))
2248 mono_class_setup_methods (gklass);
2249 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2252 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2253 count = mono_class_get_method_count (gklass);
2254 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2256 for (i = 0; i < count; i++) {
2257 methods [i] = mono_class_inflate_generic_method_full_checked (
2258 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2259 if (!mono_error_ok (&error)) {
2260 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2261 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2264 mono_error_cleanup (&error);
2268 } else if (klass->rank) {
2270 MonoMethod *amethod;
2271 MonoMethodSignature *sig;
2272 int count_generic = 0, first_generic = 0;
2274 gboolean jagged_ctor = FALSE;
2276 count = 3 + (klass->rank > 1? 2: 1);
2278 mono_class_setup_interfaces (klass, &error);
2279 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2281 if (klass->rank == 1 && klass->element_class->rank) {
2286 if (klass->interface_count) {
2287 count_generic = generic_array_methods (klass);
2288 first_generic = count;
2289 count += klass->interface_count * count_generic;
2292 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2294 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2295 sig->ret = &mono_defaults.void_class->byval_arg;
2296 sig->pinvoke = TRUE;
2297 sig->hasthis = TRUE;
2298 for (i = 0; i < klass->rank; ++i)
2299 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2301 amethod = create_array_method (klass, ".ctor", sig);
2302 methods [method_num++] = amethod;
2303 if (klass->rank > 1) {
2304 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2305 sig->ret = &mono_defaults.void_class->byval_arg;
2306 sig->pinvoke = TRUE;
2307 sig->hasthis = TRUE;
2308 for (i = 0; i < klass->rank * 2; ++i)
2309 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2311 amethod = create_array_method (klass, ".ctor", sig);
2312 methods [method_num++] = amethod;
2316 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2317 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2318 sig->ret = &mono_defaults.void_class->byval_arg;
2319 sig->pinvoke = TRUE;
2320 sig->hasthis = TRUE;
2321 for (i = 0; i < klass->rank + 1; ++i)
2322 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2323 amethod = create_array_method (klass, ".ctor", sig);
2324 methods [method_num++] = amethod;
2327 /* element Get (idx11, [idx2, ...]) */
2328 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2329 sig->ret = &klass->element_class->byval_arg;
2330 sig->pinvoke = TRUE;
2331 sig->hasthis = TRUE;
2332 for (i = 0; i < klass->rank; ++i)
2333 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2334 amethod = create_array_method (klass, "Get", sig);
2335 methods [method_num++] = amethod;
2336 /* element& Address (idx11, [idx2, ...]) */
2337 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2338 sig->ret = &klass->element_class->this_arg;
2339 sig->pinvoke = TRUE;
2340 sig->hasthis = TRUE;
2341 for (i = 0; i < klass->rank; ++i)
2342 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2343 amethod = create_array_method (klass, "Address", sig);
2344 methods [method_num++] = amethod;
2345 /* void Set (idx11, [idx2, ...], element) */
2346 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2347 sig->ret = &mono_defaults.void_class->byval_arg;
2348 sig->pinvoke = TRUE;
2349 sig->hasthis = TRUE;
2350 for (i = 0; i < klass->rank; ++i)
2351 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2352 sig->params [i] = &klass->element_class->byval_arg;
2353 amethod = create_array_method (klass, "Set", sig);
2354 methods [method_num++] = amethod;
2356 for (i = 0; i < klass->interface_count; i++)
2357 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2358 } else if (mono_class_has_static_metadata (klass)) {
2360 int first_idx = mono_class_get_first_method_idx (klass);
2362 count = mono_class_get_method_count (klass);
2363 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2364 for (i = 0; i < count; ++i) {
2365 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2366 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2368 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2369 mono_error_cleanup (&error);
2373 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2377 if (MONO_CLASS_IS_INTERFACE (klass)) {
2379 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2380 for (i = 0; i < count; ++i) {
2381 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2382 methods [i]->slot = slot++;
2386 mono_image_lock (klass->image);
2388 if (!klass->methods) {
2389 mono_class_set_method_count (klass, count);
2391 /* Needed because of the double-checking locking pattern */
2392 mono_memory_barrier ();
2394 klass->methods = methods;
2397 mono_image_unlock (klass->image);
2401 * mono_class_get_method_by_index:
2403 * Returns klass->methods [index], initializing klass->methods if neccesary.
2405 * LOCKING: Acquires the loader lock.
2408 mono_class_get_method_by_index (MonoClass *klass, int index)
2412 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2413 /* Avoid calling setup_methods () if possible */
2414 if (gklass && !klass->methods) {
2417 m = mono_class_inflate_generic_method_full_checked (
2418 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2419 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2421 * If setup_methods () is called later for this class, no duplicates are created,
2422 * since inflate_generic_method guarantees that only one instance of a method
2423 * is created for each context.
2426 mono_class_setup_methods (klass);
2427 g_assert (m == klass->methods [index]);
2431 mono_class_setup_methods (klass);
2432 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2434 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2435 return klass->methods [index];
2440 * mono_class_get_inflated_method:
2442 * Given an inflated class CLASS and a method METHOD which should be a method of
2443 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2446 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2448 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2451 g_assert (method->klass == gklass);
2453 mono_class_setup_methods (gklass);
2454 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2456 mcount = mono_class_get_method_count (gklass);
2457 for (i = 0; i < mcount; ++i) {
2458 if (gklass->methods [i] == method) {
2459 if (klass->methods) {
2460 return klass->methods [i];
2463 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2464 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2474 * mono_class_get_vtable_entry:
2476 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2477 * LOCKING: Acquires the loader lock.
2480 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2484 if (klass->rank == 1) {
2486 * szarrays do not overwrite any methods of Array, so we can avoid
2487 * initializing their vtables in some cases.
2489 mono_class_setup_vtable (klass->parent);
2490 if (offset < klass->parent->vtable_size)
2491 return klass->parent->vtable [offset];
2494 if (mono_class_is_ginst (klass)) {
2496 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2497 mono_class_setup_vtable (gklass);
2498 m = gklass->vtable [offset];
2500 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2501 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2503 mono_class_setup_vtable (klass);
2504 if (mono_class_has_failure (klass))
2506 m = klass->vtable [offset];
2513 * mono_class_get_vtable_size:
2515 * Return the vtable size for KLASS.
2518 mono_class_get_vtable_size (MonoClass *klass)
2520 mono_class_setup_vtable (klass);
2522 return klass->vtable_size;
2526 * mono_class_setup_properties:
2528 * Initialize klass->ext.property and klass->ext.properties.
2530 * This method can fail the class.
2533 mono_class_setup_properties (MonoClass *klass)
2535 guint startm, endm, i, j;
2536 guint32 cols [MONO_PROPERTY_SIZE];
2537 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2538 MonoProperty *properties;
2542 MonoClassExt *ext = mono_class_get_ext (klass);
2543 if (ext && ext->properties)
2546 if (mono_class_is_ginst (klass)) {
2547 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2549 mono_class_init (gklass);
2550 mono_class_setup_properties (gklass);
2551 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2554 MonoClassExt *gext = mono_class_get_ext (gklass);
2555 properties = mono_class_new0 (klass, MonoProperty, gext->property.count + 1);
2557 for (i = 0; i < gext->property.count; i++) {
2559 MonoProperty *prop = &properties [i];
2561 *prop = gext->properties [i];
2564 prop->get = mono_class_inflate_generic_method_full_checked (
2565 prop->get, klass, mono_class_get_context (klass), &error);
2567 prop->set = mono_class_inflate_generic_method_full_checked (
2568 prop->set, klass, mono_class_get_context (klass), &error);
2570 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2571 prop->parent = klass;
2574 first = gext->property.first;
2575 count = gext->property.count;
2577 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2578 count = last - first;
2581 mono_class_setup_methods (klass);
2582 if (mono_class_has_failure (klass))
2586 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2587 for (i = first; i < last; ++i) {
2588 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2589 properties [i - first].parent = klass;
2590 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2591 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2593 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2594 int first_idx = mono_class_get_first_method_idx (klass);
2595 for (j = startm; j < endm; ++j) {
2598 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2600 if (klass->image->uncompressed_metadata) {
2602 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2603 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2604 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2606 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2609 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2610 case METHOD_SEMANTIC_SETTER:
2611 properties [i - first].set = method;
2613 case METHOD_SEMANTIC_GETTER:
2614 properties [i - first].get = method;
2623 mono_class_alloc_ext (klass);
2624 ext = mono_class_get_ext (klass);
2626 mono_image_lock (klass->image);
2628 if (ext->properties) {
2629 /* We leak 'properties' which was allocated from the image mempool */
2630 mono_image_unlock (klass->image);
2634 ext->property.first = first;
2635 ext->property.count = count;
2637 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2638 mono_memory_barrier ();
2640 /* Leave this assignment as the last op in the function */
2641 ext->properties = properties;
2643 mono_image_unlock (klass->image);
2647 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2649 MonoMethod **om, **retval;
2652 for (om = methods, count = 0; *om; ++om, ++count)
2655 retval = g_new0 (MonoMethod*, count + 1);
2657 for (om = methods, count = 0; *om; ++om, ++count) {
2659 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2660 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2666 /*This method can fail the class.*/
2668 mono_class_setup_events (MonoClass *klass)
2671 guint startm, endm, i, j;
2672 guint32 cols [MONO_EVENT_SIZE];
2673 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2677 MonoClassExt *ext = mono_class_get_ext (klass);
2678 if (ext && ext->events)
2681 if (mono_class_is_ginst (klass)) {
2682 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2683 MonoGenericContext *context = NULL;
2685 mono_class_setup_events (gklass);
2686 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2689 MonoClassExt *gext = mono_class_get_ext (gklass);
2690 first = gext->event.first;
2691 count = gext->event.count;
2693 events = mono_class_new0 (klass, MonoEvent, count);
2696 context = mono_class_get_context (klass);
2698 for (i = 0; i < count; i++) {
2700 MonoEvent *event = &events [i];
2701 MonoEvent *gevent = &gext->events [i];
2703 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2705 event->parent = klass;
2706 event->name = gevent->name;
2707 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2708 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2709 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2710 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2711 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2712 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2714 #ifndef MONO_SMALL_CONFIG
2715 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2717 event->attrs = gevent->attrs;
2720 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2721 count = last - first;
2724 mono_class_setup_methods (klass);
2725 if (mono_class_has_failure (klass)) {
2730 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2731 for (i = first; i < last; ++i) {
2732 MonoEvent *event = &events [i - first];
2734 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2735 event->parent = klass;
2736 event->attrs = cols [MONO_EVENT_FLAGS];
2737 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2739 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2740 int first_idx = mono_class_get_first_method_idx (klass);
2741 for (j = startm; j < endm; ++j) {
2744 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2746 if (klass->image->uncompressed_metadata) {
2748 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2749 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2750 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2752 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2755 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2756 case METHOD_SEMANTIC_ADD_ON:
2757 event->add = method;
2759 case METHOD_SEMANTIC_REMOVE_ON:
2760 event->remove = method;
2762 case METHOD_SEMANTIC_FIRE:
2763 event->raise = method;
2765 case METHOD_SEMANTIC_OTHER: {
2766 #ifndef MONO_SMALL_CONFIG
2769 if (event->other == NULL) {
2770 event->other = g_new0 (MonoMethod*, 2);
2772 while (event->other [n])
2774 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2776 event->other [n] = method;
2777 /* NULL terminated */
2778 event->other [n + 1] = NULL;
2789 mono_class_alloc_ext (klass);
2790 ext = mono_class_get_ext (klass);
2792 mono_image_lock (klass->image);
2795 mono_image_unlock (klass->image);
2799 ext->event.first = first;
2800 ext->event.count = count;
2802 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2803 mono_memory_barrier ();
2805 /* Leave this assignment as the last op in the function */
2806 ext->events = events;
2808 mono_image_unlock (klass->image);
2812 * Global pool of interface IDs, represented as a bitset.
2813 * LOCKING: Protected by the classes lock.
2815 static MonoBitSet *global_interface_bitset = NULL;
2818 * mono_unload_interface_ids:
2819 * @bitset: bit set of interface IDs
2821 * When an image is unloaded, the interface IDs associated with
2822 * the image are put back in the global pool of IDs so the numbers
2826 mono_unload_interface_ids (MonoBitSet *bitset)
2829 mono_bitset_sub (global_interface_bitset, bitset);
2834 mono_unload_interface_id (MonoClass *klass)
2836 if (global_interface_bitset && klass->interface_id) {
2838 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2844 * mono_get_unique_iid:
2847 * Assign a unique integer ID to the interface represented by @class.
2848 * The ID will positive and as small as possible.
2849 * LOCKING: Acquires the classes lock.
2850 * Returns: The new ID.
2853 mono_get_unique_iid (MonoClass *klass)
2857 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2861 if (!global_interface_bitset) {
2862 global_interface_bitset = mono_bitset_new (128, 0);
2865 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2867 int old_size = mono_bitset_size (global_interface_bitset);
2868 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2869 mono_bitset_free (global_interface_bitset);
2870 global_interface_bitset = new_set;
2873 mono_bitset_set (global_interface_bitset, iid);
2874 /* set the bit also in the per-image set */
2875 if (!mono_class_is_ginst (klass)) {
2876 if (klass->image->interface_bitset) {
2877 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2878 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2879 mono_bitset_free (klass->image->interface_bitset);
2880 klass->image->interface_bitset = new_set;
2883 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2885 mono_bitset_set (klass->image->interface_bitset, iid);
2890 #ifndef MONO_SMALL_CONFIG
2891 if (mono_print_vtable) {
2893 char *type_name = mono_type_full_name (&klass->byval_arg);
2894 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2895 if (gklass && !gklass->context.class_inst->is_open) {
2896 generic_id = gklass->context.class_inst->id;
2897 g_assert (generic_id != 0);
2901 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2906 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2907 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2908 g_assert (iid < INT_MAX);
2913 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2918 mono_class_setup_interfaces (klass, error);
2919 return_if_nok (error);
2921 for (i = 0; i < klass->interface_count; i++) {
2922 ic = klass->interfaces [i];
2925 *res = g_ptr_array_new ();
2926 g_ptr_array_add (*res, ic);
2927 mono_class_init (ic);
2928 if (mono_class_has_failure (ic)) {
2929 mono_error_set_type_load_class (error, ic, "Error Loading class");
2933 collect_implemented_interfaces_aux (ic, res, error);
2934 return_if_nok (error);
2939 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2941 GPtrArray *res = NULL;
2943 collect_implemented_interfaces_aux (klass, &res, error);
2944 if (!mono_error_ok (error)) {
2946 g_ptr_array_free (res, TRUE);
2953 compare_interface_ids (const void *p_key, const void *p_element) {
2954 const MonoClass *key = (const MonoClass *)p_key;
2955 const MonoClass *element = *(const MonoClass **)p_element;
2957 return (key->interface_id - element->interface_id);
2960 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2962 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2963 MonoClass **result = (MonoClass **)mono_binary_search (
2965 klass->interfaces_packed,
2966 klass->interface_offsets_count,
2967 sizeof (MonoClass *),
2968 compare_interface_ids);
2970 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2977 * mono_class_interface_offset_with_variance:
2979 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2980 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2982 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2984 * FIXME figure out MS disambiguation rules and fix this function.
2987 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2988 int i = mono_class_interface_offset (klass, itf);
2989 *non_exact_match = FALSE;
2993 if (!mono_class_has_variant_generic_params (itf))
2996 for (i = 0; i < klass->interface_offsets_count; i++) {
2997 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2998 *non_exact_match = TRUE;
2999 return klass->interface_offsets_packed [i];
3007 print_implemented_interfaces (MonoClass *klass) {
3010 GPtrArray *ifaces = NULL;
3012 int ancestor_level = 0;
3014 name = mono_type_get_full_name (klass);
3015 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3018 for (i = 0; i < klass->interface_offsets_count; i++)
3019 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3020 klass->interfaces_packed [i]->interface_id,
3021 klass->interface_offsets_packed [i],
3022 mono_class_get_method_count (klass->interfaces_packed [i]),
3023 klass->interfaces_packed [i]->name_space,
3024 klass->interfaces_packed [i]->name );
3025 printf ("Interface flags: ");
3026 for (i = 0; i <= klass->max_interface_id; i++)
3027 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3028 printf ("(%d,T)", i);
3030 printf ("(%d,F)", i);
3032 printf ("Dump interface flags:");
3033 #ifdef COMPRESSED_INTERFACE_BITMAP
3035 const uint8_t* p = klass->interface_bitmap;
3036 i = klass->max_interface_id;
3038 printf (" %d x 00 %02X", p [0], p [1]);
3044 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3045 printf (" %02X", klass->interface_bitmap [i]);
3048 while (klass != NULL) {
3049 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3050 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3051 if (!mono_error_ok (&error)) {
3052 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3053 mono_error_cleanup (&error);
3054 } else if (ifaces) {
3055 for (i = 0; i < ifaces->len; i++) {
3056 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3057 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3058 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3060 mono_class_interface_offset (klass, ic),
3061 mono_class_get_method_count (ic),
3065 g_ptr_array_free (ifaces, TRUE);
3068 klass = klass->parent;
3073 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3076 args [0] = &arg0->byval_arg;
3078 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3082 array_class_get_if_rank (MonoClass *klass, guint rank)
3084 return rank ? mono_array_class_get (klass, rank) : klass;
3088 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3090 valuetype_types [0] = eclass;
3091 if (eclass == mono_defaults.int16_class)
3092 valuetype_types [1] = mono_defaults.uint16_class;
3093 else if (eclass == mono_defaults.uint16_class)
3094 valuetype_types [1] = mono_defaults.int16_class;
3095 else if (eclass == mono_defaults.int32_class)
3096 valuetype_types [1] = mono_defaults.uint32_class;
3097 else if (eclass == mono_defaults.uint32_class)
3098 valuetype_types [1] = mono_defaults.int32_class;
3099 else if (eclass == mono_defaults.int64_class)
3100 valuetype_types [1] = mono_defaults.uint64_class;
3101 else if (eclass == mono_defaults.uint64_class)
3102 valuetype_types [1] = mono_defaults.int64_class;
3103 else if (eclass == mono_defaults.byte_class)
3104 valuetype_types [1] = mono_defaults.sbyte_class;
3105 else if (eclass == mono_defaults.sbyte_class)
3106 valuetype_types [1] = mono_defaults.byte_class;
3107 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3108 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3111 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3112 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3113 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3114 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3115 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3117 /* this won't be needed once bug #325495 is completely fixed
3118 * though we'll need something similar to know which interfaces to allow
3119 * in arrays when they'll be lazyly created
3121 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3122 * MS returns diferrent types based on which instance is called. For example:
3123 * object obj = new byte[10][];
3124 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3125 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3128 * Fixing this should kill quite some code, save some bits and improve compatibility.
3131 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3133 MonoClass *eclass = klass->element_class;
3134 MonoClass* generic_icollection_class;
3135 MonoClass* generic_ienumerable_class;
3136 MonoClass* generic_ienumerator_class;
3137 MonoClass* generic_ireadonlylist_class;
3138 MonoClass* generic_ireadonlycollection_class;
3139 MonoClass *valuetype_types[2] = { NULL, NULL };
3140 MonoClass **interfaces = NULL;
3141 int i, nifaces, interface_count, real_count, original_rank;
3143 gboolean internal_enumerator;
3144 gboolean eclass_is_valuetype;
3146 if (!mono_defaults.generic_ilist_class) {
3150 internal_enumerator = FALSE;
3151 eclass_is_valuetype = FALSE;
3152 original_rank = eclass->rank;
3153 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3154 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3155 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3157 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3159 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3160 original_rank = eclass->rank;
3162 eclass = eclass->element_class;
3163 internal_enumerator = TRUE;
3164 *is_enumerator = TRUE;
3172 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3173 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3175 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3177 generic_icollection_class = mono_class_get_generic_icollection_class ();
3178 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3179 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3180 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3181 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3183 mono_class_init (eclass);
3186 * Arrays in 2.0 need to implement a number of generic interfaces
3187 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3188 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3189 * We collect the types needed to build the
3190 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3191 * the generic interfaces needed to implement.
3193 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3194 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3196 if (eclass->valuetype) {
3197 nifaces = generic_ireadonlylist_class ? 5 : 3;
3198 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3200 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3201 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3202 if (internal_enumerator) {
3204 if (valuetype_types [1])
3208 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3209 interfaces [0] = valuetype_types [0];
3210 if (valuetype_types [1])
3211 interfaces [nifaces] = valuetype_types [1];
3213 eclass_is_valuetype = TRUE;
3216 int idepth = eclass->idepth;
3217 if (!internal_enumerator)
3219 nifaces = generic_ireadonlylist_class ? 2 : 3;
3221 // FIXME: This doesn't seem to work/required for generic params
3222 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3223 mono_class_setup_interface_offsets (eclass);
3225 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3226 /* we add object for interfaces and the supertypes for the other
3227 * types. The last of the supertypes is the element class itself which we
3228 * already created the explicit interfaces for (so we include it for IEnumerator
3229 * and exclude it for arrays).
3231 if (MONO_CLASS_IS_INTERFACE (eclass))
3234 interface_count += idepth;
3235 if (eclass->rank && eclass->element_class->valuetype) {
3236 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3237 if (valuetype_types [1])
3240 /* IList, ICollection, IEnumerable, IReadOnlyList */
3241 interface_count *= nifaces;
3242 real_count = interface_count;
3243 if (internal_enumerator) {
3244 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3245 if (valuetype_types [1])
3248 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3249 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3250 interfaces [0] = mono_defaults.object_class;
3254 for (i = 0; i < idepth; i++) {
3255 mono_class_init (eclass->supertypes [i]);
3256 interfaces [j] = eclass->supertypes [i];
3260 if (all_interfaces) {
3261 for (i = 0; i < eclass->interface_offsets_count; i++) {
3262 interfaces [j] = eclass->interfaces_packed [i];
3266 for (i = 0; i < eclass->interface_count; i++) {
3267 interfaces [j] = eclass->interfaces [i];
3271 if (valuetype_types [1]) {
3272 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3277 /* instantiate the generic interfaces */
3278 for (i = 0; i < interface_count; i += nifaces) {
3279 MonoClass *iface = interfaces [i];
3281 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3282 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3284 if (eclass->valuetype) {
3285 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3286 if (generic_ireadonlylist_class) {
3287 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3288 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3291 if (!generic_ireadonlylist_class)
3292 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3295 if (internal_enumerator) {
3297 /* instantiate IEnumerator<iface> */
3298 for (i = 0; i < interface_count; i++) {
3299 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3301 j = interface_count;
3302 if (!eclass_is_valuetype) {
3303 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3304 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3307 for (i = 0; i < eclass->idepth; i++) {
3308 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3312 for (i = 0; i < eclass->interface_offsets_count; i++) {
3313 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3317 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3319 if (valuetype_types [1])
3320 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3324 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3325 for (i = 0; i < real_count; ++i) {
3326 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3327 g_print ("%s implements %s\n", type_name, name);
3338 find_array_interface (MonoClass *klass, const char *name)
3341 for (i = 0; i < klass->interface_count; ++i) {
3342 if (strcmp (klass->interfaces [i]->name, name) == 0)
3349 * Return the number of virtual methods.
3350 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3351 * Return -1 on failure.
3352 * FIXME It would be nice if this information could be cached somewhere.
3355 count_virtual_methods (MonoClass *klass)
3357 int i, mcount, vcount = 0;
3359 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3361 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3362 mono_class_setup_methods (klass);
3363 if (mono_class_has_failure (klass))
3366 mcount = mono_class_get_method_count (klass);
3367 for (i = 0; i < mcount; ++i) {
3368 flags = klass->methods [i]->flags;
3369 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3373 int first_idx = mono_class_get_first_method_idx (klass);
3374 mcount = mono_class_get_method_count (klass);
3375 for (i = 0; i < mcount; ++i) {
3376 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3378 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3386 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3394 m = (l + num_ifaces) / 2;
3395 if (interfaces_full [m] == ic)
3397 if (l == num_ifaces)
3399 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3408 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3410 int i = find_interface (num_ifaces, interfaces_full, ic);
3412 return interface_offsets_full [i];
3417 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3419 int i = find_interface (num_ifaces, interfaces_full, ic);
3423 interface_offsets_full [i] = offset;
3426 for (i = 0; i < num_ifaces; ++i) {
3427 if (interfaces_full [i]) {
3429 if (interfaces_full [i]->interface_id < ic->interface_id)
3432 while (end < num_ifaces && interfaces_full [end]) end++;
3433 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3434 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3436 interfaces_full [i] = ic;
3437 interface_offsets_full [i] = offset;
3443 #ifdef COMPRESSED_INTERFACE_BITMAP
3446 * Compressed interface bitmap design.
3448 * Interface bitmaps take a large amount of memory, because their size is
3449 * linear with the maximum interface id assigned in the process (each interface
3450 * is assigned a unique id as it is loaded). The number of interface classes
3451 * is high because of the many implicit interfaces implemented by arrays (we'll
3452 * need to lazy-load them in the future).
3453 * Most classes implement a very small number of interfaces, so the bitmap is
3454 * sparse. This bitmap needs to be checked by interface casts, so access to the
3455 * needed bit must be fast and doable with few jit instructions.
3457 * The current compression format is as follows:
3458 * *) it is a sequence of one or more two-byte elements
3459 * *) the first byte in the element is the count of empty bitmap bytes
3460 * at the current bitmap position
3461 * *) the second byte in the element is an actual bitmap byte at the current
3464 * As an example, the following compressed bitmap bytes:
3465 * 0x07 0x01 0x00 0x7
3466 * correspond to the following bitmap:
3467 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3469 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3470 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3471 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3475 * mono_compress_bitmap:
3476 * @dest: destination buffer
3477 * @bitmap: bitmap buffer
3478 * @size: size of @bitmap in bytes
3480 * This is a mono internal function.
3481 * The @bitmap data is compressed into a format that is small but
3482 * still searchable in few instructions by the JIT and runtime.
3483 * The compressed data is stored in the buffer pointed to by the
3484 * @dest array. Passing a #NULL value for @dest allows to just compute
3485 * the size of the buffer.
3486 * This compression algorithm assumes the bits set in the bitmap are
3487 * few and far between, like in interface bitmaps.
3488 * Returns: The size of the compressed bitmap in bytes.
3491 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3495 const uint8_t *end = bitmap + size;
3496 while (bitmap < end) {
3497 if (*bitmap || numz == 255) {
3521 * mono_class_interface_match:
3522 * @bitmap: a compressed bitmap buffer
3523 * @id: the index to check in the bitmap
3525 * This is a mono internal function.
3526 * Checks if a bit is set in a compressed interface bitmap. @id must
3527 * be already checked for being smaller than the maximum id encoded in the
3530 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3534 mono_class_interface_match (const uint8_t *bitmap, int id)
3537 id -= bitmap [0] * 8;
3541 return bitmap [1] & (1 << id);
3550 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3551 * LOCKING: Acquires the loader lock.
3554 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3558 int i, j, num_ifaces;
3560 MonoClass **interfaces_full = NULL;
3561 int *interface_offsets_full = NULL;
3563 GPtrArray **ifaces_array = NULL;
3564 int interface_offsets_count;
3565 MonoClass **array_interfaces = NULL;
3566 int num_array_interfaces;
3567 int is_enumerator = FALSE;
3569 mono_loader_lock ();
3571 mono_class_setup_supertypes (klass);
3573 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3574 * implicit interfaces have the property that they are assigned the same slot in the
3575 * vtables for compatible interfaces
3577 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3579 /* compute maximum number of slots and maximum interface id */
3581 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3582 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3583 for (j = 0; j < klass->idepth; j++) {
3584 k = klass->supertypes [j];
3586 num_ifaces += k->interface_count;
3587 for (i = 0; i < k->interface_count; i++) {
3588 ic = k->interfaces [i];
3590 mono_class_init (ic);
3592 if (max_iid < ic->interface_id)
3593 max_iid = ic->interface_id;
3595 ifaces = mono_class_get_implemented_interfaces (k, &error);
3596 if (!mono_error_ok (&error)) {
3597 char *name = mono_type_get_full_name (k);
3598 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3600 mono_error_cleanup (&error);
3605 num_ifaces += ifaces->len;
3606 for (i = 0; i < ifaces->len; ++i) {
3607 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3608 if (max_iid < ic->interface_id)
3609 max_iid = ic->interface_id;
3611 ifaces_array [j] = ifaces;
3615 for (i = 0; i < num_array_interfaces; ++i) {
3616 ic = array_interfaces [i];
3617 mono_class_init (ic);
3618 if (max_iid < ic->interface_id)
3619 max_iid = ic->interface_id;
3622 if (MONO_CLASS_IS_INTERFACE (klass)) {
3624 if (max_iid < klass->interface_id)
3625 max_iid = klass->interface_id;
3628 /* compute vtable offset for interfaces */
3629 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3630 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3632 for (i = 0; i < num_ifaces; i++)
3633 interface_offsets_full [i] = -1;
3635 /* skip the current class */
3636 for (j = 0; j < klass->idepth - 1; j++) {
3637 k = klass->supertypes [j];
3638 ifaces = ifaces_array [j];
3641 for (i = 0; i < ifaces->len; ++i) {
3643 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3645 /*Force the sharing of interface offsets between parent and subtypes.*/
3646 io = mono_class_interface_offset (k, ic);
3648 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3653 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3654 ifaces = ifaces_array [klass->idepth - 1];
3656 for (i = 0; i < ifaces->len; ++i) {
3658 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3659 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3661 count = count_virtual_methods (ic);
3663 char *name = mono_type_get_full_name (ic);
3664 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3673 if (MONO_CLASS_IS_INTERFACE (klass))
3674 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3676 if (num_array_interfaces) {
3677 if (is_enumerator) {
3678 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3679 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3680 g_assert (ienumerator_offset >= 0);
3681 for (i = 0; i < num_array_interfaces; ++i) {
3682 ic = array_interfaces [i];
3683 if (strcmp (ic->name, "IEnumerator`1") == 0)
3684 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3686 g_assert_not_reached ();
3687 /*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);*/
3690 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3691 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3692 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3693 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3694 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3695 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3696 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3697 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3698 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3699 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3700 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3701 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3702 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3703 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3704 for (i = 0; i < num_array_interfaces; ++i) {
3706 ic = array_interfaces [i];
3707 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3708 offset = ilist_offset;
3709 else if (strcmp (ic->name, "ICollection`1") == 0)
3710 offset = icollection_offset;
3711 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3712 offset = ienumerable_offset;
3713 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3714 offset = ireadonlylist_offset;
3715 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3716 offset = ireadonlycollection_offset;
3718 g_assert_not_reached ();
3719 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3720 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3725 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3726 if (interface_offsets_full [i] != -1)
3727 interface_offsets_count ++;
3730 /* Publish the data */
3731 klass->max_interface_id = max_iid;
3733 * We might get called multiple times:
3734 * - mono_class_init ()
3735 * - mono_class_setup_vtable ().
3736 * - mono_class_setup_interface_offsets ().
3737 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3738 * means we have to overwrite those when called from other places (#4440).
3740 if (klass->interfaces_packed) {
3742 g_assert (klass->interface_offsets_count == interface_offsets_count);
3746 klass->interface_offsets_count = interface_offsets_count;
3747 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3748 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3749 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3750 #ifdef COMPRESSED_INTERFACE_BITMAP
3751 bitmap = g_malloc0 (bsize);
3753 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3755 for (i = 0; i < interface_offsets_count; i++) {
3756 guint32 id = interfaces_full [i]->interface_id;
3757 bitmap [id >> 3] |= (1 << (id & 7));
3758 klass->interfaces_packed [i] = interfaces_full [i];
3759 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3760 /*if (num_array_interfaces)
3761 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]);*/
3763 #ifdef COMPRESSED_INTERFACE_BITMAP
3764 i = mono_compress_bitmap (NULL, bitmap, bsize);
3765 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3766 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3769 klass->interface_bitmap = bitmap;
3773 mono_loader_unlock ();
3775 g_free (interfaces_full);
3776 g_free (interface_offsets_full);
3777 g_free (array_interfaces);
3778 for (i = 0; i < klass->idepth; i++) {
3779 ifaces = ifaces_array [i];
3781 g_ptr_array_free (ifaces, TRUE);
3783 g_free (ifaces_array);
3785 //printf ("JUST DONE: ");
3786 //print_implemented_interfaces (klass);
3792 * Setup interface offsets for interfaces.
3794 * - klass->max_interface_id
3795 * - klass->interface_offsets_count
3796 * - klass->interfaces_packed
3797 * - klass->interface_offsets_packed
3798 * - klass->interface_bitmap
3800 * This function can fail @class.
3803 mono_class_setup_interface_offsets (MonoClass *klass)
3805 setup_interface_offsets (klass, 0, FALSE);
3808 /*Checks if @klass has @parent as one of it's parents type gtd
3812 * Bar<T> : Foo<Bar<Bar<T>>>
3816 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3818 klass = mono_class_get_generic_type_definition (klass);
3819 parent = mono_class_get_generic_type_definition (parent);
3820 mono_class_setup_supertypes (klass);
3821 mono_class_setup_supertypes (parent);
3823 return klass->idepth >= parent->idepth &&
3824 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3828 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3830 MonoGenericInst *ginst;
3833 if (!mono_class_is_ginst (klass)) {
3834 mono_class_setup_vtable_full (klass, in_setup);
3835 return !mono_class_has_failure (klass);
3838 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3839 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3842 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3843 for (i = 0; i < ginst->type_argc; ++i) {
3845 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3847 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3848 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3849 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3851 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3852 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3860 * mono_class_setup_vtable:
3862 * Creates the generic vtable of CLASS.
3863 * Initializes the following fields in MonoClass:
3866 * Plus all the fields initialized by setup_interface_offsets ().
3867 * If there is an error during vtable construction, klass->has_failure
3868 * is set and details are stored in a MonoErrorBoxed.
3870 * LOCKING: Acquires the loader lock.
3873 mono_class_setup_vtable (MonoClass *klass)
3875 mono_class_setup_vtable_full (klass, NULL);
3879 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3882 MonoMethod **overrides;
3883 MonoGenericContext *context;
3891 if (MONO_CLASS_IS_INTERFACE (klass)) {
3892 /* This sets method->slot for all methods if this is an interface */
3893 mono_class_setup_methods (klass);
3897 if (mono_class_has_failure (klass))
3900 if (g_list_find (in_setup, klass))
3903 mono_loader_lock ();
3905 if (klass->vtable) {
3906 mono_loader_unlock ();
3910 mono_stats.generic_vtable_count ++;
3911 in_setup = g_list_prepend (in_setup, klass);
3913 if (mono_class_is_ginst (klass)) {
3914 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3915 mono_loader_unlock ();
3916 g_list_remove (in_setup, klass);
3920 context = mono_class_get_context (klass);
3921 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3923 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3924 type_token = klass->type_token;
3927 if (image_is_dynamic (klass->image)) {
3928 /* Generic instances can have zero method overrides without causing any harm.
3929 * This is true since we don't do layout all over again for them, we simply inflate
3930 * the layout of the parent.
3932 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3933 if (!is_ok (&error)) {
3934 mono_loader_unlock ();
3935 g_list_remove (in_setup, klass);
3936 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3937 mono_error_cleanup (&error);
3941 /* The following call fails if there are missing methods in the type */
3942 /* FIXME it's probably a good idea to avoid this for generic instances. */
3943 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3947 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3949 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3953 mono_loader_unlock ();
3954 g_list_remove (in_setup, klass);
3959 #define DEBUG_INTERFACE_VTABLE_CODE 0
3960 #define TRACE_INTERFACE_VTABLE_CODE 0
3961 #define VERIFY_INTERFACE_VTABLE_CODE 0
3962 #define VTABLE_SELECTOR (1)
3964 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3965 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3966 if (!(VTABLE_SELECTOR)) break; \
3970 #define DEBUG_INTERFACE_VTABLE(stmt)
3973 #if TRACE_INTERFACE_VTABLE_CODE
3974 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3975 if (!(VTABLE_SELECTOR)) break; \
3979 #define TRACE_INTERFACE_VTABLE(stmt)
3982 #if VERIFY_INTERFACE_VTABLE_CODE
3983 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3984 if (!(VTABLE_SELECTOR)) break; \
3988 #define VERIFY_INTERFACE_VTABLE(stmt)
3992 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3994 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3998 GString *res = g_string_new ("");
4000 g_string_append_c (res, '(');
4001 for (i = 0; i < sig->param_count; ++i) {
4003 g_string_append_c (res, ',');
4004 mono_type_get_desc (res, sig->params [i], include_namespace);
4006 g_string_append (res, ")=>");
4007 if (sig->ret != NULL) {
4008 mono_type_get_desc (res, sig->ret, include_namespace);
4010 g_string_append (res, "NULL");
4013 g_string_free (res, FALSE);
4017 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
4018 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
4019 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
4020 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4028 is_wcf_hack_disabled (void)
4030 static gboolean disabled;
4031 static gboolean inited = FALSE;
4033 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4040 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4042 MonoMethodSignature *cmsig, *imsig;
4043 if (strcmp (im->name, cm->name) == 0) {
4044 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4045 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4048 if (! slot_is_empty) {
4049 if (require_newslot) {
4050 if (! interface_is_explicitly_implemented_by_class) {
4051 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4054 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4055 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4059 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4062 cmsig = mono_method_signature (cm);
4063 imsig = mono_method_signature (im);
4064 if (!cmsig || !imsig) {
4065 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4069 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4070 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4071 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4072 TRACE_INTERFACE_VTABLE (printf ("]"));
4075 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4076 if (mono_security_core_clr_enabled ())
4077 mono_security_core_clr_check_override (klass, cm, im);
4079 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4080 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4081 char *body_name = mono_method_full_name (cm, TRUE);
4082 char *decl_name = mono_method_full_name (im, TRUE);
4083 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4091 MonoClass *ic = im->klass;
4092 const char *ic_name_space = ic->name_space;
4093 const char *ic_name = ic->name;
4096 if (! require_newslot) {
4097 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4100 if (cm->klass->rank == 0) {
4101 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4104 cmsig = mono_method_signature (cm);
4105 imsig = mono_method_signature (im);
4106 if (!cmsig || !imsig) {
4107 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4111 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4112 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4113 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4114 TRACE_INTERFACE_VTABLE (printf ("]"));
4117 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4118 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4121 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4122 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4125 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))) {
4126 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4130 subname = strstr (cm->name, ic_name_space);
4131 if (subname != cm->name) {
4132 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4135 subname += strlen (ic_name_space);
4136 if (subname [0] != '.') {
4137 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4141 if (strstr (subname, ic_name) != subname) {
4142 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4145 subname += strlen (ic_name);
4146 if (subname [0] != '.') {
4147 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4151 if (strcmp (subname, im->name) != 0) {
4152 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4156 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4157 if (mono_security_core_clr_enabled ())
4158 mono_security_core_clr_check_override (klass, cm, im);
4160 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4161 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4162 char *body_name = mono_method_full_name (cm, TRUE);
4163 char *decl_name = mono_method_full_name (im, TRUE);
4164 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4174 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4176 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4177 MonoMethod *method = key;
4178 MonoMethod *override = value;
4179 MonoClass *method_class = mono_method_get_class (method);
4180 MonoClass *override_class = mono_method_get_class (override);
4182 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4183 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4184 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4187 print_overrides (GHashTable *override_map, const char *message) {
4189 printf ("Override map \"%s\" START:\n", message);
4190 g_hash_table_foreach (override_map, foreach_override, NULL);
4191 printf ("Override map \"%s\" END.\n", message);
4193 printf ("Override map \"%s\" EMPTY.\n", message);
4197 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4198 char *full_name = mono_type_full_name (&klass->byval_arg);
4202 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4204 if (print_interfaces) {
4205 print_implemented_interfaces (klass);
4206 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4209 if (klass->parent) {
4210 parent_size = klass->parent->vtable_size;
4214 for (i = 0; i < size; ++i) {
4215 MonoMethod *cm = vtable [i];
4216 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4217 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4219 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4227 #if VERIFY_INTERFACE_VTABLE_CODE
4229 mono_method_try_get_vtable_index (MonoMethod *method)
4231 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4232 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4233 if (imethod->declaring->is_generic)
4234 return imethod->declaring->slot;
4236 return method->slot;
4240 mono_class_verify_vtable (MonoClass *klass)
4243 char *full_name = mono_type_full_name (&klass->byval_arg);
4245 printf ("*** Verifying VTable of class '%s' \n", full_name);
4249 if (!klass->methods)
4252 count = mono_class_method_count (klass);
4253 for (i = 0; i < count; ++i) {
4254 MonoMethod *cm = klass->methods [i];
4257 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4261 full_name = mono_method_full_name (cm, TRUE);
4263 slot = mono_method_try_get_vtable_index (cm);
4265 if (slot >= klass->vtable_size) {
4266 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4270 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4271 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4272 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4273 g_free (other_name);
4276 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4283 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
4286 char *method_signature;
4289 for (index = 0; index < onum; ++index) {
4290 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4291 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4293 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4294 type_name = mono_type_full_name (&klass->byval_arg);
4295 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4296 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4297 g_free (method_signature);
4299 mono_class_setup_methods (klass);
4300 if (mono_class_has_failure (klass)) {
4301 char *name = mono_type_get_full_name (klass);
4302 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4306 mcount = mono_class_get_method_count (klass);
4307 for (index = 0; index < mcount; ++index) {
4308 MonoMethod *cm = klass->methods [index];
4309 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4311 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4312 g_free (method_signature);
4317 mono_method_get_method_definition (MonoMethod *method)
4319 while (method->is_inflated)
4320 method = ((MonoMethodInflated*)method)->declaring;
4325 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4329 for (i = 0; i < onum; ++i) {
4330 MonoMethod *decl = overrides [i * 2];
4331 MonoMethod *body = overrides [i * 2 + 1];
4333 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4334 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4338 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4339 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4340 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4342 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4346 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4347 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4348 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4350 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4354 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4355 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4359 body = mono_method_get_method_definition (body);
4360 decl = mono_method_get_method_definition (decl);
4362 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4363 char *body_name = mono_method_full_name (body, TRUE);
4364 char *decl_name = mono_method_full_name (decl, TRUE);
4365 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4375 mono_class_need_stelemref_method (MonoClass *klass)
4377 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4381 * LOCKING: this is supposed to be called with the loader lock held.
4384 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4388 MonoMethod **vtable;
4389 int i, max_vtsize = 0, cur_slot = 0;
4391 GPtrArray *ifaces = NULL;
4392 GHashTable *override_map = NULL;
4394 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4395 int first_non_interface_slot;
4397 GSList *virt_methods = NULL, *l;
4398 int stelemref_slot = 0;
4403 if (overrides && !verify_class_overrides (klass, overrides, onum))
4406 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4407 if (!mono_error_ok (&error)) {
4408 char *name = mono_type_get_full_name (klass);
4409 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4411 mono_error_cleanup (&error);
4413 } else if (ifaces) {
4414 for (i = 0; i < ifaces->len; i++) {
4415 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4416 max_vtsize += mono_class_get_method_count (ic);
4418 g_ptr_array_free (ifaces, TRUE);
4422 if (klass->parent) {
4423 mono_class_init (klass->parent);
4424 mono_class_setup_vtable_full (klass->parent, in_setup);
4426 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4429 max_vtsize += klass->parent->vtable_size;
4430 cur_slot = klass->parent->vtable_size;
4433 max_vtsize += mono_class_get_method_count (klass);
4435 /*Array have a slot for stelemref*/
4436 if (mono_class_need_stelemref_method (klass)) {
4437 stelemref_slot = cur_slot;
4442 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4443 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4445 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4447 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4448 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4451 max_iid = klass->max_interface_id;
4452 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4454 /* Optimized version for generic instances */
4455 if (mono_class_is_ginst (klass)) {
4457 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4460 mono_class_setup_vtable_full (gklass, in_setup);
4461 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4464 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4465 klass->vtable_size = gklass->vtable_size;
4466 for (i = 0; i < gklass->vtable_size; ++i)
4467 if (gklass->vtable [i]) {
4468 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4469 if (!mono_error_ok (&error)) {
4470 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4471 mono_error_cleanup (&error);
4475 tmp [i]->slot = gklass->vtable [i]->slot;
4477 mono_memory_barrier ();
4478 klass->vtable = tmp;
4480 /* Have to set method->slot for abstract virtual methods */
4481 if (klass->methods && gklass->methods) {
4482 int mcount = mono_class_get_method_count (klass);
4483 for (i = 0; i < mcount; ++i)
4484 if (klass->methods [i]->slot == -1)
4485 klass->methods [i]->slot = gklass->methods [i]->slot;
4491 if (klass->parent && klass->parent->vtable_size) {
4492 MonoClass *parent = klass->parent;
4495 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4497 // Also inherit parent interface vtables, just as a starting point.
4498 // This is needed otherwise bug-77127.exe fails when the property methods
4499 // have different names in the iterface and the class, because for child
4500 // classes the ".override" information is not used anymore.
4501 for (i = 0; i < parent->interface_offsets_count; i++) {
4502 MonoClass *parent_interface = parent->interfaces_packed [i];
4503 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4504 /*FIXME this is now dead code as this condition will never hold true.
4505 Since interface offsets are inherited then the offset of an interface implemented
4506 by a parent will never be the out of it's vtable boundary.
4508 if (interface_offset >= parent->vtable_size) {
4509 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4512 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4513 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4514 int mcount = mono_class_get_method_count (parent_interface);
4515 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4516 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4517 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4518 parent_interface_offset + j, parent_interface_offset, j,
4519 interface_offset + j, interface_offset, j));
4526 /*Array have a slot for stelemref*/
4527 if (mono_class_need_stelemref_method (klass)) {
4528 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4530 method->slot = stelemref_slot;
4532 g_assert (method->slot == stelemref_slot);
4534 vtable [stelemref_slot] = method;
4537 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4538 /* override interface methods */
4539 for (i = 0; i < onum; i++) {
4540 MonoMethod *decl = overrides [i*2];
4541 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4543 dslot = mono_method_get_vtable_slot (decl);
4545 mono_class_set_type_load_failure (klass, "");
4549 dslot += mono_class_interface_offset (klass, decl->klass);
4550 vtable [dslot] = overrides [i*2 + 1];
4551 vtable [dslot]->slot = dslot;
4553 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4555 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4557 if (mono_security_core_clr_enabled ())
4558 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4561 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4562 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4565 * Create a list of virtual methods to avoid calling
4566 * mono_class_get_virtual_methods () which is slow because of the metadata
4570 gpointer iter = NULL;
4573 virt_methods = NULL;
4574 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4575 virt_methods = g_slist_prepend (virt_methods, cm);
4577 if (mono_class_has_failure (klass))
4581 // Loop on all implemented interfaces...
4582 for (i = 0; i < klass->interface_offsets_count; i++) {
4583 MonoClass *parent = klass->parent;
4585 gboolean interface_is_explicitly_implemented_by_class;
4588 ic = klass->interfaces_packed [i];
4589 ic_offset = mono_class_interface_offset (klass, ic);
4591 mono_class_setup_methods (ic);
4592 if (mono_class_has_failure (ic))
4595 // Check if this interface is explicitly implemented (instead of just inherited)
4596 if (parent != NULL) {
4597 int implemented_interfaces_index;
4598 interface_is_explicitly_implemented_by_class = FALSE;
4599 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4600 if (ic == klass->interfaces [implemented_interfaces_index]) {
4601 interface_is_explicitly_implemented_by_class = TRUE;
4606 interface_is_explicitly_implemented_by_class = TRUE;
4609 // Loop on all interface methods...
4610 int mcount = mono_class_get_method_count (ic);
4611 for (im_index = 0; im_index < mcount; im_index++) {
4612 MonoMethod *im = ic->methods [im_index];
4613 int im_slot = ic_offset + im->slot;
4614 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4616 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4619 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4621 // If there is an explicit implementation, just use it right away,
4622 // otherwise look for a matching method
4623 if (override_im == NULL) {
4627 // First look for a suitable method among the class methods
4628 for (l = virt_methods; l; l = l->next) {
4629 cm = (MonoMethod *)l->data;
4630 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)));
4631 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4632 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4633 vtable [im_slot] = cm;
4634 /* Why do we need this? */
4639 TRACE_INTERFACE_VTABLE (printf ("\n"));
4640 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4644 // If the slot is still empty, look in all the inherited virtual methods...
4645 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4646 MonoClass *parent = klass->parent;
4647 // Reverse order, so that last added methods are preferred
4648 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4649 MonoMethod *cm = parent->vtable [cm_index];
4651 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));
4652 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4653 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4654 vtable [im_slot] = cm;
4655 /* Why do we need this? */
4661 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4663 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4667 g_assert (vtable [im_slot] == override_im);
4672 // If the class is not abstract, check that all its interface slots are full.
4673 // The check is done here and not directly at the end of the loop above because
4674 // it can happen (for injected generic array interfaces) that the same slot is
4675 // processed multiple times (those interfaces have overlapping slots), and it
4676 // will not always be the first pass the one that fills the slot.
4677 if (!mono_class_is_abstract (klass)) {
4678 for (i = 0; i < klass->interface_offsets_count; i++) {
4682 ic = klass->interfaces_packed [i];
4683 ic_offset = mono_class_interface_offset (klass, ic);
4685 int mcount = mono_class_get_method_count (ic);
4686 for (im_index = 0; im_index < mcount; im_index++) {
4687 MonoMethod *im = ic->methods [im_index];
4688 int im_slot = ic_offset + im->slot;
4690 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4693 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4694 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4695 if (vtable [im_slot] == NULL) {
4696 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4703 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4704 for (l = virt_methods; l; l = l->next) {
4705 cm = (MonoMethod *)l->data;
4707 * If the method is REUSE_SLOT, we must check in the
4708 * base class for a method to override.
4710 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4712 for (k = klass->parent; k ; k = k->parent) {
4717 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4718 MonoMethodSignature *cmsig, *m1sig;
4720 cmsig = mono_method_signature (cm);
4721 m1sig = mono_method_signature (m1);
4723 if (!cmsig || !m1sig) {
4724 /* FIXME proper error message */
4725 mono_class_set_type_load_failure (klass, "");
4729 if (!strcmp(cm->name, m1->name) &&
4730 mono_metadata_signature_equal (cmsig, m1sig)) {
4732 if (mono_security_core_clr_enabled ())
4733 mono_security_core_clr_check_override (klass, cm, m1);
4735 slot = mono_method_get_vtable_slot (m1);
4739 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4740 char *body_name = mono_method_full_name (cm, TRUE);
4741 char *decl_name = mono_method_full_name (m1, TRUE);
4742 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4748 g_assert (cm->slot < max_vtsize);
4750 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4751 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4752 mono_method_full_name (m1, 1), m1,
4753 mono_method_full_name (cm, 1), cm));
4754 g_hash_table_insert (override_map, m1, cm);
4758 if (mono_class_has_failure (k))
4768 /*Non final newslot methods must be given a non-interface vtable slot*/
4769 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4773 cm->slot = cur_slot++;
4775 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4776 vtable [cm->slot] = cm;
4779 /* override non interface methods */
4780 for (i = 0; i < onum; i++) {
4781 MonoMethod *decl = overrides [i*2];
4782 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4783 g_assert (decl->slot != -1);
4784 vtable [decl->slot] = overrides [i*2 + 1];
4785 overrides [i * 2 + 1]->slot = decl->slot;
4787 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4788 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4789 mono_method_full_name (decl, 1), decl,
4790 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4791 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4793 if (mono_security_core_clr_enabled ())
4794 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4799 * If a method occupies more than one place in the vtable, and it is
4800 * overriden, then change the other occurances too.
4805 for (i = 0; i < max_vtsize; ++i)
4807 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4809 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4814 g_hash_table_destroy (override_map);
4815 override_map = NULL;
4818 g_slist_free (virt_methods);
4819 virt_methods = NULL;
4821 /* Ensure that all vtable slots are filled with concrete instance methods */
4822 if (!mono_class_is_abstract (klass)) {
4823 for (i = 0; i < cur_slot; ++i) {
4824 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4825 char *type_name = mono_type_get_full_name (klass);
4826 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4827 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4829 g_free (method_name);
4835 if (mono_class_is_ginst (klass)) {
4836 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4838 mono_class_init (gklass);
4840 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4842 /* Check that the vtable_size value computed in mono_class_init () is correct */
4843 if (klass->vtable_size)
4844 g_assert (cur_slot == klass->vtable_size);
4845 klass->vtable_size = cur_slot;
4848 /* Try to share the vtable with our parent. */
4849 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4850 mono_memory_barrier ();
4851 klass->vtable = klass->parent->vtable;
4853 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4854 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4855 mono_memory_barrier ();
4856 klass->vtable = tmp;
4859 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4860 if (mono_print_vtable) {
4863 print_implemented_interfaces (klass);
4865 for (i = 0; i <= max_iid; i++)
4866 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4869 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4870 klass->vtable_size, icount);
4872 for (i = 0; i < cur_slot; ++i) {
4877 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4878 mono_method_full_name (cm, TRUE));
4884 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4885 klass->name, max_iid);
4887 for (i = 0; i < klass->interface_count; i++) {
4888 ic = klass->interfaces [i];
4889 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4890 mono_class_interface_offset (klass, ic),
4891 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4894 for (k = klass->parent; k ; k = k->parent) {
4895 for (i = 0; i < k->interface_count; i++) {
4896 ic = k->interfaces [i];
4897 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4898 mono_class_interface_offset (klass, ic),
4899 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4905 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4910 char *name = mono_type_get_full_name (klass);
4911 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4914 g_hash_table_destroy (override_map);
4916 g_slist_free (virt_methods);
4921 * mono_method_get_vtable_slot:
4923 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4924 * LOCKING: Acquires the loader lock.
4926 * FIXME Use proper MonoError machinery here.
4929 mono_method_get_vtable_slot (MonoMethod *method)
4931 if (method->slot == -1) {
4932 mono_class_setup_vtable (method->klass);
4933 if (mono_class_has_failure (method->klass))
4935 if (method->slot == -1) {
4939 if (!mono_class_is_ginst (method->klass)) {
4940 g_assert (method->is_inflated);
4941 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4944 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4945 g_assert (mono_class_is_ginst (method->klass));
4946 gklass = mono_class_get_generic_class (method->klass)->container_class;
4947 mono_class_setup_methods (method->klass);
4948 g_assert (method->klass->methods);
4949 mcount = mono_class_get_method_count (method->klass);
4950 for (i = 0; i < mcount; ++i) {
4951 if (method->klass->methods [i] == method)
4954 g_assert (i < mcount);
4955 g_assert (gklass->methods);
4956 method->slot = gklass->methods [i]->slot;
4958 g_assert (method->slot != -1);
4960 return method->slot;
4964 * mono_method_get_vtable_index:
4967 * Returns the index into the runtime vtable to access the method or,
4968 * in the case of a virtual generic method, the virtual generic method
4969 * thunk. Returns -1 on failure.
4971 * FIXME Use proper MonoError machinery here.
4974 mono_method_get_vtable_index (MonoMethod *method)
4976 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4977 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4978 if (imethod->declaring->is_generic)
4979 return mono_method_get_vtable_slot (imethod->declaring);
4981 return mono_method_get_vtable_slot (method);
4984 static MonoMethod *default_ghc = NULL;
4985 static MonoMethod *default_finalize = NULL;
4986 static int finalize_slot = -1;
4987 static int ghc_slot = -1;
4990 initialize_object_slots (MonoClass *klass)
4995 if (klass == mono_defaults.object_class) {
4996 mono_class_setup_vtable (klass);
4997 for (i = 0; i < klass->vtable_size; ++i) {
4998 MonoMethod *cm = klass->vtable [i];
5000 if (!strcmp (cm->name, "GetHashCode"))
5002 else if (!strcmp (cm->name, "Finalize"))
5006 g_assert (ghc_slot > 0);
5007 default_ghc = klass->vtable [ghc_slot];
5009 g_assert (finalize_slot > 0);
5010 default_finalize = klass->vtable [finalize_slot];
5015 MonoMethod *array_method;
5017 } GenericArrayMethodInfo;
5019 static int generic_array_method_num = 0;
5020 static GenericArrayMethodInfo *generic_array_method_info = NULL;
5023 generic_array_methods (MonoClass *klass)
5025 int i, count_generic = 0, mcount;
5026 GList *list = NULL, *tmp;
5027 if (generic_array_method_num)
5028 return generic_array_method_num;
5029 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
5030 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
5031 mcount = mono_class_get_method_count (klass->parent);
5032 for (i = 0; i < mcount; i++) {
5033 MonoMethod *m = klass->parent->methods [i];
5034 if (!strncmp (m->name, "InternalArray__", 15)) {
5036 list = g_list_prepend (list, m);
5039 list = g_list_reverse (list);
5040 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5042 for (tmp = list; tmp; tmp = tmp->next) {
5043 const char *mname, *iname;
5045 MonoMethod *m = (MonoMethod *)tmp->data;
5046 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5047 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5049 generic_array_method_info [i].array_method = m;
5050 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5051 iname = "System.Collections.Generic.ICollection`1.";
5052 mname = m->name + 27;
5053 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5054 iname = "System.Collections.Generic.IEnumerable`1.";
5055 mname = m->name + 27;
5056 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5057 iname = "System.Collections.Generic.IReadOnlyList`1.";
5058 mname = m->name + strlen (ireadonlylist_prefix);
5059 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5060 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5061 mname = m->name + strlen (ireadonlycollection_prefix);
5062 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5063 iname = "System.Collections.Generic.IList`1.";
5064 mname = m->name + 15;
5066 g_assert_not_reached ();
5069 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5070 strcpy (name, iname);
5071 strcpy (name + strlen (iname), mname);
5072 generic_array_method_info [i].name = name;
5075 /*g_print ("array generic methods: %d\n", count_generic);*/
5077 generic_array_method_num = count_generic;
5079 return generic_array_method_num;
5083 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5085 MonoGenericContext tmp_context;
5088 tmp_context.class_inst = NULL;
5089 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5090 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5092 for (i = 0; i < generic_array_method_num; i++) {
5094 MonoMethod *m = generic_array_method_info [i].array_method;
5095 MonoMethod *inflated;
5097 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5098 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5099 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5104 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5106 int null_length = strlen ("(null)");
5107 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5108 char *s = (char *)mono_image_alloc (image, len);
5111 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5112 g_assert (result == len - 1);
5119 * @klass: the class to initialize
5121 * Compute the instance_size, class_size and other infos that cannot be
5122 * computed at mono_class_get() time. Also compute vtable_size if possible.
5123 * Returns TRUE on success or FALSE if there was a problem in loading
5124 * the type (incorrect assemblies, missing assemblies, methods, etc).
5125 * Initializes the following fields in @klass:
5126 * - all the fields initialized by mono_class_init_sizes ()
5131 * LOCKING: Acquires the loader lock.
5134 mono_class_init (MonoClass *klass)
5136 int i, vtable_size = 0, array_method_count = 0;
5137 MonoCachedClassInfo cached_info;
5138 gboolean has_cached_info;
5139 gboolean locked = FALSE;
5140 gboolean ghcimpl = FALSE;
5141 gboolean has_cctor = FALSE;
5142 int first_iface_slot = 0;
5146 /* Double-checking locking pattern */
5147 if (klass->inited || mono_class_has_failure (klass))
5148 return !mono_class_has_failure (klass);
5150 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5153 * This function can recursively call itself.
5155 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5156 if (g_slist_find (init_list, klass)) {
5157 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5160 init_list = g_slist_prepend (init_list, klass);
5161 mono_native_tls_set_value (init_pending_tls_id, init_list);
5164 * We want to avoid doing complicated work inside locks, so we compute all the required
5165 * information and write it to @klass inside a lock.
5168 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5169 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5173 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5174 MonoClass *element_class = klass->element_class;
5175 if (!element_class->inited)
5176 mono_class_init (element_class);
5177 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5181 mono_stats.initialized_class_count++;
5183 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5184 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5186 mono_class_init (gklass);
5187 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5190 mono_class_setup_interface_id (klass);
5193 if (klass->parent && !klass->parent->inited)
5194 mono_class_init (klass->parent);
5196 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5198 /* Compute instance size etc. */
5199 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5200 if (mono_class_has_failure (klass))
5203 mono_class_setup_supertypes (klass);
5206 initialize_object_slots (klass);
5209 * Initialize the rest of the data without creating a generic vtable if possible.
5210 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5211 * also avoid computing a generic vtable.
5213 if (has_cached_info) {
5215 vtable_size = cached_info.vtable_size;
5216 ghcimpl = cached_info.ghcimpl;
5217 has_cctor = cached_info.has_cctor;
5218 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5219 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5220 * The first slot if for array with.
5222 static int szarray_vtable_size[2] = { 0 };
5224 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5227 if (!szarray_vtable_size [slot]) {
5228 mono_class_setup_vtable (klass);
5229 szarray_vtable_size [slot] = klass->vtable_size;
5230 vtable_size = klass->vtable_size;
5232 vtable_size = szarray_vtable_size[slot];
5234 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5235 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5237 /* Generic instance case */
5238 ghcimpl = gklass->ghcimpl;
5239 has_cctor = gklass->has_cctor;
5241 mono_class_setup_vtable (gklass);
5242 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5245 vtable_size = gklass->vtable_size;
5249 /* ghcimpl is not currently used
5251 if (klass->parent) {
5252 MonoMethod *cmethod = klass->vtable [ghc_slot];
5253 if (cmethod->is_inflated)
5254 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5255 if (cmethod == default_ghc) {
5261 /* C# doesn't allow interfaces to have cctors */
5262 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5263 MonoMethod *cmethod = NULL;
5265 if (mono_class_is_ginst (klass)) {
5266 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5268 /* Generic instance case */
5269 ghcimpl = gklass->ghcimpl;
5270 has_cctor = gklass->has_cctor;
5271 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5272 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5273 /* The find_method function ignores the 'flags' argument */
5274 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5277 mono_class_setup_methods (klass);
5278 if (mono_class_has_failure (klass))
5281 int mcount = mono_class_get_method_count (klass);
5282 for (i = 0; i < mcount; ++i) {
5283 MonoMethod *method = klass->methods [i];
5284 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5285 (strcmp (".cctor", method->name) == 0)) {
5295 array_method_count = 3 + (klass->rank > 1? 2: 1);
5297 if (klass->interface_count) {
5298 int count_generic = generic_array_methods (klass);
5299 array_method_count += klass->interface_count * count_generic;
5303 if (klass->parent) {
5304 if (!klass->parent->vtable_size)
5305 mono_class_setup_vtable (klass->parent);
5306 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5308 g_assert (klass->parent->vtable_size);
5309 first_iface_slot = klass->parent->vtable_size;
5310 if (mono_class_need_stelemref_method (klass))
5315 * Do the actual changes to @klass inside the loader lock
5317 mono_loader_lock ();
5320 if (klass->inited || mono_class_has_failure (klass)) {
5321 mono_loader_unlock ();
5322 /* Somebody might have gotten in before us */
5323 return !mono_class_has_failure (klass);
5326 mono_stats.initialized_class_count++;
5328 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5329 mono_stats.generic_class_count++;
5331 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5332 klass->nested_classes_inited = TRUE;
5333 klass->ghcimpl = ghcimpl;
5334 klass->has_cctor = has_cctor;
5336 klass->vtable_size = vtable_size;
5337 if (has_cached_info) {
5338 klass->has_finalize = cached_info.has_finalize;
5339 klass->has_finalize_inited = TRUE;
5342 mono_class_set_method_count (klass, array_method_count);
5344 mono_loader_unlock ();
5347 setup_interface_offsets (klass, first_iface_slot, TRUE);
5349 if (mono_security_core_clr_enabled ())
5350 mono_security_core_clr_check_inheritance (klass);
5352 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5353 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5358 init_list = g_slist_remove (init_list, klass);
5359 mono_native_tls_set_value (init_pending_tls_id, init_list);
5361 /* Because of the double-checking locking pattern */
5362 mono_memory_barrier ();
5366 mono_loader_unlock ();
5368 return !mono_class_has_failure (klass);
5372 * mono_class_has_finalizer:
5374 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5378 mono_class_has_finalizer (MonoClass *klass)
5380 gboolean has_finalize = FALSE;
5382 if (klass->has_finalize_inited)
5383 return klass->has_finalize;
5385 /* Interfaces and valuetypes are not supposed to have finalizers */
5386 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5387 MonoMethod *cmethod = NULL;
5389 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5390 } else if (mono_class_is_ginst (klass)) {
5391 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5393 has_finalize = mono_class_has_finalizer (gklass);
5394 } else if (klass->parent && klass->parent->has_finalize) {
5395 has_finalize = TRUE;
5397 if (klass->parent) {
5399 * Can't search in metadata for a method named Finalize, because that
5400 * ignores overrides.
5402 mono_class_setup_vtable (klass);
5403 if (mono_class_has_failure (klass))
5406 cmethod = klass->vtable [finalize_slot];
5410 g_assert (klass->vtable_size > finalize_slot);
5412 if (klass->parent) {
5413 if (cmethod->is_inflated)
5414 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5415 if (cmethod != default_finalize)
5416 has_finalize = TRUE;
5422 mono_image_lock (klass->image);
5424 if (!klass->has_finalize_inited) {
5425 klass->has_finalize = has_finalize ? 1 : 0;
5427 mono_memory_barrier ();
5428 klass->has_finalize_inited = TRUE;
5431 mono_image_unlock (klass->image);
5433 return klass->has_finalize;
5437 mono_is_corlib_image (MonoImage *image)
5439 return image == mono_defaults.corlib;
5443 * LOCKING: this assumes the loader lock is held
5446 mono_class_setup_mono_type (MonoClass *klass)
5448 const char *name = klass->name;
5449 const char *nspace = klass->name_space;
5450 gboolean is_corlib = mono_is_corlib_image (klass->image);
5452 klass->this_arg.byref = 1;
5453 klass->this_arg.data.klass = klass;
5454 klass->this_arg.type = MONO_TYPE_CLASS;
5455 klass->byval_arg.data.klass = klass;
5456 klass->byval_arg.type = MONO_TYPE_CLASS;
5458 if (is_corlib && !strcmp (nspace, "System")) {
5459 if (!strcmp (name, "ValueType")) {
5461 * do not set the valuetype bit for System.ValueType.
5462 * klass->valuetype = 1;
5464 klass->blittable = TRUE;
5465 } else if (!strcmp (name, "Enum")) {
5467 * do not set the valuetype bit for System.Enum.
5468 * klass->valuetype = 1;
5470 klass->valuetype = 0;
5471 klass->enumtype = 0;
5472 } else if (!strcmp (name, "Object")) {
5473 klass->byval_arg.type = MONO_TYPE_OBJECT;
5474 klass->this_arg.type = MONO_TYPE_OBJECT;
5475 } else if (!strcmp (name, "String")) {
5476 klass->byval_arg.type = MONO_TYPE_STRING;
5477 klass->this_arg.type = MONO_TYPE_STRING;
5478 } else if (!strcmp (name, "TypedReference")) {
5479 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5480 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5484 if (klass->valuetype) {
5485 int t = MONO_TYPE_VALUETYPE;
5487 if (is_corlib && !strcmp (nspace, "System")) {
5490 if (!strcmp (name, "Boolean")) {
5491 t = MONO_TYPE_BOOLEAN;
5492 } else if (!strcmp(name, "Byte")) {
5494 klass->blittable = TRUE;
5498 if (!strcmp (name, "Char")) {
5503 if (!strcmp (name, "Double")) {
5505 klass->blittable = TRUE;
5509 if (!strcmp (name, "Int32")) {
5511 klass->blittable = TRUE;
5512 } else if (!strcmp(name, "Int16")) {
5514 klass->blittable = TRUE;
5515 } else if (!strcmp(name, "Int64")) {
5517 klass->blittable = TRUE;
5518 } else if (!strcmp(name, "IntPtr")) {
5520 klass->blittable = TRUE;
5524 if (!strcmp (name, "Single")) {
5526 klass->blittable = TRUE;
5527 } else if (!strcmp(name, "SByte")) {
5529 klass->blittable = TRUE;
5533 if (!strcmp (name, "UInt32")) {
5535 klass->blittable = TRUE;
5536 } else if (!strcmp(name, "UInt16")) {
5538 klass->blittable = TRUE;
5539 } else if (!strcmp(name, "UInt64")) {
5541 klass->blittable = TRUE;
5542 } else if (!strcmp(name, "UIntPtr")) {
5544 klass->blittable = TRUE;
5548 if (!strcmp (name, "TypedReference")) {
5549 t = MONO_TYPE_TYPEDBYREF;
5550 klass->blittable = TRUE;
5554 if (!strcmp (name, "Void")) {
5562 klass->byval_arg.type = (MonoTypeEnum)t;
5563 klass->this_arg.type = (MonoTypeEnum)t;
5566 if (MONO_CLASS_IS_INTERFACE (klass))
5567 klass->interface_id = mono_get_unique_iid (klass);
5572 * COM initialization is delayed until needed.
5573 * However when a [ComImport] attribute is present on a type it will trigger
5574 * the initialization. This is not a problem unless the BCL being executed
5575 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5578 init_com_from_comimport (MonoClass *klass)
5580 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5581 if (mono_security_core_clr_enabled ()) {
5582 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5583 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5584 /* but it can not be made available for application (i.e. user code) since all COM calls
5585 * are considered native calls. In this case we fail with a TypeLoadException (just like
5586 * Silverlight 2 does */
5587 mono_class_set_type_load_failure (klass, "");
5592 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5594 #endif /*DISABLE_COM*/
5597 * LOCKING: this assumes the loader lock is held
5600 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5602 gboolean system_namespace;
5603 gboolean is_corlib = mono_is_corlib_image (klass->image);
5605 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5607 /* if root of the hierarchy */
5608 if (system_namespace && !strcmp (klass->name, "Object")) {
5609 klass->parent = NULL;
5610 klass->instance_size = sizeof (MonoObject);
5613 if (!strcmp (klass->name, "<Module>")) {
5614 klass->parent = NULL;
5615 klass->instance_size = 0;
5619 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5620 /* Imported COM Objects always derive from __ComObject. */
5622 if (MONO_CLASS_IS_IMPORT (klass)) {
5623 init_com_from_comimport (klass);
5624 if (parent == mono_defaults.object_class)
5625 parent = mono_class_get_com_object_class ();
5629 /* set the parent to something useful and safe, but mark the type as broken */
5630 parent = mono_defaults.object_class;
5631 mono_class_set_type_load_failure (klass, "");
5635 klass->parent = parent;
5637 if (mono_class_is_ginst (parent) && !parent->name) {
5639 * If the parent is a generic instance, we may get
5640 * called before it is fully initialized, especially
5641 * before it has its name.
5646 #ifndef DISABLE_REMOTING
5647 klass->marshalbyref = parent->marshalbyref;
5648 klass->contextbound = parent->contextbound;
5651 klass->delegate = parent->delegate;
5653 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5654 mono_class_set_is_com_object (klass);
5656 if (system_namespace) {
5657 #ifndef DISABLE_REMOTING
5658 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5659 klass->marshalbyref = 1;
5661 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5662 klass->contextbound = 1;
5664 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5665 klass->delegate = 1;
5668 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5669 (strcmp (klass->parent->name_space, "System") == 0)))
5670 klass->valuetype = 1;
5671 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5672 klass->valuetype = klass->enumtype = 1;
5674 /*klass->enumtype = klass->parent->enumtype; */
5676 /* initialize com types if COM interfaces are present */
5678 if (MONO_CLASS_IS_IMPORT (klass))
5679 init_com_from_comimport (klass);
5681 klass->parent = NULL;
5687 * mono_class_setup_supertypes:
5690 * Build the data structure needed to make fast type checks work.
5691 * This currently sets two fields in @class:
5692 * - idepth: distance between @class and System.Object in the type
5694 * - supertypes: array of classes: each element has a class in the hierarchy
5695 * starting from @class up to System.Object
5697 * LOCKING: Acquires the loader lock.
5700 mono_class_setup_supertypes (MonoClass *klass)
5703 MonoClass **supertypes;
5705 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5709 if (klass->parent && !klass->parent->supertypes)
5710 mono_class_setup_supertypes (klass->parent);
5712 idepth = klass->parent->idepth + 1;
5716 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5717 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5719 if (klass->parent) {
5720 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5723 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5724 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5726 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5729 mono_memory_barrier ();
5731 mono_loader_lock ();
5732 klass->idepth = idepth;
5733 /* Needed so idepth is visible before supertypes is set */
5734 mono_memory_barrier ();
5735 klass->supertypes = supertypes;
5736 mono_loader_unlock ();
5740 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5742 MonoClass *gtd = (MonoClass*)user_data;
5743 /* Only try to fix generic instances of @gtd */
5744 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5747 /* Check if the generic instance has no parent. */
5748 if (gtd->parent && !gclass->parent)
5749 mono_generic_class_setup_parent (gclass, gtd);
5755 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5757 mono_class_set_type_load_failure (klass, "%s", msg);
5758 mono_error_set_type_load_class (error, klass, "%s", msg);
5762 * mono_class_create_from_typedef:
5763 * @image: image where the token is valid
5764 * @type_token: typedef token
5765 * @error: used to return any error found while creating the type
5767 * Create the MonoClass* representing the specified type token.
5768 * @type_token must be a TypeDef token.
5770 * FIXME: don't return NULL on failure, just the the caller figure it out.
5773 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5775 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5776 MonoClass *klass, *parent = NULL;
5777 guint32 cols [MONO_TYPEDEF_SIZE];
5778 guint32 cols_next [MONO_TYPEDEF_SIZE];
5779 guint tidx = mono_metadata_token_index (type_token);
5780 MonoGenericContext *context = NULL;
5781 const char *name, *nspace;
5783 MonoClass **interfaces;
5784 guint32 field_last, method_last;
5785 guint32 nesting_tokeen;
5787 mono_error_init (error);
5789 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5790 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5794 mono_loader_lock ();
5796 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5797 mono_loader_unlock ();
5801 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5803 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5804 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5806 if (mono_metadata_has_generic_params (image, type_token)) {
5807 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5808 klass->class_kind = MONO_CLASS_GTD;
5809 classes_size += sizeof (MonoClassGtd);
5812 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5813 klass->class_kind = MONO_CLASS_DEF;
5814 classes_size += sizeof (MonoClassDef);
5819 klass->name_space = nspace;
5821 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5823 klass->image = image;
5824 klass->type_token = type_token;
5825 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5827 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5830 * Check whether we're a generic type definition.
5832 if (mono_class_is_gtd (klass)) {
5833 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5834 generic_container->owner.klass = klass;
5835 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5836 context = &generic_container->context;
5837 mono_class_set_generic_container (klass, generic_container);
5838 enable_gclass_recording ();
5841 if (cols [MONO_TYPEDEF_EXTENDS]) {
5843 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5845 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5846 /*WARNING: this must satisfy mono_metadata_type_hash*/
5847 klass->this_arg.byref = 1;
5848 klass->this_arg.data.klass = klass;
5849 klass->this_arg.type = MONO_TYPE_CLASS;
5850 klass->byval_arg.data.klass = klass;
5851 klass->byval_arg.type = MONO_TYPE_CLASS;
5853 parent = mono_class_get_checked (image, parent_token, error);
5854 if (parent && context) /* Always inflate */
5855 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5857 if (parent == NULL) {
5858 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5859 goto parent_failure;
5862 for (tmp = parent; tmp; tmp = tmp->parent) {
5864 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5865 goto parent_failure;
5867 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5868 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5869 goto parent_failure;
5874 mono_class_setup_parent (klass, parent);
5876 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5877 mono_class_setup_mono_type (klass);
5879 if (mono_class_is_gtd (klass))
5880 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5883 * This might access klass->byval_arg for recursion generated by generic constraints,
5884 * so it has to come after setup_mono_type ().
5886 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5887 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5888 if (!mono_error_ok (error)) {
5889 /*FIXME implement a mono_class_set_failure_from_mono_error */
5890 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5891 mono_loader_unlock ();
5892 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5897 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5901 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5905 klass->cast_class = klass->element_class = klass;
5907 if (!klass->enumtype) {
5908 if (!mono_metadata_interfaces_from_typedef_full (
5909 image, type_token, &interfaces, &icount, FALSE, context, error)){
5911 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5912 mono_loader_unlock ();
5913 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5917 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5918 g_assert(icount <= 65535);
5920 klass->interfaces = interfaces;
5921 klass->interface_count = icount;
5922 klass->interfaces_inited = 1;
5925 /*g_print ("Load class %s\n", name);*/
5928 * Compute the field and method lists
5930 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5931 mono_class_set_first_field_idx (klass, first_field_idx);
5932 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5933 mono_class_set_first_method_idx (klass, first_method_idx);
5935 if (tt->rows > tidx){
5936 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5937 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5938 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5940 field_last = image->tables [MONO_TABLE_FIELD].rows;
5941 method_last = image->tables [MONO_TABLE_METHOD].rows;
5944 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5945 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5946 mono_class_set_field_count (klass, field_last - first_field_idx);
5947 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5948 mono_class_set_method_count (klass, method_last - first_method_idx);
5950 /* reserve space to store vector pointer in arrays */
5951 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5952 klass->instance_size += 2 * sizeof (gpointer);
5953 g_assert (mono_class_get_field_count (klass) == 0);
5956 if (klass->enumtype) {
5957 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5958 if (!enum_basetype) {
5959 /*set it to a default value as the whole runtime can't handle this to be null*/
5960 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5961 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5962 mono_loader_unlock ();
5963 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5966 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5970 * If we're a generic type definition, load the constraints.
5971 * We must do this after the class has been constructed to make certain recursive scenarios
5974 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5975 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5976 mono_loader_unlock ();
5977 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5981 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5982 if (!strncmp (name, "Vector", 6))
5983 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");
5986 mono_loader_unlock ();
5988 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5993 mono_class_setup_mono_type (klass);
5994 mono_loader_unlock ();
5995 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5999 /** Is klass a Nullable<T> ginst? */
6001 mono_class_is_nullable (MonoClass *klass)
6003 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
6004 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
6008 /** if klass is T? return T */
6010 mono_class_get_nullable_param (MonoClass *klass)
6012 g_assert (mono_class_is_nullable (klass));
6013 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
6017 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6021 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
6023 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6024 if (!mono_error_ok (&error)) {
6025 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6026 klass->parent = mono_defaults.object_class;
6027 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
6028 mono_error_cleanup (&error);
6032 mono_class_setup_parent (klass, klass->parent);
6034 if (klass->enumtype) {
6035 klass->cast_class = gtd->cast_class;
6036 klass->element_class = gtd->element_class;
6042 * Create the `MonoClass' for an instantiation of a generic type.
6043 * We only do this if we actually need it.
6046 mono_generic_class_get_class (MonoGenericClass *gclass)
6048 MonoClass *klass, *gklass;
6050 if (gclass->cached_class)
6051 return gclass->cached_class;
6053 mono_loader_lock ();
6054 if (gclass->cached_class) {
6055 mono_loader_unlock ();
6056 return gclass->cached_class;
6059 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6061 gklass = gclass->container_class;
6063 if (record_gclass_instantiation > 0)
6064 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6066 if (gklass->nested_in) {
6067 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6068 klass->nested_in = gklass->nested_in;
6071 klass->name = gklass->name;
6072 klass->name_space = gklass->name_space;
6074 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6076 klass->image = gklass->image;
6077 klass->type_token = gklass->type_token;
6079 klass->class_kind = MONO_CLASS_GINST;
6081 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6083 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6084 klass->this_arg.type = klass->byval_arg.type;
6085 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6086 klass->this_arg.byref = TRUE;
6087 klass->enumtype = gklass->enumtype;
6088 klass->valuetype = gklass->valuetype;
6090 klass->cast_class = klass->element_class = klass;
6092 if (mono_class_is_nullable (klass))
6093 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6096 * We're not interested in the nested classes of a generic instance.
6097 * We use the generic type definition to look for nested classes.
6100 mono_generic_class_setup_parent (klass, gklass);
6102 if (gclass->is_dynamic) {
6104 * 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.
6105 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6106 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6108 if (!gklass->wastypebuilder)
6111 mono_class_setup_supertypes (klass);
6113 if (klass->enumtype) {
6115 * For enums, gklass->fields might not been set, but instance_size etc. is
6116 * already set in mono_reflection_create_internal_class (). For non-enums,
6117 * these will be computed normally in mono_class_layout_fields ().
6119 klass->instance_size = gklass->instance_size;
6120 klass->sizes.class_size = gklass->sizes.class_size;
6121 mono_memory_barrier ();
6122 klass->size_inited = 1;
6126 mono_memory_barrier ();
6127 gclass->cached_class = klass;
6129 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6131 ++class_ginst_count;
6132 inflated_classes_size += sizeof (MonoClassGenericInst);
6134 mono_loader_unlock ();
6140 get_image_for_container (MonoGenericContainer *container)
6143 if (container->is_anonymous) {
6144 result = container->owner.image;
6147 if (container->is_method) {
6148 MonoMethod *method = container->owner.method;
6149 g_assert_checked (method);
6150 klass = method->klass;
6152 klass = container->owner.klass;
6154 g_assert_checked (klass);
6155 result = klass->image;
6162 get_image_for_generic_param (MonoGenericParam *param)
6164 MonoGenericContainer *container = mono_generic_param_owner (param);
6165 g_assert_checked (container);
6166 return get_image_for_container (container);
6169 // Make a string in the designated image consisting of a single integer.
6170 #define INT_STRING_SIZE 16
6172 make_generic_name_string (MonoImage *image, int num)
6174 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6175 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6179 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6180 // pinfo is derived from param by the caller for us.
6182 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6184 MonoClass *klass, **ptr;
6186 MonoGenericContainer *container = mono_generic_param_owner (param);
6187 g_assert_checked (container);
6189 MonoImage *image = get_image_for_container (container);
6190 gboolean is_mvar = container->is_method;
6191 gboolean is_anonymous = container->is_anonymous;
6193 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6194 klass->class_kind = MONO_CLASS_GPARAM;
6195 classes_size += sizeof (MonoClassGenericParam);
6196 ++class_gparam_count;
6199 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6201 int n = mono_generic_param_num (param);
6202 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6206 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6207 } else if (is_mvar) {
6208 MonoMethod *omethod = container->owner.method;
6209 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6211 MonoClass *oklass = container->owner.klass;
6212 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6215 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6217 // Count non-NULL items in pinfo->constraints
6220 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6224 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6225 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6227 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6228 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6230 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6233 if (count - pos > 0) {
6234 klass->interface_count = count - pos;
6235 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6236 klass->interfaces_inited = TRUE;
6237 for (i = pos; i < count; i++)
6238 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6241 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6243 klass->inited = TRUE;
6244 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6245 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6247 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6248 klass->this_arg.type = klass->byval_arg.type;
6249 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6250 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6251 klass->this_arg.byref = TRUE;
6253 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6254 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6256 /*Init these fields to sane values*/
6257 klass->min_align = 1;
6259 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6260 * constrained to, the JIT depends on this.
6262 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6263 mono_memory_barrier ();
6264 klass->size_inited = 1;
6266 mono_class_setup_supertypes (klass);
6268 if (count - pos > 0) {
6269 mono_class_setup_vtable (klass->parent);
6270 if (mono_class_has_failure (klass->parent))
6271 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6273 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6279 #define FAST_CACHE_SIZE 16
6282 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6283 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6284 * we cache the MonoClasses.
6285 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6286 * LOCKING: Takes the image lock depending on @take_lock.
6289 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6291 int n = mono_generic_param_num (param);
6292 MonoImage *image = get_image_for_generic_param (param);
6293 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6294 MonoClass *klass = NULL;
6299 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6300 // For high numbers or constraints we have to use pointer hashes.
6301 if (param->gshared_constraint) {
6302 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6305 mono_image_lock (image);
6306 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6308 mono_image_unlock (image);
6313 if (n < FAST_CACHE_SIZE) {
6315 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6317 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6319 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6322 mono_image_lock (image);
6323 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6325 mono_image_unlock (image);
6332 * LOCKING: Image lock (param->image) must be held
6335 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6337 int n = mono_generic_param_num (param);
6338 MonoImage *image = get_image_for_generic_param (param);
6339 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6343 if (param->gshared_constraint) {
6344 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6346 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6347 mono_memory_barrier ();
6349 image->mvar_cache_constrained = ht;
6351 image->var_cache_constrained = ht;
6353 g_hash_table_insert (ht, param, klass);
6354 } else if (n < FAST_CACHE_SIZE) {
6356 /* Requires locking to avoid droping an already published class */
6357 if (!image->mvar_cache_fast)
6358 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6359 image->mvar_cache_fast [n] = klass;
6361 if (!image->var_cache_fast)
6362 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6363 image->var_cache_fast [n] = klass;
6366 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6368 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6370 ht = g_hash_table_new (NULL, NULL);
6371 mono_memory_barrier ();
6373 image->mvar_cache_slow = ht;
6375 image->var_cache_slow = ht;
6378 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6383 * LOCKING: Acquires the image lock (@image).
6386 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6388 MonoImage *image = get_image_for_generic_param (param);
6389 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6390 MonoClass *klass, *klass2;
6392 // If a klass already exists for this object and is cached, return it.
6393 if (pinfo) // Non-anonymous
6394 klass = pinfo->pklass;
6396 klass = get_anon_gparam_class (param, TRUE);
6401 // Create a new klass
6402 klass = make_generic_param_class (param, pinfo);
6404 // Now we need to cache the klass we created.
6405 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6406 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6407 // and allow our newly-created klass object to just leak.
6408 mono_memory_barrier ();
6410 mono_image_lock (image);
6412 // Here "klass2" refers to the klass potentially created by the other thread.
6413 if (pinfo) // Repeat check from above
6414 klass2 = pinfo->pklass;
6416 klass2 = get_anon_gparam_class (param, FALSE);
6423 pinfo->pklass = klass;
6425 set_anon_gparam_class (param, klass);
6427 mono_image_unlock (image);
6429 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6431 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6433 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6439 * mono_class_from_generic_parameter:
6440 * @param: Parameter to find/construct a class for.
6441 * @arg2: Is ignored.
6442 * @arg3: Is ignored.
6445 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6447 return mono_class_from_generic_parameter_internal (param);
6452 mono_ptr_class_get (MonoType *type)
6455 MonoClass *el_class;
6459 el_class = mono_class_from_mono_type (type);
6460 image = el_class->image;
6462 mono_image_lock (image);
6463 if (image->ptr_cache) {
6464 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6465 mono_image_unlock (image);
6469 mono_image_unlock (image);
6471 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6473 classes_size += sizeof (MonoClassPointer);
6474 ++class_pointer_count;
6476 result->parent = NULL; /* no parent for PTR types */
6477 result->name_space = el_class->name_space;
6478 name = g_strdup_printf ("%s*", el_class->name);
6479 result->name = mono_image_strdup (image, name);
6480 result->class_kind = MONO_CLASS_POINTER;
6483 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6485 result->image = el_class->image;
6486 result->inited = TRUE;
6487 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6488 result->cast_class = result->element_class = el_class;
6489 result->blittable = TRUE;
6491 result->byval_arg.type = MONO_TYPE_PTR;
6492 result->this_arg.type = result->byval_arg.type;
6493 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6494 result->this_arg.byref = TRUE;
6496 mono_class_setup_supertypes (result);
6498 mono_image_lock (image);
6499 if (image->ptr_cache) {
6501 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6502 mono_image_unlock (image);
6503 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6507 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6509 g_hash_table_insert (image->ptr_cache, el_class, result);
6510 mono_image_unlock (image);
6512 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6518 mono_fnptr_class_get (MonoMethodSignature *sig)
6521 static GHashTable *ptr_hash = NULL;
6523 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6525 mono_loader_lock ();
6528 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6530 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6531 mono_loader_unlock ();
6534 result = g_new0 (MonoClass, 1);
6536 classes_size += sizeof (MonoClassPointer);
6537 ++class_pointer_count;
6539 result->parent = NULL; /* no parent for PTR types */
6540 result->name_space = "System";
6541 result->name = "MonoFNPtrFakeClass";
6542 result->class_kind = MONO_CLASS_POINTER;
6544 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6546 result->image = mono_defaults.corlib; /* need to fix... */
6547 result->inited = TRUE;
6548 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6549 result->cast_class = result->element_class = result;
6550 result->blittable = TRUE;
6552 result->byval_arg.type = MONO_TYPE_FNPTR;
6553 result->this_arg.type = result->byval_arg.type;
6554 result->this_arg.data.method = result->byval_arg.data.method = sig;
6555 result->this_arg.byref = TRUE;
6556 result->blittable = TRUE;
6558 mono_class_setup_supertypes (result);
6560 g_hash_table_insert (ptr_hash, sig, result);
6562 mono_loader_unlock ();
6564 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6570 * mono_class_from_mono_type:
6571 * @type: describes the type to return
6573 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6576 mono_class_from_mono_type (MonoType *type)
6578 switch (type->type) {
6579 case MONO_TYPE_OBJECT:
6580 return type->data.klass? type->data.klass: mono_defaults.object_class;
6581 case MONO_TYPE_VOID:
6582 return type->data.klass? type->data.klass: mono_defaults.void_class;
6583 case MONO_TYPE_BOOLEAN:
6584 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6585 case MONO_TYPE_CHAR:
6586 return type->data.klass? type->data.klass: mono_defaults.char_class;
6588 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6590 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6592 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6594 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6596 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6598 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6600 return type->data.klass? type->data.klass: mono_defaults.int_class;
6602 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6604 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6606 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6608 return type->data.klass? type->data.klass: mono_defaults.single_class;
6610 return type->data.klass? type->data.klass: mono_defaults.double_class;
6611 case MONO_TYPE_STRING:
6612 return type->data.klass? type->data.klass: mono_defaults.string_class;
6613 case MONO_TYPE_TYPEDBYREF:
6614 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6615 case MONO_TYPE_ARRAY:
6616 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6618 return mono_ptr_class_get (type->data.type);
6619 case MONO_TYPE_FNPTR:
6620 return mono_fnptr_class_get (type->data.method);
6621 case MONO_TYPE_SZARRAY:
6622 return mono_array_class_get (type->data.klass, 1);
6623 case MONO_TYPE_CLASS:
6624 case MONO_TYPE_VALUETYPE:
6625 return type->data.klass;
6626 case MONO_TYPE_GENERICINST:
6627 return mono_generic_class_get_class (type->data.generic_class);
6628 case MONO_TYPE_MVAR:
6630 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6632 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6633 g_assert_not_reached ();
6636 // Yes, this returns NULL, even if it is documented as not doing so, but there
6637 // is no way for the code to make it this far, due to the assert above.
6642 * mono_type_retrieve_from_typespec
6643 * @image: context where the image is created
6644 * @type_spec: typespec token
6645 * @context: the generic context used to evaluate generic instantiations in
6648 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6650 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6652 *did_inflate = FALSE;
6657 if (context && (context->class_inst || context->method_inst)) {
6658 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6660 if (!mono_error_ok (error)) {
6666 *did_inflate = TRUE;
6673 * mono_class_create_from_typespec
6674 * @image: context where the image is created
6675 * @type_spec: typespec token
6676 * @context: the generic context used to evaluate generic instantiations in
6679 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6682 gboolean inflated = FALSE;
6683 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6684 return_val_if_nok (error, NULL);
6685 ret = mono_class_from_mono_type (t);
6687 mono_metadata_free_type (t);
6692 * mono_bounded_array_class_get:
6693 * @element_class: element class
6694 * @rank: the dimension of the array class
6695 * @bounded: whenever the array has non-zero bounds
6697 * Returns: A class object describing the array with element type @element_type and
6701 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6705 MonoClass *parent = NULL;
6706 GSList *list, *rootlist = NULL;
6710 g_assert (rank <= 255);
6713 /* bounded only matters for one-dimensional arrays */
6716 image = eclass->image;
6718 if (rank == 1 && !bounded) {
6720 * This case is very frequent not just during compilation because of calls
6721 * from mono_class_from_mono_type (), mono_array_new (),
6722 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6724 mono_os_mutex_lock (&image->szarray_cache_lock);
6725 if (!image->szarray_cache)
6726 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6727 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6728 mono_os_mutex_unlock (&image->szarray_cache_lock);
6732 mono_loader_lock ();
6734 mono_loader_lock ();
6736 if (!image->array_cache)
6737 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6739 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6740 for (; list; list = list->next) {
6741 klass = (MonoClass *)list->data;
6742 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6743 mono_loader_unlock ();
6750 parent = mono_defaults.array_class;
6751 if (!parent->inited)
6752 mono_class_init (parent);
6754 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6756 klass->image = image;
6757 klass->name_space = eclass->name_space;
6758 klass->class_kind = MONO_CLASS_ARRAY;
6760 nsize = strlen (eclass->name);
6761 name = (char *)g_malloc (nsize + 2 + rank + 1);
6762 memcpy (name, eclass->name, nsize);
6765 memset (name + nsize + 1, ',', rank - 1);
6767 name [nsize + rank] = '*';
6768 name [nsize + rank + bounded] = ']';
6769 name [nsize + rank + bounded + 1] = 0;
6770 klass->name = mono_image_strdup (image, name);
6773 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6775 classes_size += sizeof (MonoClassArray);
6776 ++class_array_count;
6778 klass->type_token = 0;
6779 klass->parent = parent;
6780 klass->instance_size = mono_class_instance_size (klass->parent);
6782 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6783 /*Arrays of those two types are invalid.*/
6784 MonoError prepared_error;
6785 mono_error_init (&prepared_error);
6786 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6787 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6788 mono_error_cleanup (&prepared_error);
6789 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6790 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6791 if (!ref_info_handle || eclass->wastypebuilder) {
6792 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6793 g_assert (ref_info_handle && !eclass->wastypebuilder);
6795 /* element_size -1 is ok as this is not an instantitable type*/
6796 klass->sizes.element_size = -1;
6798 klass->sizes.element_size = mono_class_array_element_size (eclass);
6800 mono_class_setup_supertypes (klass);
6802 if (mono_class_is_ginst (eclass))
6803 mono_class_init (eclass);
6804 if (!eclass->size_inited)
6805 mono_class_setup_fields (eclass);
6806 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6807 /*FIXME we fail the array type, but we have to let other fields be set.*/
6809 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6813 if (eclass->enumtype)
6814 klass->cast_class = eclass->element_class;
6816 klass->cast_class = eclass;
6818 switch (klass->cast_class->byval_arg.type) {
6820 klass->cast_class = mono_defaults.byte_class;
6823 klass->cast_class = mono_defaults.int16_class;
6826 #if SIZEOF_VOID_P == 4
6830 klass->cast_class = mono_defaults.int32_class;
6833 #if SIZEOF_VOID_P == 8
6837 klass->cast_class = mono_defaults.int64_class;
6843 klass->element_class = eclass;
6845 if ((rank > 1) || bounded) {
6846 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6847 klass->byval_arg.type = MONO_TYPE_ARRAY;
6848 klass->byval_arg.data.array = at;
6849 at->eklass = eclass;
6851 /* FIXME: complete.... */
6853 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6854 klass->byval_arg.data.klass = eclass;
6856 klass->this_arg = klass->byval_arg;
6857 klass->this_arg.byref = 1;
6859 //WTF was this? it's wrong
6860 // klass->generic_container = eclass->generic_container;
6862 if (rank == 1 && !bounded) {
6863 MonoClass *prev_class;
6865 mono_os_mutex_lock (&image->szarray_cache_lock);
6866 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6868 /* Someone got in before us */
6871 g_hash_table_insert (image->szarray_cache, eclass, klass);
6872 mono_os_mutex_unlock (&image->szarray_cache_lock);
6874 list = g_slist_append (rootlist, klass);
6875 g_hash_table_insert (image->array_cache, eclass, list);
6878 mono_loader_unlock ();
6880 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6886 * mono_array_class_get:
6887 * @element_class: element class
6888 * @rank: the dimension of the array class
6890 * Returns: A class object describing the array with element type @element_type and
6894 mono_array_class_get (MonoClass *eclass, guint32 rank)
6896 return mono_bounded_array_class_get (eclass, rank, FALSE);
6900 * mono_class_instance_size:
6903 * Use to get the size of a class in bytes.
6905 * Returns: The size of an object instance
6908 mono_class_instance_size (MonoClass *klass)
6910 if (!klass->size_inited)
6911 mono_class_init (klass);
6913 return klass->instance_size;
6917 * mono_class_min_align:
6920 * Use to get the computed minimum alignment requirements for the specified class.
6922 * Returns: minimum alignment requirements
6925 mono_class_min_align (MonoClass *klass)
6927 if (!klass->size_inited)
6928 mono_class_init (klass);
6930 return klass->min_align;
6934 * mono_class_value_size:
6937 * This function is used for value types, and return the
6938 * space and the alignment to store that kind of value object.
6940 * Returns: the size of a value of kind @klass
6943 mono_class_value_size (MonoClass *klass, guint32 *align)
6947 /* fixme: check disable, because we still have external revereces to
6948 * mscorlib and Dummy Objects
6950 /*g_assert (klass->valuetype);*/
6952 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6955 *align = klass->min_align;
6961 * mono_class_data_size:
6964 * Returns: The size of the static class data
6967 mono_class_data_size (MonoClass *klass)
6970 mono_class_init (klass);
6971 /* This can happen with dynamically created types */
6972 if (!klass->fields_inited)
6973 mono_class_setup_fields (klass);
6975 /* in arrays, sizes.class_size is unioned with element_size
6976 * and arrays have no static fields
6980 return klass->sizes.class_size;
6984 * Auxiliary routine to mono_class_get_field
6986 * Takes a field index instead of a field token.
6988 static MonoClassField *
6989 mono_class_get_field_idx (MonoClass *klass, int idx)
6991 mono_class_setup_fields (klass);
6992 if (mono_class_has_failure (klass))
6996 int first_field_idx = mono_class_get_first_field_idx (klass);
6997 int fcount = mono_class_get_field_count (klass);
6998 if (klass->image->uncompressed_metadata) {
7000 * first_field_idx points to the FieldPtr table, while idx points into the
7001 * Field table, so we have to do a search.
7003 /*FIXME this is broken for types with multiple fields with the same name.*/
7004 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7007 for (i = 0; i < fcount; ++i)
7008 if (mono_field_get_name (&klass->fields [i]) == name)
7009 return &klass->fields [i];
7010 g_assert_not_reached ();
7013 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
7014 return &klass->fields [idx - first_field_idx];
7018 klass = klass->parent;
7024 * mono_class_get_field:
7025 * @class: the class to lookup the field.
7026 * @field_token: the field token
7028 * Returns: A MonoClassField representing the type and offset of
7029 * the field, or a NULL value if the field does not belong to this
7033 mono_class_get_field (MonoClass *klass, guint32 field_token)
7035 int idx = mono_metadata_token_index (field_token);
7037 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7039 return mono_class_get_field_idx (klass, idx - 1);
7043 * mono_class_get_field_from_name:
7044 * @klass: the class to lookup the field.
7045 * @name: the field name
7047 * Search the class @klass and it's parents for a field with the name @name.
7049 * Returns: The MonoClassField pointer of the named field or NULL
7052 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7054 return mono_class_get_field_from_name_full (klass, name, NULL);
7058 * mono_class_get_field_from_name_full:
7059 * @klass: the class to lookup the field.
7060 * @name: the field name
7061 * @type: the type of the fields. This optional.
7063 * Search the class @klass and it's parents for a field with the name @name and type @type.
7065 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7066 * of its generic type definition.
7068 * Returns: The MonoClassField pointer of the named field or NULL
7071 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7075 mono_class_setup_fields (klass);
7076 if (mono_class_has_failure (klass))
7080 int fcount = mono_class_get_field_count (klass);
7081 for (i = 0; i < fcount; ++i) {
7082 MonoClassField *field = &klass->fields [i];
7084 if (strcmp (name, mono_field_get_name (field)) != 0)
7088 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7089 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7094 klass = klass->parent;
7100 * mono_class_get_field_token:
7101 * @field: the field we need the token of
7103 * Get the token of a field. Note that the tokesn is only valid for the image
7104 * the field was loaded from. Don't use this function for fields in dynamic types.
7106 * Returns: The token representing the field in the image it was loaded from.
7109 mono_class_get_field_token (MonoClassField *field)
7111 MonoClass *klass = field->parent;
7114 mono_class_setup_fields (klass);
7119 int first_field_idx = mono_class_get_first_field_idx (klass);
7120 int fcount = mono_class_get_field_count (klass);
7121 for (i = 0; i < fcount; ++i) {
7122 if (&klass->fields [i] == field) {
7123 int idx = first_field_idx + i + 1;
7125 if (klass->image->uncompressed_metadata)
7126 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7127 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7130 klass = klass->parent;
7133 g_assert_not_reached ();
7138 mono_field_get_index (MonoClassField *field)
7140 int index = field - field->parent->fields;
7141 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7147 * mono_class_get_field_default_value:
7149 * Return the default value of the field as a pointer into the metadata blob.
7152 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7155 guint32 constant_cols [MONO_CONSTANT_SIZE];
7157 MonoClass *klass = field->parent;
7159 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7161 MonoClassExt *ext = mono_class_get_ext (klass);
7162 if (!ext || !ext->field_def_values) {
7163 MonoFieldDefaultValue *def_values;
7165 mono_class_alloc_ext (klass);
7166 ext = mono_class_get_ext (klass);
7168 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7170 mono_image_lock (klass->image);
7171 mono_memory_barrier ();
7172 if (!ext->field_def_values)
7173 ext->field_def_values = def_values;
7174 mono_image_unlock (klass->image);
7177 field_index = mono_field_get_index (field);
7179 if (!ext->field_def_values [field_index].data) {
7180 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7184 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7186 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7187 ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7188 ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7191 *def_type = ext->field_def_values [field_index].def_type;
7192 return ext->field_def_values [field_index].data;
7196 mono_property_get_index (MonoProperty *prop)
7198 MonoClassExt *ext = mono_class_get_ext (prop->parent);
7199 int index = prop - ext->properties;
7201 g_assert (index >= 0 && index < ext->property.count);
7207 * mono_class_get_property_default_value:
7209 * Return the default value of the field as a pointer into the metadata blob.
7212 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7215 guint32 constant_cols [MONO_CONSTANT_SIZE];
7216 MonoClass *klass = property->parent;
7218 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7220 * We don't cache here because it is not used by C# so it's quite rare, but
7221 * we still do the lookup in klass->ext because that is where the data
7222 * is stored for dynamic assemblies.
7225 if (image_is_dynamic (klass->image)) {
7226 MonoClassExt *ext = mono_class_get_ext (klass);
7227 int prop_index = mono_property_get_index (property);
7228 if (ext->prop_def_values && ext->prop_def_values [prop_index].data) {
7229 *def_type = ext->prop_def_values [prop_index].def_type;
7230 return ext->prop_def_values [prop_index].data;
7234 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7238 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7239 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7240 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7244 mono_class_get_event_token (MonoEvent *event)
7246 MonoClass *klass = event->parent;
7250 MonoClassExt *ext = mono_class_get_ext (klass);
7252 for (i = 0; i < ext->event.count; ++i) {
7253 if (&ext->events [i] == event)
7254 return mono_metadata_make_token (MONO_TABLE_EVENT, ext->event.first + i + 1);
7257 klass = klass->parent;
7260 g_assert_not_reached ();
7265 * mono_class_get_property_from_name:
7267 * @name: name of the property to lookup in the specified class
7269 * Use this method to lookup a property in a class
7270 * Returns: the MonoProperty with the given name, or NULL if the property
7271 * does not exist on the @klass.
7274 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7278 gpointer iter = NULL;
7279 while ((p = mono_class_get_properties (klass, &iter))) {
7280 if (! strcmp (name, p->name))
7283 klass = klass->parent;
7289 * mono_class_get_property_token:
7290 * @prop: MonoProperty to query
7292 * Returns: The ECMA token for the specified property.
7295 mono_class_get_property_token (MonoProperty *prop)
7297 MonoClass *klass = prop->parent;
7301 gpointer iter = NULL;
7302 MonoClassExt *ext = mono_class_get_ext (klass);
7303 while ((p = mono_class_get_properties (klass, &iter))) {
7304 if (&ext->properties [i] == prop)
7305 return mono_metadata_make_token (MONO_TABLE_PROPERTY, ext->property.first + i + 1);
7309 klass = klass->parent;
7312 g_assert_not_reached ();
7317 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7319 const char *name, *nspace;
7320 if (image_is_dynamic (image))
7321 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7323 switch (type_token & 0xff000000){
7324 case MONO_TOKEN_TYPE_DEF: {
7325 guint32 cols [MONO_TYPEDEF_SIZE];
7326 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7327 guint tidx = mono_metadata_token_index (type_token);
7329 if (tidx > tt->rows)
7330 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7332 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7333 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7334 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7335 if (strlen (nspace) == 0)
7336 return g_strdup_printf ("%s", name);
7338 return g_strdup_printf ("%s.%s", nspace, name);
7341 case MONO_TOKEN_TYPE_REF: {
7343 guint32 cols [MONO_TYPEREF_SIZE];
7344 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7345 guint tidx = mono_metadata_token_index (type_token);
7348 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7350 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7351 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7352 mono_error_cleanup (&error);
7356 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7357 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7358 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7359 if (strlen (nspace) == 0)
7360 return g_strdup_printf ("%s", name);
7362 return g_strdup_printf ("%s.%s", nspace, name);
7365 case MONO_TOKEN_TYPE_SPEC:
7366 return g_strdup_printf ("Typespec 0x%08x", type_token);
7368 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7373 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7375 if (image_is_dynamic (image))
7376 return g_strdup_printf ("DynamicAssembly %s", image->name);
7378 switch (type_token & 0xff000000){
7379 case MONO_TOKEN_TYPE_DEF:
7380 if (image->assembly)
7381 return mono_stringify_assembly_name (&image->assembly->aname);
7382 else if (image->assembly_name)
7383 return g_strdup (image->assembly_name);
7384 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7385 case MONO_TOKEN_TYPE_REF: {
7387 MonoAssemblyName aname;
7388 guint32 cols [MONO_TYPEREF_SIZE];
7389 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7390 guint32 idx = mono_metadata_token_index (type_token);
7393 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7395 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7396 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7397 mono_error_cleanup (&error);
7400 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7402 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7403 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7404 case MONO_RESOLUTION_SCOPE_MODULE:
7406 return g_strdup ("");
7407 case MONO_RESOLUTION_SCOPE_MODULEREF:
7409 return g_strdup ("");
7410 case MONO_RESOLUTION_SCOPE_TYPEREF:
7412 return g_strdup ("");
7413 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7414 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7415 return mono_stringify_assembly_name (&aname);
7417 g_assert_not_reached ();
7421 case MONO_TOKEN_TYPE_SPEC:
7423 return g_strdup ("");
7425 g_assert_not_reached ();
7432 * mono_class_get_full:
7433 * @image: the image where the class resides
7434 * @type_token: the token for the class
7435 * @context: the generic context used to evaluate generic instantiations in
7436 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7438 * Returns: The MonoClass that represents @type_token in @image
7441 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7445 klass = mono_class_get_checked (image, type_token, &error);
7447 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7448 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7450 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7456 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7460 mono_error_init (error);
7461 klass = mono_class_get_checked (image, type_token, error);
7463 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7464 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7469 * mono_class_get_checked:
7470 * @image: the image where the class resides
7471 * @type_token: the token for the class
7472 * @error: error object to return any error
7474 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7477 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7479 MonoClass *klass = NULL;
7481 mono_error_init (error);
7483 if (image_is_dynamic (image)) {
7484 int table = mono_metadata_token_table (type_token);
7486 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7487 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7490 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7494 switch (type_token & 0xff000000){
7495 case MONO_TOKEN_TYPE_DEF:
7496 klass = mono_class_create_from_typedef (image, type_token, error);
7498 case MONO_TOKEN_TYPE_REF:
7499 klass = mono_class_from_typeref_checked (image, type_token, error);
7501 case MONO_TOKEN_TYPE_SPEC:
7502 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7505 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7509 /* Generic case, should be avoided for when a better error is possible. */
7510 if (!klass && mono_error_ok (error)) {
7511 char *name = mono_class_name_from_token (image, type_token);
7512 char *assembly = mono_assembly_name_from_token (image, type_token);
7513 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7521 * mono_type_get_checked:
7522 * @image: the image where the type resides
7523 * @type_token: the token for the type
7524 * @context: the generic context used to evaluate generic instantiations in
7525 * @error: Error handling context
7527 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7529 * Returns: The MonoType that represents @type_token in @image
7532 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7534 MonoType *type = NULL;
7535 gboolean inflated = FALSE;
7537 mono_error_init (error);
7539 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7540 if (image_is_dynamic (image)) {
7541 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7542 return_val_if_nok (error, NULL);
7543 return mono_class_get_type (klass);
7546 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7547 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7554 return mono_class_get_type (klass);
7557 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7564 MonoType *tmp = type;
7565 type = mono_class_get_type (mono_class_from_mono_type (type));
7566 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7567 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7568 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7570 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7572 if (type->type != tmp->type)
7575 mono_metadata_free_type (tmp);
7582 * @image: image where the class token will be looked up.
7583 * @type_token: a type token from the image
7585 * Returns the MonoClass with the given @type_token on the @image
7588 mono_class_get (MonoImage *image, guint32 type_token)
7590 return mono_class_get_full (image, type_token, NULL);
7594 * mono_image_init_name_cache:
7596 * Initializes the class name cache stored in image->name_cache.
7598 * LOCKING: Acquires the corresponding image lock.
7601 mono_image_init_name_cache (MonoImage *image)
7603 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7604 guint32 cols [MONO_TYPEDEF_SIZE];
7607 guint32 i, visib, nspace_index;
7608 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7610 if (image->name_cache)
7613 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7615 if (image_is_dynamic (image)) {
7616 mono_image_lock (image);
7617 if (image->name_cache) {
7618 /* Somebody initialized it before us */
7619 g_hash_table_destroy (the_name_cache);
7621 mono_atomic_store_release (&image->name_cache, the_name_cache);
7623 mono_image_unlock (image);
7627 /* Temporary hash table to avoid lookups in the nspace_table */
7628 name_cache2 = g_hash_table_new (NULL, NULL);
7630 for (i = 1; i <= t->rows; ++i) {
7631 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7632 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7634 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7635 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7637 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7639 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7640 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7642 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7643 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7644 if (!nspace_table) {
7645 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7646 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7647 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7650 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7653 /* Load type names from EXPORTEDTYPES table */
7655 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7656 guint32 cols [MONO_EXP_TYPE_SIZE];
7659 for (i = 0; i < t->rows; ++i) {
7660 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7662 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7663 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7667 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7668 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7670 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7671 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7672 if (!nspace_table) {
7673 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7674 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7675 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7678 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7682 g_hash_table_destroy (name_cache2);
7684 mono_image_lock (image);
7685 if (image->name_cache) {
7686 /* Somebody initialized it before us */
7687 g_hash_table_destroy (the_name_cache);
7689 mono_atomic_store_release (&image->name_cache, the_name_cache);
7691 mono_image_unlock (image);
7694 /*FIXME Only dynamic assemblies should allow this operation.*/
7696 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7697 const char *name, guint32 index)
7699 GHashTable *nspace_table;
7700 GHashTable *name_cache;
7703 mono_image_init_name_cache (image);
7704 mono_image_lock (image);
7706 name_cache = image->name_cache;
7707 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7708 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7709 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7712 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7713 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7715 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7717 mono_image_unlock (image);
7726 find_nocase (gpointer key, gpointer value, gpointer user_data)
7728 char *name = (char*)key;
7729 FindUserData *data = (FindUserData*)user_data;
7731 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7732 data->value = value;
7736 * mono_class_from_name_case:
7737 * @image: The MonoImage where the type is looked up in
7738 * @name_space: the type namespace
7739 * @name: the type short name.
7740 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7742 * Obtains a MonoClass with a given namespace and a given name which
7743 * is located in the given MonoImage. The namespace and name
7744 * lookups are case insensitive.
7747 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7750 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7751 mono_error_cleanup (&error);
7757 * mono_class_from_name_case:
7758 * @image: The MonoImage where the type is looked up in
7759 * @name_space: the type namespace
7760 * @name: the type short name.
7763 * Obtains a MonoClass with a given namespace and a given name which
7764 * is located in the given MonoImage. The namespace and name
7765 * lookups are case insensitive.
7767 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7768 * was not found. The @error object will contain information about the problem
7772 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7774 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7775 guint32 cols [MONO_TYPEDEF_SIZE];
7780 mono_error_init (error);
7782 if (image_is_dynamic (image)) {
7784 FindUserData user_data;
7786 mono_image_init_name_cache (image);
7787 mono_image_lock (image);
7789 user_data.key = name_space;
7790 user_data.value = NULL;
7791 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7793 if (user_data.value) {
7794 GHashTable *nspace_table = (GHashTable*)user_data.value;
7796 user_data.key = name;
7797 user_data.value = NULL;
7799 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7801 if (user_data.value)
7802 token = GPOINTER_TO_UINT (user_data.value);
7805 mono_image_unlock (image);
7808 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7814 /* add a cache if needed */
7815 for (i = 1; i <= t->rows; ++i) {
7816 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7817 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7819 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7820 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7822 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7824 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7825 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7826 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7827 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7833 return_nested_in (MonoClass *klass, char *nested)
7836 char *s = strchr (nested, '/');
7837 gpointer iter = NULL;
7844 while ((found = mono_class_get_nested_types (klass, &iter))) {
7845 if (strcmp (found->name, nested) == 0) {
7847 return return_nested_in (found, s);
7855 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7857 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7858 MonoImage *file_image;
7862 mono_error_init (error);
7865 * The EXPORTEDTYPES table only contains public types, so have to search the
7867 * Note: image->modules contains the contents of the MODULEREF table, while
7868 * the real module list is in the FILE table.
7870 for (i = 0; i < file_table->rows; i++) {
7871 guint32 cols [MONO_FILE_SIZE];
7872 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7873 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7876 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7878 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7879 if (klass || !is_ok (error))
7888 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7890 GHashTable *nspace_table;
7891 MonoImage *loaded_image;
7898 mono_error_init (error);
7900 // Checking visited images avoids stack overflows when cyclic references exist.
7901 if (g_hash_table_lookup (visited_images, image))
7904 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7906 if ((nested = strchr (name, '/'))) {
7907 int pos = nested - name;
7908 int len = strlen (name);
7911 memcpy (buf, name, len + 1);
7913 nested = buf + pos + 1;
7917 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7918 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7919 gboolean res = get_class_from_name (image, name_space, name, &klass);
7922 klass = search_modules (image, name_space, name, error);
7927 return klass ? return_nested_in (klass, nested) : NULL;
7933 mono_image_init_name_cache (image);
7934 mono_image_lock (image);
7936 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7939 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7941 mono_image_unlock (image);
7943 if (!token && image_is_dynamic (image) && image->modules) {
7944 /* Search modules as well */
7945 for (i = 0; i < image->module_count; ++i) {
7946 MonoImage *module = image->modules [i];
7948 klass = mono_class_from_name_checked (module, name_space, name, error);
7949 if (klass || !is_ok (error))
7955 klass = search_modules (image, name_space, name, error);
7956 if (klass || !is_ok (error))
7961 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7962 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7963 guint32 cols [MONO_EXP_TYPE_SIZE];
7966 idx = mono_metadata_token_index (token);
7968 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7970 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7971 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7972 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7975 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7977 return klass ? return_nested_in (klass, nested) : NULL;
7979 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7980 guint32 assembly_idx;
7982 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7984 mono_assembly_load_reference (image, assembly_idx - 1);
7985 g_assert (image->references [assembly_idx - 1]);
7986 if (image->references [assembly_idx - 1] == (gpointer)-1)
7988 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7990 return klass ? return_nested_in (klass, nested) : NULL;
7993 g_assert_not_reached ();
7997 token = MONO_TOKEN_TYPE_DEF | token;
7999 klass = mono_class_get_checked (image, token, error);
8001 return return_nested_in (klass, nested);
8006 * mono_class_from_name_checked:
8007 * @image: The MonoImage where the type is looked up in
8008 * @name_space: the type namespace
8009 * @name: the type short name.
8011 * Obtains a MonoClass with a given namespace and a given name which
8012 * is located in the given MonoImage.
8014 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
8015 * set if the class was not found or it will return NULL and set the error if there was a loading error.
8018 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8021 GHashTable *visited_images;
8023 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8025 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8027 g_hash_table_destroy (visited_images);
8033 * mono_class_from_name:
8034 * @image: The MonoImage where the type is looked up in
8035 * @name_space: the type namespace
8036 * @name: the type short name.
8038 * Obtains a MonoClass with a given namespace and a given name which
8039 * is located in the given MonoImage.
8041 * To reference nested classes, use the "/" character as a separator.
8042 * For example use "Foo/Bar" to reference the class Bar that is nested
8043 * inside Foo, like this: "class Foo { class Bar {} }".
8046 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8051 klass = mono_class_from_name_checked (image, name_space, name, &error);
8052 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8058 * mono_class_load_from_name:
8059 * @image: The MonoImage where the type is looked up in
8060 * @name_space: the type namespace
8061 * @name: the type short name.
8063 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8064 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8065 * If they are missing. Thing of System.Object or System.String.
8068 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8073 klass = mono_class_from_name_checked (image, name_space, name, &error);
8075 g_error ("Runtime critical type %s.%s not found", name_space, name);
8076 if (!mono_error_ok (&error))
8077 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8082 * mono_class_try_load_from_name:
8083 * @image: The MonoImage where the type is looked up in
8084 * @name_space: the type namespace
8085 * @name: the type short name.
8087 * This function tries to load a type, returning the class was found or NULL otherwise.
8088 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8090 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8091 * a type that we would otherwise assume to be available but was not due some error.
8095 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8100 klass = mono_class_from_name_checked (image, name_space, name, &error);
8101 if (!mono_error_ok (&error))
8102 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8108 * mono_class_is_subclass_of:
8109 * @klass: class to probe if it is a subclass of another one
8110 * @klassc: the class we suspect is the base class
8111 * @check_interfaces: whether we should perform interface checks
8113 * This method determines whether @klass is a subclass of @klassc.
8115 * If the @check_interfaces flag is set, then if @klassc is an interface
8116 * this method return TRUE if the @klass implements the interface or
8117 * if @klass is an interface, if one of its base classes is @klass.
8119 * If @check_interfaces is false then, then if @klass is not an interface
8120 * then it returns TRUE if the @klass is a subclass of @klassc.
8122 * if @klass is an interface and @klassc is System.Object, then this function
8127 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8128 gboolean check_interfaces)
8130 /* FIXME test for interfaces with variant generic arguments */
8131 mono_class_init (klass);
8132 mono_class_init (klassc);
8134 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8135 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8137 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8140 for (i = 0; i < klass->interface_count; i ++) {
8141 MonoClass *ic = klass->interfaces [i];
8146 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8151 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8154 if (klassc == mono_defaults.object_class)
8161 mono_type_is_generic_argument (MonoType *type)
8163 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8167 mono_class_has_variant_generic_params (MonoClass *klass)
8170 MonoGenericContainer *container;
8172 if (!mono_class_is_ginst (klass))
8175 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8177 for (i = 0; i < container->type_argc; ++i)
8178 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8185 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8187 if (target == candidate)
8190 if (check_for_reference_conv &&
8191 mono_type_is_generic_argument (&target->byval_arg) &&
8192 mono_type_is_generic_argument (&candidate->byval_arg)) {
8193 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8194 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8196 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8199 if (!mono_class_is_assignable_from (target, candidate))
8205 * @container the generic container from the GTD
8206 * @klass: the class to be assigned to
8207 * @oklass: the source class
8209 * Both @klass and @oklass must be instances of the same generic interface.
8211 * Returns: TRUE if @klass can be assigned to a @klass variable
8214 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8217 MonoType **klass_argv, **oklass_argv;
8218 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8219 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8221 if (klass == oklass)
8224 /*Viable candidates are instances of the same generic interface*/
8225 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8228 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8229 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8231 for (j = 0; j < container->type_argc; ++j) {
8232 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8233 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8235 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8239 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8240 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8242 if (param1_class != param2_class) {
8243 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8244 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8246 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8247 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8257 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8259 MonoGenericParam *gparam, *ogparam;
8260 MonoGenericParamInfo *tinfo, *cinfo;
8261 MonoClass **candidate_class;
8262 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8265 if (target == candidate)
8267 if (target->byval_arg.type != candidate->byval_arg.type)
8270 gparam = target->byval_arg.data.generic_param;
8271 ogparam = candidate->byval_arg.data.generic_param;
8272 tinfo = mono_generic_param_info (gparam);
8273 cinfo = mono_generic_param_info (ogparam);
8275 class_constraint_satisfied = FALSE;
8276 valuetype_constraint_satisfied = FALSE;
8278 /*candidate must have a super set of target's special constraints*/
8279 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8280 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8282 if (cinfo->constraints) {
8283 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8284 MonoClass *cc = *candidate_class;
8286 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8287 class_constraint_satisfied = TRUE;
8288 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8289 valuetype_constraint_satisfied = TRUE;
8292 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8293 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8295 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8297 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8299 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8300 valuetype_constraint_satisfied)) {
8305 /*candidate type constraints must be a superset of target's*/
8306 if (tinfo->constraints) {
8307 MonoClass **target_class;
8308 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8309 MonoClass *tc = *target_class;
8312 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8313 * check it's constraints since it satisfy the constraint by itself.
8315 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8318 if (!cinfo->constraints)
8321 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8322 MonoClass *cc = *candidate_class;
8324 if (mono_class_is_assignable_from (tc, cc))
8328 * This happens when we have the following:
8330 * Bar<K> where K : IFace
8331 * Foo<T, U> where T : U where U : IFace
8333 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8336 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8337 if (mono_gparam_is_assignable_from (target, cc))
8341 if (!*candidate_class)
8346 /*candidate itself must have a constraint that satisfy target*/
8347 if (cinfo->constraints) {
8348 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8349 MonoClass *cc = *candidate_class;
8350 if (mono_class_is_assignable_from (target, cc))
8358 * mono_class_is_assignable_from:
8359 * @klass: the class to be assigned to
8360 * @oklass: the source class
8362 * Returns: TRUE if an instance of object oklass can be assigned to an
8363 * instance of object @klass
8366 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8369 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8371 mono_class_init (klass);
8373 if (!oklass->inited)
8374 mono_class_init (oklass);
8376 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8379 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8380 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8382 return mono_gparam_is_assignable_from (klass, oklass);
8385 if (MONO_CLASS_IS_INTERFACE (klass)) {
8386 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8387 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8388 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8392 for (i = 0; constraints [i]; ++i) {
8393 if (mono_class_is_assignable_from (klass, constraints [i]))
8401 /* interface_offsets might not be set for dynamic classes */
8402 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8404 * oklass might be a generic type parameter but they have
8405 * interface_offsets set.
8407 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8408 if (!is_ok (&error)) {
8409 mono_error_cleanup (&error);
8414 if (!oklass->interface_bitmap)
8415 /* Happens with generic instances of not-yet created dynamic types */
8417 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8420 if (mono_class_has_variant_generic_params (klass)) {
8422 mono_class_setup_interfaces (oklass, &error);
8423 if (!mono_error_ok (&error)) {
8424 mono_error_cleanup (&error);
8428 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8429 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8430 MonoClass *iface = oklass->interfaces_packed [i];
8432 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8437 } else if (klass->delegate) {
8438 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8440 }else if (klass->rank) {
8441 MonoClass *eclass, *eoclass;
8443 if (oklass->rank != klass->rank)
8446 /* vectors vs. one dimensional arrays */
8447 if (oklass->byval_arg.type != klass->byval_arg.type)
8450 eclass = klass->cast_class;
8451 eoclass = oklass->cast_class;
8454 * a is b does not imply a[] is b[] when a is a valuetype, and
8455 * b is a reference type.
8458 if (eoclass->valuetype) {
8459 if ((eclass == mono_defaults.enum_class) ||
8460 (eclass == mono_defaults.enum_class->parent) ||
8461 (eclass == mono_defaults.object_class))
8465 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8466 } else if (mono_class_is_nullable (klass)) {
8467 if (mono_class_is_nullable (oklass))
8468 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8470 return mono_class_is_assignable_from (klass->cast_class, oklass);
8471 } else if (klass == mono_defaults.object_class)
8474 return mono_class_has_parent (oklass, klass);
8477 /*Check if @oklass is variant compatible with @klass.*/
8479 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8482 MonoType **klass_argv, **oklass_argv;
8483 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8484 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8486 /*Viable candidates are instances of the same generic interface*/
8487 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8490 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8491 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8493 for (j = 0; j < container->type_argc; ++j) {
8494 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8495 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8497 if (param1_class->valuetype != param2_class->valuetype)
8501 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8502 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8504 if (param1_class != param2_class) {
8505 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8506 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8508 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8509 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8517 /*Check if @candidate implements the interface @target*/
8519 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8523 gboolean is_variant = mono_class_has_variant_generic_params (target);
8525 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8526 if (mono_class_is_variant_compatible_slow (target, candidate))
8531 if (candidate == target)
8534 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8535 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8536 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8538 if (tb && tb->interfaces) {
8539 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8540 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8541 MonoClass *iface_class;
8543 /* we can't realize the type here since it can do pretty much anything. */
8546 iface_class = mono_class_from_mono_type (iface->type);
8547 if (iface_class == target)
8549 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8551 if (mono_class_implement_interface_slow (target, iface_class))
8556 /*setup_interfaces don't mono_class_init anything*/
8557 /*FIXME this doesn't handle primitive type arrays.
8558 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8559 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8561 mono_class_setup_interfaces (candidate, &error);
8562 if (!mono_error_ok (&error)) {
8563 mono_error_cleanup (&error);
8567 for (i = 0; i < candidate->interface_count; ++i) {
8568 if (candidate->interfaces [i] == target)
8571 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8574 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8578 candidate = candidate->parent;
8579 } while (candidate);
8585 * Check if @oklass can be assigned to @klass.
8586 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8589 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8591 if (candidate == target)
8593 if (target == mono_defaults.object_class)
8596 if (mono_class_has_parent (candidate, target))
8599 /*If target is not an interface there is no need to check them.*/
8600 if (MONO_CLASS_IS_INTERFACE (target))
8601 return mono_class_implement_interface_slow (target, candidate);
8603 if (target->delegate && mono_class_has_variant_generic_params (target))
8604 return mono_class_is_variant_compatible (target, candidate, FALSE);
8607 MonoClass *eclass, *eoclass;
8609 if (target->rank != candidate->rank)
8612 /* vectors vs. one dimensional arrays */
8613 if (target->byval_arg.type != candidate->byval_arg.type)
8616 eclass = target->cast_class;
8617 eoclass = candidate->cast_class;
8620 * a is b does not imply a[] is b[] when a is a valuetype, and
8621 * b is a reference type.
8624 if (eoclass->valuetype) {
8625 if ((eclass == mono_defaults.enum_class) ||
8626 (eclass == mono_defaults.enum_class->parent) ||
8627 (eclass == mono_defaults.object_class))
8631 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8633 /*FIXME properly handle nullables */
8634 /*FIXME properly handle (M)VAR */
8639 * mono_class_get_cctor:
8640 * @klass: A MonoClass pointer
8642 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8645 mono_class_get_cctor (MonoClass *klass)
8647 MonoCachedClassInfo cached_info;
8649 if (image_is_dynamic (klass->image)) {
8651 * has_cctor is not set for these classes because mono_class_init () is
8654 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8657 if (!klass->has_cctor)
8660 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8662 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8663 if (!mono_error_ok (&error))
8664 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8668 if (mono_class_is_ginst (klass) && !klass->methods)
8669 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8671 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8675 * mono_class_get_finalizer:
8676 * @klass: The MonoClass pointer
8678 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8681 mono_class_get_finalizer (MonoClass *klass)
8683 MonoCachedClassInfo cached_info;
8686 mono_class_init (klass);
8687 if (!mono_class_has_finalizer (klass))
8690 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8692 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8693 if (!mono_error_ok (&error))
8694 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8697 mono_class_setup_vtable (klass);
8698 return klass->vtable [finalize_slot];
8703 * mono_class_needs_cctor_run:
8704 * @klass: the MonoClass pointer
8705 * @caller: a MonoMethod describing the caller
8707 * Determines whenever the class has a static constructor and whenever it
8708 * needs to be called when executing CALLER.
8711 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8715 method = mono_class_get_cctor (klass);
8717 return (method == caller) ? FALSE : TRUE;
8723 * mono_class_array_element_size:
8726 * Returns: The number of bytes an element of type @klass
8727 * uses when stored into an array.
8730 mono_class_array_element_size (MonoClass *klass)
8732 MonoType *type = &klass->byval_arg;
8735 switch (type->type) {
8738 case MONO_TYPE_BOOLEAN:
8742 case MONO_TYPE_CHAR:
8751 case MONO_TYPE_CLASS:
8752 case MONO_TYPE_STRING:
8753 case MONO_TYPE_OBJECT:
8754 case MONO_TYPE_SZARRAY:
8755 case MONO_TYPE_ARRAY:
8756 return sizeof (gpointer);
8761 case MONO_TYPE_VALUETYPE:
8762 if (type->data.klass->enumtype) {
8763 type = mono_class_enum_basetype (type->data.klass);
8764 klass = klass->element_class;
8767 return mono_class_instance_size (klass) - sizeof (MonoObject);
8768 case MONO_TYPE_GENERICINST:
8769 type = &type->data.generic_class->container_class->byval_arg;
8772 case MONO_TYPE_MVAR: {
8775 return mono_type_size (type, &align);
8777 case MONO_TYPE_VOID:
8781 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8787 * mono_array_element_size:
8788 * @ac: pointer to a #MonoArrayClass
8790 * Returns: The size of single array element.
8793 mono_array_element_size (MonoClass *ac)
8795 g_assert (ac->rank);
8796 return ac->sizes.element_size;
8800 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8801 MonoGenericContext *context)
8804 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8805 g_assert (mono_error_ok (&error));
8810 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8811 MonoGenericContext *context, MonoError *error)
8813 mono_error_init (error);
8815 if (image_is_dynamic (image)) {
8816 MonoClass *tmp_handle_class;
8817 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8819 mono_error_assert_ok (error);
8820 g_assert (tmp_handle_class);
8822 *handle_class = tmp_handle_class;
8824 if (tmp_handle_class == mono_defaults.typehandle_class)
8825 return &((MonoClass*)obj)->byval_arg;
8830 switch (token & 0xff000000) {
8831 case MONO_TOKEN_TYPE_DEF:
8832 case MONO_TOKEN_TYPE_REF:
8833 case MONO_TOKEN_TYPE_SPEC: {
8836 *handle_class = mono_defaults.typehandle_class;
8837 type = mono_type_get_checked (image, token, context, error);
8841 mono_class_init (mono_class_from_mono_type (type));
8842 /* We return a MonoType* as handle */
8845 case MONO_TOKEN_FIELD_DEF: {
8847 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8849 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8853 *handle_class = mono_defaults.fieldhandle_class;
8854 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8858 mono_class_init (klass);
8859 return mono_class_get_field (klass, token);
8861 case MONO_TOKEN_METHOD_DEF:
8862 case MONO_TOKEN_METHOD_SPEC: {
8864 meth = mono_get_method_checked (image, token, NULL, context, error);
8866 *handle_class = mono_defaults.methodhandle_class;
8872 case MONO_TOKEN_MEMBER_REF: {
8873 guint32 cols [MONO_MEMBERREF_SIZE];
8875 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8876 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8877 mono_metadata_decode_blob_size (sig, &sig);
8878 if (*sig == 0x6) { /* it's a field */
8880 MonoClassField *field;
8881 field = mono_field_from_token_checked (image, token, &klass, context, error);
8883 *handle_class = mono_defaults.fieldhandle_class;
8887 meth = mono_get_method_checked (image, token, NULL, context, error);
8889 *handle_class = mono_defaults.methodhandle_class;
8894 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8900 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8902 MonoClass *handle_class;
8903 mono_error_init (error);
8904 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8908 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8910 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8913 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8916 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8918 get_cached_class_info = func;
8922 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8924 if (!get_cached_class_info)
8927 return get_cached_class_info (klass, res);
8931 mono_install_get_class_from_name (MonoGetClassFromName func)
8933 get_class_from_name = func;
8937 * mono_class_get_image:
8939 * Use this method to get the `MonoImage*` where this class came from.
8941 * Returns: The image where this class is defined.
8944 mono_class_get_image (MonoClass *klass)
8946 return klass->image;
8950 * mono_class_get_element_class:
8951 * @klass: the MonoClass to act on
8953 * Use this function to get the element class of an array.
8955 * Returns: The element class of an array.
8958 mono_class_get_element_class (MonoClass *klass)
8960 return klass->element_class;
8964 * mono_class_is_valuetype:
8965 * @klass: the MonoClass to act on
8967 * Use this method to determine if the provided `MonoClass*` represents a value type,
8968 * or a reference type.
8970 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8973 mono_class_is_valuetype (MonoClass *klass)
8975 return klass->valuetype;
8979 * mono_class_is_enum:
8980 * @klass: the MonoClass to act on
8982 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8984 * Returns: TRUE if the MonoClass represents an enumeration.
8987 mono_class_is_enum (MonoClass *klass)
8989 return klass->enumtype;
8993 * mono_class_enum_basetype:
8994 * @klass: the MonoClass to act on
8996 * Use this function to get the underlying type for an enumeration value.
8998 * Returns: The underlying type representation for an enumeration.
9001 mono_class_enum_basetype (MonoClass *klass)
9003 if (klass->element_class == klass)
9004 /* SRE or broken types */
9007 return &klass->element_class->byval_arg;
9011 * mono_class_get_parent
9012 * @klass: the MonoClass to act on
9014 * Returns: The parent class for this class.
9017 mono_class_get_parent (MonoClass *klass)
9019 return klass->parent;
9023 * mono_class_get_nesting_type:
9024 * @klass: the MonoClass to act on
9026 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9028 * If the return is NULL, this indicates that this class is not nested.
9030 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9033 mono_class_get_nesting_type (MonoClass *klass)
9035 return klass->nested_in;
9039 * mono_class_get_rank:
9040 * @klass: the MonoClass to act on
9042 * Returns: The rank for the array (the number of dimensions).
9045 mono_class_get_rank (MonoClass *klass)
9051 * mono_class_get_name
9052 * @klass: the MonoClass to act on
9054 * Returns: The name of the class.
9057 mono_class_get_name (MonoClass *klass)
9063 * mono_class_get_namespace:
9064 * @klass: the MonoClass to act on
9066 * Returns: The namespace of the class.
9069 mono_class_get_namespace (MonoClass *klass)
9071 return klass->name_space;
9075 * mono_class_get_type:
9076 * @klass: the MonoClass to act on
9078 * This method returns the internal Type representation for the class.
9080 * Returns: The MonoType from the class.
9083 mono_class_get_type (MonoClass *klass)
9085 return &klass->byval_arg;
9089 * mono_class_get_type_token:
9090 * @klass: the MonoClass to act on
9092 * This method returns type token for the class.
9094 * Returns: The type token for the class.
9097 mono_class_get_type_token (MonoClass *klass)
9099 return klass->type_token;
9103 * mono_class_get_byref_type:
9104 * @klass: the MonoClass to act on
9109 mono_class_get_byref_type (MonoClass *klass)
9111 return &klass->this_arg;
9115 * mono_class_num_fields:
9116 * @klass: the MonoClass to act on
9118 * Returns: The number of static and instance fields in the class.
9121 mono_class_num_fields (MonoClass *klass)
9123 return mono_class_get_field_count (klass);
9127 * mono_class_num_methods:
9128 * @klass: the MonoClass to act on
9130 * Returns: The number of methods in the class.
9133 mono_class_num_methods (MonoClass *klass)
9135 return mono_class_get_method_count (klass);
9139 * mono_class_num_properties
9140 * @klass: the MonoClass to act on
9142 * Returns: The number of properties in the class.
9145 mono_class_num_properties (MonoClass *klass)
9147 mono_class_setup_properties (klass);
9149 return mono_class_get_ext (klass)->property.count;
9153 * mono_class_num_events:
9154 * @klass: the MonoClass to act on
9156 * Returns: The number of events in the class.
9159 mono_class_num_events (MonoClass *klass)
9161 mono_class_setup_events (klass);
9163 return mono_class_get_ext (klass)->event.count;
9167 * mono_class_get_fields:
9168 * @klass: the MonoClass to act on
9170 * This routine is an iterator routine for retrieving the fields in a class.
9172 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9173 * iterate over all of the elements. When no more values are
9174 * available, the return value is NULL.
9176 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9179 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9181 MonoClassField* field;
9185 mono_class_setup_fields (klass);
9186 if (mono_class_has_failure (klass))
9188 /* start from the first */
9189 if (mono_class_get_field_count (klass)) {
9190 *iter = &klass->fields [0];
9191 return &klass->fields [0];
9197 field = (MonoClassField *)*iter;
9199 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9207 * mono_class_get_methods
9208 * @klass: the MonoClass to act on
9210 * This routine is an iterator routine for retrieving the fields in a class.
9212 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9213 * iterate over all of the elements. When no more values are
9214 * available, the return value is NULL.
9216 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9219 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9221 MonoMethod** method;
9225 mono_class_setup_methods (klass);
9228 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9229 * FIXME we should better report this error to the caller
9231 if (!klass->methods)
9233 /* start from the first */
9234 if (mono_class_get_method_count (klass)) {
9235 *iter = &klass->methods [0];
9236 return klass->methods [0];
9242 method = (MonoMethod **)*iter;
9244 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9252 * mono_class_get_virtual_methods:
9254 * Iterate over the virtual methods of KLASS.
9256 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9259 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9261 MonoMethod** method;
9264 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9266 mono_class_setup_methods (klass);
9268 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9269 * FIXME we should better report this error to the caller
9271 if (!klass->methods)
9273 /* start from the first */
9274 method = &klass->methods [0];
9276 method = (MonoMethod **)*iter;
9279 int mcount = mono_class_get_method_count (klass);
9280 while (method < &klass->methods [mcount]) {
9281 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9285 if (method < &klass->methods [mcount]) {
9292 /* Search directly in metadata to avoid calling setup_methods () */
9293 MonoMethod *res = NULL;
9299 start_index = GPOINTER_TO_UINT (*iter);
9302 int first_idx = mono_class_get_first_method_idx (klass);
9303 int mcount = mono_class_get_method_count (klass);
9304 for (i = start_index; i < mcount; ++i) {
9307 /* first_idx points into the methodptr table */
9308 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9310 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9316 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9317 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9319 /* Add 1 here so the if (*iter) check fails */
9320 *iter = GUINT_TO_POINTER (i + 1);
9329 * mono_class_get_properties:
9330 * @klass: the MonoClass to act on
9332 * This routine is an iterator routine for retrieving the properties in a class.
9334 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9335 * iterate over all of the elements. When no more values are
9336 * available, the return value is NULL.
9338 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9341 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9343 MonoProperty* property;
9347 mono_class_setup_properties (klass);
9348 MonoClassExt *ext = mono_class_get_ext (klass);
9349 /* start from the first */
9350 if (ext->property.count) {
9351 *iter = &ext->properties [0];
9352 return (MonoProperty *)*iter;
9358 property = (MonoProperty *)*iter;
9360 MonoClassExt *ext = mono_class_get_ext (klass);
9361 if (property < &ext->properties [ext->property.count]) {
9363 return (MonoProperty *)*iter;
9369 * mono_class_get_events:
9370 * @klass: the MonoClass to act on
9372 * This routine is an iterator routine for retrieving the properties in a class.
9374 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9375 * iterate over all of the elements. When no more values are
9376 * available, the return value is NULL.
9378 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9381 mono_class_get_events (MonoClass* klass, gpointer *iter)
9387 mono_class_setup_events (klass);
9388 MonoClassExt *ext = mono_class_get_ext (klass);
9389 /* start from the first */
9390 if (ext->event.count) {
9391 *iter = &ext->events [0];
9392 return (MonoEvent *)*iter;
9398 event = (MonoEvent *)*iter;
9400 MonoClassExt *ext = mono_class_get_ext (klass);
9401 if (event < &ext->events [ext->event.count]) {
9403 return (MonoEvent *)*iter;
9409 * mono_class_get_interfaces
9410 * @klass: the MonoClass to act on
9412 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9414 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9415 * iterate over all of the elements. When no more values are
9416 * available, the return value is NULL.
9418 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9421 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9429 mono_class_init (klass);
9430 if (!klass->interfaces_inited) {
9431 mono_class_setup_interfaces (klass, &error);
9432 if (!mono_error_ok (&error)) {
9433 mono_error_cleanup (&error);
9437 /* start from the first */
9438 if (klass->interface_count) {
9439 *iter = &klass->interfaces [0];
9440 return klass->interfaces [0];
9446 iface = (MonoClass **)*iter;
9448 if (iface < &klass->interfaces [klass->interface_count]) {
9456 setup_nested_types (MonoClass *klass)
9459 GList *classes, *nested_classes, *l;
9462 if (klass->nested_classes_inited)
9465 if (!klass->type_token)
9466 klass->nested_classes_inited = TRUE;
9468 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9472 guint32 cols [MONO_NESTED_CLASS_SIZE];
9473 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9474 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9475 if (!mono_error_ok (&error)) {
9476 /*FIXME don't swallow the error message*/
9477 mono_error_cleanup (&error);
9479 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9483 classes = g_list_prepend (classes, nclass);
9485 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9488 mono_class_alloc_ext (klass);
9490 nested_classes = NULL;
9491 for (l = classes; l; l = l->next)
9492 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9493 g_list_free (classes);
9495 mono_image_lock (klass->image);
9497 mono_memory_barrier ();
9498 if (!klass->nested_classes_inited) {
9499 mono_class_get_ext (klass)->nested_classes = nested_classes;
9500 mono_memory_barrier ();
9501 klass->nested_classes_inited = TRUE;
9504 mono_image_unlock (klass->image);
9508 * mono_class_get_nested_types
9509 * @klass: the MonoClass to act on
9511 * This routine is an iterator routine for retrieving the nested types of a class.
9512 * This works only if @klass is non-generic, or a generic type definition.
9514 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9515 * iterate over all of the elements. When no more values are
9516 * available, the return value is NULL.
9518 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9521 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9527 if (!klass->nested_classes_inited)
9528 setup_nested_types (klass);
9531 MonoClassExt *ext = mono_class_get_ext (klass);
9532 /* start from the first */
9533 if (ext && ext->nested_classes) {
9534 *iter = ext->nested_classes;
9535 return (MonoClass *)ext->nested_classes->data;
9537 /* no nested types */
9541 item = (GList *)*iter;
9545 return (MonoClass *)item->data;
9552 * mono_class_is_delegate
9553 * @klass: the MonoClass to act on
9555 * Returns: TRUE if the MonoClass represents a System.Delegate.
9558 mono_class_is_delegate (MonoClass *klass)
9560 return klass->delegate;
9564 * mono_class_implements_interface
9565 * @klass: The MonoClass to act on
9566 * @interface: The interface to check if @klass implements.
9568 * Returns: TRUE if @klass implements @interface.
9571 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9573 return mono_class_is_assignable_from (iface, klass);
9577 * mono_field_get_name:
9578 * @field: the MonoClassField to act on
9580 * Returns: The name of the field.
9583 mono_field_get_name (MonoClassField *field)
9589 * mono_field_get_type:
9590 * @field: the MonoClassField to act on
9592 * Returns: MonoType of the field.
9595 mono_field_get_type (MonoClassField *field)
9598 MonoType *type = mono_field_get_type_checked (field, &error);
9599 if (!mono_error_ok (&error)) {
9600 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9601 mono_error_cleanup (&error);
9608 * mono_field_get_type_checked:
9609 * @field: the MonoClassField to act on
9610 * @error: used to return any erro found while retrieving @field type
9612 * Returns: MonoType of the field.
9615 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9617 mono_error_init (error);
9619 mono_field_resolve_type (field, error);
9624 * mono_field_get_parent:
9625 * @field: the MonoClassField to act on
9627 * Returns: MonoClass where the field was defined.
9630 mono_field_get_parent (MonoClassField *field)
9632 return field->parent;
9636 * mono_field_get_flags;
9637 * @field: the MonoClassField to act on
9639 * The metadata flags for a field are encoded using the
9640 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9642 * Returns: The flags for the field.
9645 mono_field_get_flags (MonoClassField *field)
9648 return mono_field_resolve_flags (field);
9649 return field->type->attrs;
9653 * mono_field_get_offset:
9654 * @field: the MonoClassField to act on
9656 * Returns: The field offset.
9659 mono_field_get_offset (MonoClassField *field)
9661 return field->offset;
9665 mono_field_get_rva (MonoClassField *field)
9669 MonoClass *klass = field->parent;
9670 MonoFieldDefaultValue *field_def_values;
9672 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9674 MonoClassExt *ext = mono_class_get_ext (klass);
9675 if (!ext || !ext->field_def_values) {
9676 mono_class_alloc_ext (klass);
9677 ext = mono_class_get_ext (klass);
9679 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9681 mono_image_lock (klass->image);
9682 if (!ext->field_def_values)
9683 ext->field_def_values = field_def_values;
9684 mono_image_unlock (klass->image);
9687 field_index = mono_field_get_index (field);
9689 if (!ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9690 int first_field_idx = mono_class_get_first_field_idx (klass);
9691 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9693 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9694 ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9697 return ext->field_def_values [field_index].data;
9701 * mono_field_get_data:
9702 * @field: the MonoClassField to act on
9704 * Returns: A pointer to the metadata constant value or to the field
9705 * data if it has an RVA flag.
9708 mono_field_get_data (MonoClassField *field)
9710 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9711 MonoTypeEnum def_type;
9713 return mono_class_get_field_default_value (field, &def_type);
9714 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9715 return mono_field_get_rva (field);
9722 * mono_property_get_name:
9723 * @prop: the MonoProperty to act on
9725 * Returns: The name of the property
9728 mono_property_get_name (MonoProperty *prop)
9734 * mono_property_get_set_method
9735 * @prop: the MonoProperty to act on.
9737 * Returns: The setter method of the property (A MonoMethod)
9740 mono_property_get_set_method (MonoProperty *prop)
9746 * mono_property_get_get_method
9747 * @prop: the MonoProperty to act on.
9749 * Returns: The setter method of the property (A MonoMethod)
9752 mono_property_get_get_method (MonoProperty *prop)
9758 * mono_property_get_parent:
9759 * @prop: the MonoProperty to act on.
9761 * Returns: The MonoClass where the property was defined.
9764 mono_property_get_parent (MonoProperty *prop)
9766 return prop->parent;
9770 * mono_property_get_flags:
9771 * @prop: the MonoProperty to act on.
9773 * The metadata flags for a property are encoded using the
9774 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9776 * Returns: The flags for the property.
9779 mono_property_get_flags (MonoProperty *prop)
9785 * mono_event_get_name:
9786 * @event: the MonoEvent to act on
9788 * Returns: The name of the event.
9791 mono_event_get_name (MonoEvent *event)
9797 * mono_event_get_add_method:
9798 * @event: The MonoEvent to act on.
9800 * Returns: The @add' method for the event (a MonoMethod).
9803 mono_event_get_add_method (MonoEvent *event)
9809 * mono_event_get_remove_method:
9810 * @event: The MonoEvent to act on.
9812 * Returns: The @remove method for the event (a MonoMethod).
9815 mono_event_get_remove_method (MonoEvent *event)
9817 return event->remove;
9821 * mono_event_get_raise_method:
9822 * @event: The MonoEvent to act on.
9824 * Returns: The @raise method for the event (a MonoMethod).
9827 mono_event_get_raise_method (MonoEvent *event)
9829 return event->raise;
9833 * mono_event_get_parent:
9834 * @event: the MonoEvent to act on.
9836 * Returns: The MonoClass where the event is defined.
9839 mono_event_get_parent (MonoEvent *event)
9841 return event->parent;
9845 * mono_event_get_flags
9846 * @event: the MonoEvent to act on.
9848 * The metadata flags for an event are encoded using the
9849 * EVENT_* constants. See the tabledefs.h file for details.
9851 * Returns: The flags for the event.
9854 mono_event_get_flags (MonoEvent *event)
9856 return event->attrs;
9860 * mono_class_get_method_from_name:
9861 * @klass: where to look for the method
9862 * @name: name of the method
9863 * @param_count: number of parameters. -1 for any number.
9865 * Obtains a MonoMethod with a given name and number of parameters.
9866 * It only works if there are no multiple signatures for any given method name.
9869 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9871 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9875 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9877 MonoMethod *res = NULL;
9880 /* Search directly in the metadata to avoid calling setup_methods () */
9881 int first_idx = mono_class_get_first_method_idx (klass);
9882 int mcount = mono_class_get_method_count (klass);
9883 for (i = 0; i < mcount; ++i) {
9885 guint32 cols [MONO_METHOD_SIZE];
9887 MonoMethodSignature *sig;
9889 /* first_idx points into the methodptr table */
9890 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9892 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9893 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9895 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9898 if (param_count == -1) {
9902 sig = mono_method_signature_checked (method, &error);
9904 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9907 if (sig->param_count == param_count) {
9918 * mono_class_get_method_from_name_flags:
9919 * @klass: where to look for the method
9920 * @name_space: name of the method
9921 * @param_count: number of parameters. -1 for any number.
9922 * @flags: flags which must be set in the method
9924 * Obtains a MonoMethod with a given name and number of parameters.
9925 * It only works if there are no multiple signatures for any given method name.
9928 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9930 MonoMethod *res = NULL;
9933 mono_class_init (klass);
9935 if (mono_class_is_ginst (klass) && !klass->methods) {
9936 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9939 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9940 if (!mono_error_ok (&error))
9941 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9946 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9947 mono_class_setup_methods (klass);
9949 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9950 See mono/tests/array_load_exception.il
9951 FIXME we should better report this error to the caller
9953 if (!klass->methods)
9955 int mcount = mono_class_get_method_count (klass);
9956 for (i = 0; i < mcount; ++i) {
9957 MonoMethod *method = klass->methods [i];
9959 if (method->name[0] == name [0] &&
9960 !strcmp (name, method->name) &&
9961 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9962 ((method->flags & flags) == flags)) {
9969 res = find_method_in_metadata (klass, name, param_count, flags);
9976 * mono_class_set_failure:
9977 * @klass: class in which the failure was detected
9978 * @ex_type: the kind of exception/error to be thrown (later)
9979 * @ex_data: exception data (specific to each type of exception/error)
9981 * Keep a detected failure informations in the class for later processing.
9982 * Note that only the first failure is kept.
9984 * LOCKING: Acquires the loader lock.
9987 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9989 g_assert (boxed_error != NULL);
9991 if (mono_class_has_failure (klass))
9994 mono_loader_lock ();
9995 klass->has_failure = 1;
9996 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9997 mono_loader_unlock ();
10003 mono_class_has_failure (const MonoClass *klass)
10005 g_assert (klass != NULL);
10006 return klass->has_failure != 0;
10011 * mono_class_set_type_load_failure:
10012 * @klass: class in which the failure was detected
10013 * @fmt: Printf-style error message string.
10015 * Collect detected failure informaion in the class for later processing.
10016 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
10017 * Note that only the first failure is kept.
10019 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
10021 * LOCKING: Acquires the loader lock.
10024 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
10026 MonoError prepare_error;
10029 if (mono_class_has_failure (klass))
10032 mono_error_init (&prepare_error);
10034 va_start (args, fmt);
10035 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10038 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10039 mono_error_cleanup (&prepare_error);
10040 return mono_class_set_failure (klass, box);
10044 * mono_class_get_exception_data:
10046 * Return the exception_data property of KLASS.
10048 * LOCKING: Acquires the loader lock.
10051 mono_class_get_exception_data (const MonoClass *klass)
10053 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10057 * mono_classes_init:
10059 * Initialize the resources used by this module.
10062 mono_classes_init (void)
10064 mono_os_mutex_init (&classes_mutex);
10066 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10067 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10069 mono_counters_register ("MonoClassDef count",
10070 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10071 mono_counters_register ("MonoClassGtd count",
10072 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10073 mono_counters_register ("MonoClassGenericInst count",
10074 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10075 mono_counters_register ("MonoClassGenericParam count",
10076 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10077 mono_counters_register ("MonoClassArray count",
10078 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10079 mono_counters_register ("MonoClassPointer count",
10080 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10081 mono_counters_register ("Inflated methods size",
10082 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10083 mono_counters_register ("Inflated classes size",
10084 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10085 mono_counters_register ("MonoClass size",
10086 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10087 mono_counters_register ("MonoClassExt size",
10088 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10090 mono_counters_register ("MonoClassExt count",
10091 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10095 * mono_classes_cleanup:
10097 * Free the resources used by this module.
10100 mono_classes_cleanup (void)
10102 mono_native_tls_free (setup_fields_tls_id);
10103 mono_native_tls_free (init_pending_tls_id);
10105 if (global_interface_bitset)
10106 mono_bitset_free (global_interface_bitset);
10107 global_interface_bitset = NULL;
10108 mono_os_mutex_destroy (&classes_mutex);
10112 * mono_class_get_exception_for_failure:
10113 * @klass: class in which the failure was detected
10115 * Return a constructed MonoException than the caller can then throw
10116 * using mono_raise_exception - or NULL if no failure is present (or
10117 * doesn't result in an exception).
10120 mono_class_get_exception_for_failure (MonoClass *klass)
10122 if (!mono_class_has_failure (klass))
10124 MonoError unboxed_error;
10125 mono_error_init (&unboxed_error);
10126 mono_error_set_for_class_failure (&unboxed_error, klass);
10127 return mono_error_convert_to_exception (&unboxed_error);
10131 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10133 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10134 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10136 if (outer_klass == inner_klass)
10138 inner_klass = inner_klass->nested_in;
10139 } while (inner_klass);
10144 mono_class_get_generic_type_definition (MonoClass *klass)
10146 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10147 return gklass ? gklass->container_class : klass;
10151 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10153 * Generic instantiations are ignored for all super types of @klass.
10155 * Visibility checks ignoring generic instantiations.
10158 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10161 klass = mono_class_get_generic_type_definition (klass);
10162 parent = mono_class_get_generic_type_definition (parent);
10163 mono_class_setup_supertypes (klass);
10165 for (i = 0; i < klass->idepth; ++i) {
10166 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10172 * Subtype can only access parent members with family protection if the site object
10173 * is subclass of Subtype. For example:
10174 * class A { protected int x; }
10176 * void valid_access () {
10180 * void invalid_access () {
10187 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10189 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10192 if (context_klass == NULL)
10194 /*if access_klass is not member_klass context_klass must be type compat*/
10195 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10201 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10204 if (accessing == accessed)
10206 if (!accessed || !accessing)
10209 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10210 * anywhere so untrusted friends are not safe to access platform's code internals */
10211 if (mono_security_core_clr_enabled ()) {
10212 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10216 mono_assembly_load_friends (accessed);
10217 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10218 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10219 /* Be conservative with checks */
10220 if (!friend_->name)
10222 if (strcmp (accessing->aname.name, friend_->name))
10224 if (friend_->public_key_token [0]) {
10225 if (!accessing->aname.public_key_token [0])
10227 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10236 * If klass is a generic type or if it is derived from a generic type, return the
10237 * MonoClass of the generic definition
10238 * Returns NULL if not found
10241 get_generic_definition_class (MonoClass *klass)
10244 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10245 if (gklass && gklass->container_class)
10246 return gklass->container_class;
10247 klass = klass->parent;
10253 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10256 for (i = 0; i < ginst->type_argc; ++i) {
10257 MonoType *type = ginst->type_argv[i];
10258 switch (type->type) {
10259 case MONO_TYPE_SZARRAY:
10260 if (!can_access_type (access_klass, type->data.klass))
10263 case MONO_TYPE_ARRAY:
10264 if (!can_access_type (access_klass, type->data.array->eklass))
10267 case MONO_TYPE_PTR:
10268 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10271 case MONO_TYPE_CLASS:
10272 case MONO_TYPE_VALUETYPE:
10273 case MONO_TYPE_GENERICINST:
10274 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10284 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10288 if (access_klass == member_klass)
10291 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10294 if (access_klass->element_class && !access_klass->enumtype)
10295 access_klass = access_klass->element_class;
10297 if (member_klass->element_class && !member_klass->enumtype)
10298 member_klass = member_klass->element_class;
10300 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10302 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10305 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10308 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10311 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10314 /*Non nested type with nested visibility. We just fail it.*/
10315 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10318 switch (access_level) {
10319 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10320 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10322 case TYPE_ATTRIBUTE_PUBLIC:
10325 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10328 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10329 return is_nesting_type (member_klass, access_klass);
10331 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10332 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10334 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10335 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10337 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10338 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10339 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10341 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10342 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10343 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10348 /* FIXME: check visibility of type, too */
10350 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10352 MonoClass *member_generic_def;
10353 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10356 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10357 if (((access_gklass && access_gklass->container_class) ||
10358 mono_class_is_gtd (access_klass)) &&
10359 (member_generic_def = get_generic_definition_class (member_klass))) {
10360 MonoClass *access_container;
10362 if (mono_class_is_gtd (access_klass))
10363 access_container = access_klass;
10365 access_container = access_gklass->container_class;
10367 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10371 /* Partition I 8.5.3.2 */
10372 /* the access level values are the same for fields and methods */
10373 switch (access_level) {
10374 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10375 /* same compilation unit */
10376 return access_klass->image == member_klass->image;
10377 case FIELD_ATTRIBUTE_PRIVATE:
10378 return access_klass == member_klass;
10379 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10380 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10381 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10384 case FIELD_ATTRIBUTE_ASSEMBLY:
10385 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10386 case FIELD_ATTRIBUTE_FAMILY:
10387 if (is_valid_family_access (access_klass, member_klass, context_klass))
10390 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10391 if (is_valid_family_access (access_klass, member_klass, context_klass))
10393 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10394 case FIELD_ATTRIBUTE_PUBLIC:
10401 * mono_method_can_access_field:
10402 * @method: Method that will attempt to access the field
10403 * @field: the field to access
10405 * Used to determine if a method is allowed to access the specified field.
10407 * Returns: TRUE if the given @method is allowed to access the @field while following
10408 * the accessibility rules of the CLI.
10411 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10413 /* FIXME: check all overlapping fields */
10414 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10416 MonoClass *nested = method->klass->nested_in;
10418 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10421 nested = nested->nested_in;
10428 * mono_method_can_access_method:
10429 * @method: Method that will attempt to access the other method
10430 * @called: the method that we want to probe for accessibility.
10432 * Used to determine if the @method is allowed to access the specified @called method.
10434 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10435 * the accessibility rules of the CLI.
10438 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10440 method = mono_method_get_method_definition (method);
10441 called = mono_method_get_method_definition (called);
10442 return mono_method_can_access_method_full (method, called, NULL);
10446 * mono_method_can_access_method_full:
10447 * @method: The caller method
10448 * @called: The called method
10449 * @context_klass: The static type on stack of the owner @called object used
10451 * This function must be used with instance calls, as they have more strict family accessibility.
10452 * It can be used with static methods, but context_klass should be NULL.
10454 * Returns: TRUE if caller have proper visibility and acessibility to @called
10457 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10459 /* Wrappers are except from access checks */
10460 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10463 MonoClass *access_class = method->klass;
10464 MonoClass *member_class = called->klass;
10465 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10467 MonoClass *nested = access_class->nested_in;
10469 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10472 nested = nested->nested_in;
10479 can = can_access_type (access_class, member_class);
10481 MonoClass *nested = access_class->nested_in;
10483 can = can_access_type (nested, member_class);
10486 nested = nested->nested_in;
10493 if (called->is_inflated) {
10494 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10495 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10504 * mono_method_can_access_field_full:
10505 * @method: The caller method
10506 * @field: The accessed field
10507 * @context_klass: The static type on stack of the owner @field object used
10509 * This function must be used with instance fields, as they have more strict family accessibility.
10510 * It can be used with static fields, but context_klass should be NULL.
10512 * Returns: TRUE if caller have proper visibility and acessibility to @field
10515 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10517 MonoClass *access_class = method->klass;
10518 MonoClass *member_class = field->parent;
10519 /* FIXME: check all overlapping fields */
10520 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10522 MonoClass *nested = access_class->nested_in;
10524 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10527 nested = nested->nested_in;
10534 can = can_access_type (access_class, member_class);
10536 MonoClass *nested = access_class->nested_in;
10538 can = can_access_type (nested, member_class);
10541 nested = nested->nested_in;
10551 * mono_class_can_access_class:
10552 * @source_class: The source class
10553 * @target_class: The accessed class
10555 * This function returns is @target_class is visible to @source_class
10557 * Returns: TRUE if source have proper visibility and acessibility to target
10560 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10562 return can_access_type (source_class, target_class);
10566 * mono_type_is_valid_enum_basetype:
10567 * @type: The MonoType to check
10569 * Returns: TRUE if the type can be used as the basetype of an enum
10571 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10572 switch (type->type) {
10575 case MONO_TYPE_BOOLEAN:
10578 case MONO_TYPE_CHAR:
10592 * mono_class_is_valid_enum:
10593 * @klass: An enum class to be validated
10595 * This method verify the required properties an enum should have.
10597 * Returns: TRUE if the informed enum class is valid
10599 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10600 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10601 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10604 mono_class_is_valid_enum (MonoClass *klass)
10606 MonoClassField * field;
10607 gpointer iter = NULL;
10608 gboolean found_base_field = FALSE;
10610 g_assert (klass->enumtype);
10611 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10612 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10616 if (!mono_class_is_auto_layout (klass))
10619 while ((field = mono_class_get_fields (klass, &iter))) {
10620 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10621 if (found_base_field)
10623 found_base_field = TRUE;
10624 if (!mono_type_is_valid_enum_basetype (field->type))
10629 if (!found_base_field)
10632 if (mono_class_get_method_count (klass) > 0)
10639 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10641 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10645 * mono_class_setup_interface_id:
10647 * Initializes MonoClass::interface_id if required.
10649 * LOCKING: Acquires the loader lock.
10652 mono_class_setup_interface_id (MonoClass *klass)
10654 mono_loader_lock ();
10655 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10656 klass->interface_id = mono_get_unique_iid (klass);
10657 mono_loader_unlock ();
10661 * mono_class_alloc_ext:
10663 * Allocate klass->ext if not already done.
10666 mono_class_alloc_ext (MonoClass *klass)
10670 if (mono_class_get_ext (klass))
10673 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10674 mono_image_lock (klass->image);
10675 mono_memory_barrier ();
10676 if (!mono_class_get_ext (klass))
10677 mono_class_set_ext (klass, ext);
10678 class_ext_size += sizeof (MonoClassExt);
10680 mono_image_unlock (klass->image);
10684 * mono_class_setup_interfaces:
10686 * Initialize klass->interfaces/interfaces_count.
10687 * LOCKING: Acquires the loader lock.
10688 * This function can fail the type.
10691 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10693 int i, interface_count;
10694 MonoClass **interfaces;
10696 mono_error_init (error);
10698 if (klass->interfaces_inited)
10701 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10702 MonoType *args [1];
10704 /* generic IList, ICollection, IEnumerable */
10705 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10706 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10708 args [0] = &klass->element_class->byval_arg;
10709 interfaces [0] = mono_class_bind_generic_parameters (
10710 mono_defaults.generic_ilist_class, 1, args, FALSE);
10711 if (interface_count > 1)
10712 interfaces [1] = mono_class_bind_generic_parameters (
10713 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10714 } else if (mono_class_is_ginst (klass)) {
10715 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10717 mono_class_setup_interfaces (gklass, error);
10718 if (!mono_error_ok (error)) {
10719 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10723 interface_count = gklass->interface_count;
10724 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10725 for (i = 0; i < interface_count; i++) {
10726 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10727 if (!mono_error_ok (error)) {
10728 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10733 interface_count = 0;
10737 mono_image_lock (klass->image);
10739 if (!klass->interfaces_inited) {
10740 klass->interface_count = interface_count;
10741 klass->interfaces = interfaces;
10743 mono_memory_barrier ();
10745 klass->interfaces_inited = TRUE;
10748 mono_image_unlock (klass->image);
10752 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10754 MonoClass *klass = field->parent;
10755 MonoImage *image = klass->image;
10756 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10758 int field_idx = field - klass->fields;
10760 mono_error_init (error);
10763 MonoClassField *gfield = >d->fields [field_idx];
10764 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10765 if (!mono_error_ok (error)) {
10766 char *full_name = mono_type_get_full_name (gtd);
10767 mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
10768 g_free (full_name);
10771 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10772 if (!mono_error_ok (error)) {
10773 char *full_name = mono_type_get_full_name (klass);
10774 mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10775 g_free (full_name);
10779 guint32 cols [MONO_FIELD_SIZE];
10780 MonoGenericContainer *container = NULL;
10781 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10783 /*FIXME, in theory we do not lazy load SRE fields*/
10784 g_assert (!image_is_dynamic (image));
10786 if (mono_class_is_gtd (klass)) {
10787 container = mono_class_get_generic_container (klass);
10789 container = mono_class_get_generic_container (gtd);
10790 g_assert (container);
10793 /* first_field_idx and idx points into the fieldptr table */
10794 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10796 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10797 char *full_name = mono_type_get_full_name (klass);
10798 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10799 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10800 g_free (full_name);
10804 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10806 mono_metadata_decode_value (sig, &sig);
10807 /* FIELD signature == 0x06 */
10808 g_assert (*sig == 0x06);
10810 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10812 char *full_name = mono_type_get_full_name (klass);
10813 mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10814 g_free (full_name);
10817 mono_memory_barrier ();
10818 field->type = ftype;
10822 mono_field_resolve_flags (MonoClassField *field)
10824 MonoClass *klass = field->parent;
10825 MonoImage *image = klass->image;
10826 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10827 int field_idx = field - klass->fields;
10831 MonoClassField *gfield = >d->fields [field_idx];
10832 return mono_field_get_flags (gfield);
10834 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10836 /*FIXME, in theory we do not lazy load SRE fields*/
10837 g_assert (!image_is_dynamic (image));
10839 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10844 * mono_class_get_fields_lazy:
10845 * @klass: the MonoClass to act on
10847 * This routine is an iterator routine for retrieving the fields in a class.
10848 * Only minimal information about fields are loaded. Accessors must be used
10849 * for all MonoClassField returned.
10851 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10852 * iterate over all of the elements. When no more values are
10853 * available, the return value is NULL.
10855 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10858 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10860 MonoClassField* field;
10864 mono_class_setup_basic_field_info (klass);
10865 if (!klass->fields)
10867 /* start from the first */
10868 if (mono_class_get_field_count (klass)) {
10869 *iter = &klass->fields [0];
10870 return (MonoClassField *)*iter;
10876 field = (MonoClassField *)*iter;
10878 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10880 return (MonoClassField *)*iter;
10886 mono_class_full_name (MonoClass *klass)
10888 return mono_type_full_name (&klass->byval_arg);
10891 /* Declare all shared lazy type lookup functions */
10892 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)