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 ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2099 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2100 g_print ("%d %d\n", klass->min_align, min_align);
2101 for (i = 0; i < top; ++i) {
2102 field = &klass->fields [i];
2103 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2104 printf (" %d %d\n", klass->fields [i].offset, field_offsets [i]);
2107 g_assert (klass->instance_size == instance_size);
2109 klass->instance_size = instance_size;
2111 klass->blittable = blittable;
2112 klass->has_references = has_references;
2113 klass->packing_size = packing_size;
2114 klass->min_align = min_align;
2115 for (i = 0; i < top; ++i) {
2116 field = &klass->fields [i];
2117 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2118 klass->fields [i].offset = field_offsets [i];
2121 mono_memory_barrier ();
2122 klass->size_inited = 1;
2123 mono_loader_unlock ();
2126 * Compute static field layout and size
2127 * Static fields can reference the class itself, so this has to be
2128 * done after instance_size etc. are initialized.
2131 for (i = 0; i < top; i++) {
2135 field = &klass->fields [i];
2137 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2139 if (mono_field_is_deleted (field))
2142 if (mono_type_has_exceptions (field->type)) {
2143 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2147 has_static_fields = TRUE;
2149 size = mono_type_size (field->type, &align);
2150 field_offsets [i] = class_size;
2151 /*align is always non-zero here*/
2152 field_offsets [i] += align - 1;
2153 field_offsets [i] &= ~(align - 1);
2154 class_size = field_offsets [i] + size;
2157 if (has_static_fields && class_size == 0)
2158 /* Simplify code which depends on class_size != 0 if the class has static fields */
2161 /* Compute klass->has_static_refs */
2162 has_static_refs = FALSE;
2163 for (i = 0; i < top; i++) {
2166 field = &klass->fields [i];
2168 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2169 ftype = mono_type_get_underlying_type (field->type);
2170 ftype = mono_type_get_basic_type_from_generic (ftype);
2171 if (type_has_references (klass, ftype))
2172 has_static_refs = TRUE;
2176 /*valuetypes can't be neither bigger than 1Mb or empty. */
2177 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2178 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2180 /* Publish the data */
2181 mono_loader_lock ();
2183 klass->sizes.class_size = class_size;
2184 klass->has_static_refs = has_static_refs;
2185 for (i = 0; i < top; ++i) {
2186 field = &klass->fields [i];
2188 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2189 field->offset = field_offsets [i];
2192 mono_memory_barrier ();
2193 klass->fields_inited = 1;
2194 mono_loader_unlock ();
2196 g_free (field_offsets);
2200 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2204 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2205 method->klass = klass;
2206 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2207 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2208 method->signature = sig;
2209 method->name = name;
2212 if (name [0] == '.') {
2213 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2215 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2221 * mono_class_setup_methods:
2224 * Initializes the 'methods' array in CLASS.
2225 * Calling this method should be avoided if possible since it allocates a lot
2226 * of long-living MonoMethod structures.
2227 * Methods belonging to an interface are assigned a sequential slot starting
2230 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2233 mono_class_setup_methods (MonoClass *klass)
2236 MonoMethod **methods;
2241 if (mono_class_is_ginst (klass)) {
2243 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2245 mono_class_init (gklass);
2246 if (!mono_class_has_failure (gklass))
2247 mono_class_setup_methods (gklass);
2248 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2251 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2252 count = mono_class_get_method_count (gklass);
2253 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2255 for (i = 0; i < count; i++) {
2256 methods [i] = mono_class_inflate_generic_method_full_checked (
2257 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2258 if (!mono_error_ok (&error)) {
2259 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2260 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2263 mono_error_cleanup (&error);
2267 } else if (klass->rank) {
2269 MonoMethod *amethod;
2270 MonoMethodSignature *sig;
2271 int count_generic = 0, first_generic = 0;
2273 gboolean jagged_ctor = FALSE;
2275 count = 3 + (klass->rank > 1? 2: 1);
2277 mono_class_setup_interfaces (klass, &error);
2278 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2280 if (klass->rank == 1 && klass->element_class->rank) {
2285 if (klass->interface_count) {
2286 count_generic = generic_array_methods (klass);
2287 first_generic = count;
2288 count += klass->interface_count * count_generic;
2291 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2293 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2294 sig->ret = &mono_defaults.void_class->byval_arg;
2295 sig->pinvoke = TRUE;
2296 sig->hasthis = TRUE;
2297 for (i = 0; i < klass->rank; ++i)
2298 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2300 amethod = create_array_method (klass, ".ctor", sig);
2301 methods [method_num++] = amethod;
2302 if (klass->rank > 1) {
2303 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2304 sig->ret = &mono_defaults.void_class->byval_arg;
2305 sig->pinvoke = TRUE;
2306 sig->hasthis = TRUE;
2307 for (i = 0; i < klass->rank * 2; ++i)
2308 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2310 amethod = create_array_method (klass, ".ctor", sig);
2311 methods [method_num++] = amethod;
2315 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2316 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2317 sig->ret = &mono_defaults.void_class->byval_arg;
2318 sig->pinvoke = TRUE;
2319 sig->hasthis = TRUE;
2320 for (i = 0; i < klass->rank + 1; ++i)
2321 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2322 amethod = create_array_method (klass, ".ctor", sig);
2323 methods [method_num++] = amethod;
2326 /* element Get (idx11, [idx2, ...]) */
2327 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2328 sig->ret = &klass->element_class->byval_arg;
2329 sig->pinvoke = TRUE;
2330 sig->hasthis = TRUE;
2331 for (i = 0; i < klass->rank; ++i)
2332 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2333 amethod = create_array_method (klass, "Get", sig);
2334 methods [method_num++] = amethod;
2335 /* element& Address (idx11, [idx2, ...]) */
2336 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2337 sig->ret = &klass->element_class->this_arg;
2338 sig->pinvoke = TRUE;
2339 sig->hasthis = TRUE;
2340 for (i = 0; i < klass->rank; ++i)
2341 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2342 amethod = create_array_method (klass, "Address", sig);
2343 methods [method_num++] = amethod;
2344 /* void Set (idx11, [idx2, ...], element) */
2345 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2346 sig->ret = &mono_defaults.void_class->byval_arg;
2347 sig->pinvoke = TRUE;
2348 sig->hasthis = TRUE;
2349 for (i = 0; i < klass->rank; ++i)
2350 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2351 sig->params [i] = &klass->element_class->byval_arg;
2352 amethod = create_array_method (klass, "Set", sig);
2353 methods [method_num++] = amethod;
2355 for (i = 0; i < klass->interface_count; i++)
2356 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2357 } else if (mono_class_has_static_metadata (klass)) {
2359 int first_idx = mono_class_get_first_method_idx (klass);
2361 count = mono_class_get_method_count (klass);
2362 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2363 for (i = 0; i < count; ++i) {
2364 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2365 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2367 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2368 mono_error_cleanup (&error);
2372 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2376 if (MONO_CLASS_IS_INTERFACE (klass)) {
2378 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2379 for (i = 0; i < count; ++i) {
2380 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2381 methods [i]->slot = slot++;
2385 mono_image_lock (klass->image);
2387 if (!klass->methods) {
2388 mono_class_set_method_count (klass, count);
2390 /* Needed because of the double-checking locking pattern */
2391 mono_memory_barrier ();
2393 klass->methods = methods;
2396 mono_image_unlock (klass->image);
2400 * mono_class_get_method_by_index:
2402 * Returns klass->methods [index], initializing klass->methods if neccesary.
2404 * LOCKING: Acquires the loader lock.
2407 mono_class_get_method_by_index (MonoClass *klass, int index)
2411 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2412 /* Avoid calling setup_methods () if possible */
2413 if (gklass && !klass->methods) {
2416 m = mono_class_inflate_generic_method_full_checked (
2417 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2418 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2420 * If setup_methods () is called later for this class, no duplicates are created,
2421 * since inflate_generic_method guarantees that only one instance of a method
2422 * is created for each context.
2425 mono_class_setup_methods (klass);
2426 g_assert (m == klass->methods [index]);
2430 mono_class_setup_methods (klass);
2431 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2433 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2434 return klass->methods [index];
2439 * mono_class_get_inflated_method:
2441 * Given an inflated class CLASS and a method METHOD which should be a method of
2442 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2445 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2447 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2450 g_assert (method->klass == gklass);
2452 mono_class_setup_methods (gklass);
2453 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2455 mcount = mono_class_get_method_count (gklass);
2456 for (i = 0; i < mcount; ++i) {
2457 if (gklass->methods [i] == method) {
2458 if (klass->methods) {
2459 return klass->methods [i];
2462 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2463 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2473 * mono_class_get_vtable_entry:
2475 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2476 * LOCKING: Acquires the loader lock.
2479 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2483 if (klass->rank == 1) {
2485 * szarrays do not overwrite any methods of Array, so we can avoid
2486 * initializing their vtables in some cases.
2488 mono_class_setup_vtable (klass->parent);
2489 if (offset < klass->parent->vtable_size)
2490 return klass->parent->vtable [offset];
2493 if (mono_class_is_ginst (klass)) {
2495 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2496 mono_class_setup_vtable (gklass);
2497 m = gklass->vtable [offset];
2499 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2500 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2502 mono_class_setup_vtable (klass);
2503 if (mono_class_has_failure (klass))
2505 m = klass->vtable [offset];
2512 * mono_class_get_vtable_size:
2514 * Return the vtable size for KLASS.
2517 mono_class_get_vtable_size (MonoClass *klass)
2519 mono_class_setup_vtable (klass);
2521 return klass->vtable_size;
2525 * mono_class_setup_properties:
2527 * Initialize klass->ext.property and klass->ext.properties.
2529 * This method can fail the class.
2532 mono_class_setup_properties (MonoClass *klass)
2534 guint startm, endm, i, j;
2535 guint32 cols [MONO_PROPERTY_SIZE];
2536 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2537 MonoProperty *properties;
2541 MonoClassExt *ext = mono_class_get_ext (klass);
2542 if (ext && ext->properties)
2545 if (mono_class_is_ginst (klass)) {
2546 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2548 mono_class_init (gklass);
2549 mono_class_setup_properties (gklass);
2550 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2553 MonoClassExt *gext = mono_class_get_ext (gklass);
2554 properties = mono_class_new0 (klass, MonoProperty, gext->property.count + 1);
2556 for (i = 0; i < gext->property.count; i++) {
2558 MonoProperty *prop = &properties [i];
2560 *prop = gext->properties [i];
2563 prop->get = mono_class_inflate_generic_method_full_checked (
2564 prop->get, klass, mono_class_get_context (klass), &error);
2566 prop->set = mono_class_inflate_generic_method_full_checked (
2567 prop->set, klass, mono_class_get_context (klass), &error);
2569 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2570 prop->parent = klass;
2573 first = gext->property.first;
2574 count = gext->property.count;
2576 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2577 count = last - first;
2580 mono_class_setup_methods (klass);
2581 if (mono_class_has_failure (klass))
2585 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2586 for (i = first; i < last; ++i) {
2587 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2588 properties [i - first].parent = klass;
2589 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2590 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2592 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2593 int first_idx = mono_class_get_first_method_idx (klass);
2594 for (j = startm; j < endm; ++j) {
2597 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2599 if (klass->image->uncompressed_metadata) {
2601 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2602 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2603 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2605 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2608 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2609 case METHOD_SEMANTIC_SETTER:
2610 properties [i - first].set = method;
2612 case METHOD_SEMANTIC_GETTER:
2613 properties [i - first].get = method;
2622 mono_class_alloc_ext (klass);
2623 ext = mono_class_get_ext (klass);
2625 mono_image_lock (klass->image);
2627 if (ext->properties) {
2628 /* We leak 'properties' which was allocated from the image mempool */
2629 mono_image_unlock (klass->image);
2633 ext->property.first = first;
2634 ext->property.count = count;
2636 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2637 mono_memory_barrier ();
2639 /* Leave this assignment as the last op in the function */
2640 ext->properties = properties;
2642 mono_image_unlock (klass->image);
2646 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2648 MonoMethod **om, **retval;
2651 for (om = methods, count = 0; *om; ++om, ++count)
2654 retval = g_new0 (MonoMethod*, count + 1);
2656 for (om = methods, count = 0; *om; ++om, ++count) {
2658 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2659 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2665 /*This method can fail the class.*/
2667 mono_class_setup_events (MonoClass *klass)
2670 guint startm, endm, i, j;
2671 guint32 cols [MONO_EVENT_SIZE];
2672 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2676 MonoClassExt *ext = mono_class_get_ext (klass);
2677 if (ext && ext->events)
2680 if (mono_class_is_ginst (klass)) {
2681 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2682 MonoGenericContext *context = NULL;
2684 mono_class_setup_events (gklass);
2685 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2688 MonoClassExt *gext = mono_class_get_ext (gklass);
2689 first = gext->event.first;
2690 count = gext->event.count;
2692 events = mono_class_new0 (klass, MonoEvent, count);
2695 context = mono_class_get_context (klass);
2697 for (i = 0; i < count; i++) {
2699 MonoEvent *event = &events [i];
2700 MonoEvent *gevent = &gext->events [i];
2702 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2704 event->parent = klass;
2705 event->name = gevent->name;
2706 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2707 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2708 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2709 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2710 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2711 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2713 #ifndef MONO_SMALL_CONFIG
2714 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2716 event->attrs = gevent->attrs;
2719 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2720 count = last - first;
2723 mono_class_setup_methods (klass);
2724 if (mono_class_has_failure (klass)) {
2729 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2730 for (i = first; i < last; ++i) {
2731 MonoEvent *event = &events [i - first];
2733 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2734 event->parent = klass;
2735 event->attrs = cols [MONO_EVENT_FLAGS];
2736 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2738 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2739 int first_idx = mono_class_get_first_method_idx (klass);
2740 for (j = startm; j < endm; ++j) {
2743 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2745 if (klass->image->uncompressed_metadata) {
2747 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2748 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2749 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2751 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2754 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2755 case METHOD_SEMANTIC_ADD_ON:
2756 event->add = method;
2758 case METHOD_SEMANTIC_REMOVE_ON:
2759 event->remove = method;
2761 case METHOD_SEMANTIC_FIRE:
2762 event->raise = method;
2764 case METHOD_SEMANTIC_OTHER: {
2765 #ifndef MONO_SMALL_CONFIG
2768 if (event->other == NULL) {
2769 event->other = g_new0 (MonoMethod*, 2);
2771 while (event->other [n])
2773 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2775 event->other [n] = method;
2776 /* NULL terminated */
2777 event->other [n + 1] = NULL;
2788 mono_class_alloc_ext (klass);
2789 ext = mono_class_get_ext (klass);
2791 mono_image_lock (klass->image);
2794 mono_image_unlock (klass->image);
2798 ext->event.first = first;
2799 ext->event.count = count;
2801 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2802 mono_memory_barrier ();
2804 /* Leave this assignment as the last op in the function */
2805 ext->events = events;
2807 mono_image_unlock (klass->image);
2811 * Global pool of interface IDs, represented as a bitset.
2812 * LOCKING: Protected by the classes lock.
2814 static MonoBitSet *global_interface_bitset = NULL;
2817 * mono_unload_interface_ids:
2818 * @bitset: bit set of interface IDs
2820 * When an image is unloaded, the interface IDs associated with
2821 * the image are put back in the global pool of IDs so the numbers
2825 mono_unload_interface_ids (MonoBitSet *bitset)
2828 mono_bitset_sub (global_interface_bitset, bitset);
2833 mono_unload_interface_id (MonoClass *klass)
2835 if (global_interface_bitset && klass->interface_id) {
2837 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2843 * mono_get_unique_iid:
2846 * Assign a unique integer ID to the interface represented by @class.
2847 * The ID will positive and as small as possible.
2848 * LOCKING: Acquires the classes lock.
2849 * Returns: The new ID.
2852 mono_get_unique_iid (MonoClass *klass)
2856 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2860 if (!global_interface_bitset) {
2861 global_interface_bitset = mono_bitset_new (128, 0);
2864 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2866 int old_size = mono_bitset_size (global_interface_bitset);
2867 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2868 mono_bitset_free (global_interface_bitset);
2869 global_interface_bitset = new_set;
2872 mono_bitset_set (global_interface_bitset, iid);
2873 /* set the bit also in the per-image set */
2874 if (!mono_class_is_ginst (klass)) {
2875 if (klass->image->interface_bitset) {
2876 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2877 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2878 mono_bitset_free (klass->image->interface_bitset);
2879 klass->image->interface_bitset = new_set;
2882 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2884 mono_bitset_set (klass->image->interface_bitset, iid);
2889 #ifndef MONO_SMALL_CONFIG
2890 if (mono_print_vtable) {
2892 char *type_name = mono_type_full_name (&klass->byval_arg);
2893 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2894 if (gklass && !gklass->context.class_inst->is_open) {
2895 generic_id = gklass->context.class_inst->id;
2896 g_assert (generic_id != 0);
2900 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2905 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2906 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2907 g_assert (iid < INT_MAX);
2912 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2917 mono_class_setup_interfaces (klass, error);
2918 return_if_nok (error);
2920 for (i = 0; i < klass->interface_count; i++) {
2921 ic = klass->interfaces [i];
2924 *res = g_ptr_array_new ();
2925 g_ptr_array_add (*res, ic);
2926 mono_class_init (ic);
2927 if (mono_class_has_failure (ic)) {
2928 mono_error_set_type_load_class (error, ic, "Error Loading class");
2932 collect_implemented_interfaces_aux (ic, res, error);
2933 return_if_nok (error);
2938 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2940 GPtrArray *res = NULL;
2942 collect_implemented_interfaces_aux (klass, &res, error);
2943 if (!mono_error_ok (error)) {
2945 g_ptr_array_free (res, TRUE);
2952 compare_interface_ids (const void *p_key, const void *p_element) {
2953 const MonoClass *key = (const MonoClass *)p_key;
2954 const MonoClass *element = *(const MonoClass **)p_element;
2956 return (key->interface_id - element->interface_id);
2959 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2961 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2962 MonoClass **result = (MonoClass **)mono_binary_search (
2964 klass->interfaces_packed,
2965 klass->interface_offsets_count,
2966 sizeof (MonoClass *),
2967 compare_interface_ids);
2969 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2976 * mono_class_interface_offset_with_variance:
2978 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2979 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2981 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2983 * FIXME figure out MS disambiguation rules and fix this function.
2986 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2987 int i = mono_class_interface_offset (klass, itf);
2988 *non_exact_match = FALSE;
2992 if (!mono_class_has_variant_generic_params (itf))
2995 for (i = 0; i < klass->interface_offsets_count; i++) {
2996 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2997 *non_exact_match = TRUE;
2998 return klass->interface_offsets_packed [i];
3006 print_implemented_interfaces (MonoClass *klass) {
3009 GPtrArray *ifaces = NULL;
3011 int ancestor_level = 0;
3013 name = mono_type_get_full_name (klass);
3014 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3017 for (i = 0; i < klass->interface_offsets_count; i++)
3018 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3019 klass->interfaces_packed [i]->interface_id,
3020 klass->interface_offsets_packed [i],
3021 mono_class_get_method_count (klass->interfaces_packed [i]),
3022 klass->interfaces_packed [i]->name_space,
3023 klass->interfaces_packed [i]->name );
3024 printf ("Interface flags: ");
3025 for (i = 0; i <= klass->max_interface_id; i++)
3026 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3027 printf ("(%d,T)", i);
3029 printf ("(%d,F)", i);
3031 printf ("Dump interface flags:");
3032 #ifdef COMPRESSED_INTERFACE_BITMAP
3034 const uint8_t* p = klass->interface_bitmap;
3035 i = klass->max_interface_id;
3037 printf (" %d x 00 %02X", p [0], p [1]);
3043 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3044 printf (" %02X", klass->interface_bitmap [i]);
3047 while (klass != NULL) {
3048 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3049 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3050 if (!mono_error_ok (&error)) {
3051 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3052 mono_error_cleanup (&error);
3053 } else if (ifaces) {
3054 for (i = 0; i < ifaces->len; i++) {
3055 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3056 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3057 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3059 mono_class_interface_offset (klass, ic),
3060 mono_class_get_method_count (ic),
3064 g_ptr_array_free (ifaces, TRUE);
3067 klass = klass->parent;
3072 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3075 args [0] = &arg0->byval_arg;
3077 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3081 array_class_get_if_rank (MonoClass *klass, guint rank)
3083 return rank ? mono_array_class_get (klass, rank) : klass;
3087 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3089 valuetype_types [0] = eclass;
3090 if (eclass == mono_defaults.int16_class)
3091 valuetype_types [1] = mono_defaults.uint16_class;
3092 else if (eclass == mono_defaults.uint16_class)
3093 valuetype_types [1] = mono_defaults.int16_class;
3094 else if (eclass == mono_defaults.int32_class)
3095 valuetype_types [1] = mono_defaults.uint32_class;
3096 else if (eclass == mono_defaults.uint32_class)
3097 valuetype_types [1] = mono_defaults.int32_class;
3098 else if (eclass == mono_defaults.int64_class)
3099 valuetype_types [1] = mono_defaults.uint64_class;
3100 else if (eclass == mono_defaults.uint64_class)
3101 valuetype_types [1] = mono_defaults.int64_class;
3102 else if (eclass == mono_defaults.byte_class)
3103 valuetype_types [1] = mono_defaults.sbyte_class;
3104 else if (eclass == mono_defaults.sbyte_class)
3105 valuetype_types [1] = mono_defaults.byte_class;
3106 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3107 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3110 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3111 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3112 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3113 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3114 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3116 /* this won't be needed once bug #325495 is completely fixed
3117 * though we'll need something similar to know which interfaces to allow
3118 * in arrays when they'll be lazyly created
3120 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3121 * MS returns diferrent types based on which instance is called. For example:
3122 * object obj = new byte[10][];
3123 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3124 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3127 * Fixing this should kill quite some code, save some bits and improve compatibility.
3130 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3132 MonoClass *eclass = klass->element_class;
3133 MonoClass* generic_icollection_class;
3134 MonoClass* generic_ienumerable_class;
3135 MonoClass* generic_ienumerator_class;
3136 MonoClass* generic_ireadonlylist_class;
3137 MonoClass* generic_ireadonlycollection_class;
3138 MonoClass *valuetype_types[2] = { NULL, NULL };
3139 MonoClass **interfaces = NULL;
3140 int i, nifaces, interface_count, real_count, original_rank;
3142 gboolean internal_enumerator;
3143 gboolean eclass_is_valuetype;
3145 if (!mono_defaults.generic_ilist_class) {
3149 internal_enumerator = FALSE;
3150 eclass_is_valuetype = FALSE;
3151 original_rank = eclass->rank;
3152 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3153 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3154 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3156 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3158 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3159 original_rank = eclass->rank;
3161 eclass = eclass->element_class;
3162 internal_enumerator = TRUE;
3163 *is_enumerator = TRUE;
3171 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3172 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3174 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3176 generic_icollection_class = mono_class_get_generic_icollection_class ();
3177 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3178 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3179 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3180 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3182 mono_class_init (eclass);
3185 * Arrays in 2.0 need to implement a number of generic interfaces
3186 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3187 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3188 * We collect the types needed to build the
3189 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3190 * the generic interfaces needed to implement.
3192 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3193 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3195 if (eclass->valuetype) {
3196 nifaces = generic_ireadonlylist_class ? 5 : 3;
3197 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3199 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3200 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3201 if (internal_enumerator) {
3203 if (valuetype_types [1])
3207 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3208 interfaces [0] = valuetype_types [0];
3209 if (valuetype_types [1])
3210 interfaces [nifaces] = valuetype_types [1];
3212 eclass_is_valuetype = TRUE;
3215 int idepth = eclass->idepth;
3216 if (!internal_enumerator)
3218 nifaces = generic_ireadonlylist_class ? 2 : 3;
3220 // FIXME: This doesn't seem to work/required for generic params
3221 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3222 mono_class_setup_interface_offsets (eclass);
3224 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3225 /* we add object for interfaces and the supertypes for the other
3226 * types. The last of the supertypes is the element class itself which we
3227 * already created the explicit interfaces for (so we include it for IEnumerator
3228 * and exclude it for arrays).
3230 if (MONO_CLASS_IS_INTERFACE (eclass))
3233 interface_count += idepth;
3234 if (eclass->rank && eclass->element_class->valuetype) {
3235 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3236 if (valuetype_types [1])
3239 /* IList, ICollection, IEnumerable, IReadOnlyList */
3240 interface_count *= nifaces;
3241 real_count = interface_count;
3242 if (internal_enumerator) {
3243 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3244 if (valuetype_types [1])
3247 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3248 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3249 interfaces [0] = mono_defaults.object_class;
3253 for (i = 0; i < idepth; i++) {
3254 mono_class_init (eclass->supertypes [i]);
3255 interfaces [j] = eclass->supertypes [i];
3259 if (all_interfaces) {
3260 for (i = 0; i < eclass->interface_offsets_count; i++) {
3261 interfaces [j] = eclass->interfaces_packed [i];
3265 for (i = 0; i < eclass->interface_count; i++) {
3266 interfaces [j] = eclass->interfaces [i];
3270 if (valuetype_types [1]) {
3271 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3276 /* instantiate the generic interfaces */
3277 for (i = 0; i < interface_count; i += nifaces) {
3278 MonoClass *iface = interfaces [i];
3280 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3281 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3283 if (eclass->valuetype) {
3284 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3285 if (generic_ireadonlylist_class) {
3286 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3287 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3290 if (!generic_ireadonlylist_class)
3291 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3294 if (internal_enumerator) {
3296 /* instantiate IEnumerator<iface> */
3297 for (i = 0; i < interface_count; i++) {
3298 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3300 j = interface_count;
3301 if (!eclass_is_valuetype) {
3302 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3303 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3306 for (i = 0; i < eclass->idepth; i++) {
3307 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3311 for (i = 0; i < eclass->interface_offsets_count; i++) {
3312 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3316 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3318 if (valuetype_types [1])
3319 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3323 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3324 for (i = 0; i < real_count; ++i) {
3325 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3326 g_print ("%s implements %s\n", type_name, name);
3337 find_array_interface (MonoClass *klass, const char *name)
3340 for (i = 0; i < klass->interface_count; ++i) {
3341 if (strcmp (klass->interfaces [i]->name, name) == 0)
3348 * Return the number of virtual methods.
3349 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3350 * Return -1 on failure.
3351 * FIXME It would be nice if this information could be cached somewhere.
3354 count_virtual_methods (MonoClass *klass)
3356 int i, mcount, vcount = 0;
3358 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3360 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3361 mono_class_setup_methods (klass);
3362 if (mono_class_has_failure (klass))
3365 mcount = mono_class_get_method_count (klass);
3366 for (i = 0; i < mcount; ++i) {
3367 flags = klass->methods [i]->flags;
3368 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3372 int first_idx = mono_class_get_first_method_idx (klass);
3373 mcount = mono_class_get_method_count (klass);
3374 for (i = 0; i < mcount; ++i) {
3375 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3377 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3385 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3393 m = (l + num_ifaces) / 2;
3394 if (interfaces_full [m] == ic)
3396 if (l == num_ifaces)
3398 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3407 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3409 int i = find_interface (num_ifaces, interfaces_full, ic);
3411 return interface_offsets_full [i];
3416 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3418 int i = find_interface (num_ifaces, interfaces_full, ic);
3422 interface_offsets_full [i] = offset;
3425 for (i = 0; i < num_ifaces; ++i) {
3426 if (interfaces_full [i]) {
3428 if (interfaces_full [i]->interface_id < ic->interface_id)
3431 while (end < num_ifaces && interfaces_full [end]) end++;
3432 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3433 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3435 interfaces_full [i] = ic;
3436 interface_offsets_full [i] = offset;
3442 #ifdef COMPRESSED_INTERFACE_BITMAP
3445 * Compressed interface bitmap design.
3447 * Interface bitmaps take a large amount of memory, because their size is
3448 * linear with the maximum interface id assigned in the process (each interface
3449 * is assigned a unique id as it is loaded). The number of interface classes
3450 * is high because of the many implicit interfaces implemented by arrays (we'll
3451 * need to lazy-load them in the future).
3452 * Most classes implement a very small number of interfaces, so the bitmap is
3453 * sparse. This bitmap needs to be checked by interface casts, so access to the
3454 * needed bit must be fast and doable with few jit instructions.
3456 * The current compression format is as follows:
3457 * *) it is a sequence of one or more two-byte elements
3458 * *) the first byte in the element is the count of empty bitmap bytes
3459 * at the current bitmap position
3460 * *) the second byte in the element is an actual bitmap byte at the current
3463 * As an example, the following compressed bitmap bytes:
3464 * 0x07 0x01 0x00 0x7
3465 * correspond to the following bitmap:
3466 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3468 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3469 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3470 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3474 * mono_compress_bitmap:
3475 * @dest: destination buffer
3476 * @bitmap: bitmap buffer
3477 * @size: size of @bitmap in bytes
3479 * This is a mono internal function.
3480 * The @bitmap data is compressed into a format that is small but
3481 * still searchable in few instructions by the JIT and runtime.
3482 * The compressed data is stored in the buffer pointed to by the
3483 * @dest array. Passing a #NULL value for @dest allows to just compute
3484 * the size of the buffer.
3485 * This compression algorithm assumes the bits set in the bitmap are
3486 * few and far between, like in interface bitmaps.
3487 * Returns: The size of the compressed bitmap in bytes.
3490 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3494 const uint8_t *end = bitmap + size;
3495 while (bitmap < end) {
3496 if (*bitmap || numz == 255) {
3520 * mono_class_interface_match:
3521 * @bitmap: a compressed bitmap buffer
3522 * @id: the index to check in the bitmap
3524 * This is a mono internal function.
3525 * Checks if a bit is set in a compressed interface bitmap. @id must
3526 * be already checked for being smaller than the maximum id encoded in the
3529 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3533 mono_class_interface_match (const uint8_t *bitmap, int id)
3536 id -= bitmap [0] * 8;
3540 return bitmap [1] & (1 << id);
3549 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3550 * LOCKING: Acquires the loader lock.
3553 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3557 int i, j, num_ifaces;
3559 MonoClass **interfaces_full = NULL;
3560 int *interface_offsets_full = NULL;
3562 GPtrArray **ifaces_array = NULL;
3563 int interface_offsets_count;
3564 MonoClass **array_interfaces = NULL;
3565 int num_array_interfaces;
3566 int is_enumerator = FALSE;
3568 mono_loader_lock ();
3570 mono_class_setup_supertypes (klass);
3572 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3573 * implicit interfaces have the property that they are assigned the same slot in the
3574 * vtables for compatible interfaces
3576 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3578 /* compute maximum number of slots and maximum interface id */
3580 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3581 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3582 for (j = 0; j < klass->idepth; j++) {
3583 k = klass->supertypes [j];
3585 num_ifaces += k->interface_count;
3586 for (i = 0; i < k->interface_count; i++) {
3587 ic = k->interfaces [i];
3589 mono_class_init (ic);
3591 if (max_iid < ic->interface_id)
3592 max_iid = ic->interface_id;
3594 ifaces = mono_class_get_implemented_interfaces (k, &error);
3595 if (!mono_error_ok (&error)) {
3596 char *name = mono_type_get_full_name (k);
3597 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3599 mono_error_cleanup (&error);
3604 num_ifaces += ifaces->len;
3605 for (i = 0; i < ifaces->len; ++i) {
3606 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3607 if (max_iid < ic->interface_id)
3608 max_iid = ic->interface_id;
3610 ifaces_array [j] = ifaces;
3614 for (i = 0; i < num_array_interfaces; ++i) {
3615 ic = array_interfaces [i];
3616 mono_class_init (ic);
3617 if (max_iid < ic->interface_id)
3618 max_iid = ic->interface_id;
3621 if (MONO_CLASS_IS_INTERFACE (klass)) {
3623 if (max_iid < klass->interface_id)
3624 max_iid = klass->interface_id;
3627 /* compute vtable offset for interfaces */
3628 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3629 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3631 for (i = 0; i < num_ifaces; i++)
3632 interface_offsets_full [i] = -1;
3634 /* skip the current class */
3635 for (j = 0; j < klass->idepth - 1; j++) {
3636 k = klass->supertypes [j];
3637 ifaces = ifaces_array [j];
3640 for (i = 0; i < ifaces->len; ++i) {
3642 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3644 /*Force the sharing of interface offsets between parent and subtypes.*/
3645 io = mono_class_interface_offset (k, ic);
3647 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3652 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3653 ifaces = ifaces_array [klass->idepth - 1];
3655 for (i = 0; i < ifaces->len; ++i) {
3657 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3658 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3660 count = count_virtual_methods (ic);
3662 char *name = mono_type_get_full_name (ic);
3663 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3672 if (MONO_CLASS_IS_INTERFACE (klass))
3673 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3675 if (num_array_interfaces) {
3676 if (is_enumerator) {
3677 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3678 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3679 g_assert (ienumerator_offset >= 0);
3680 for (i = 0; i < num_array_interfaces; ++i) {
3681 ic = array_interfaces [i];
3682 if (strcmp (ic->name, "IEnumerator`1") == 0)
3683 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3685 g_assert_not_reached ();
3686 /*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);*/
3689 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3690 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3691 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3692 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3693 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3694 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3695 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3696 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3697 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3698 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3699 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3700 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3701 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3702 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3703 for (i = 0; i < num_array_interfaces; ++i) {
3705 ic = array_interfaces [i];
3706 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3707 offset = ilist_offset;
3708 else if (strcmp (ic->name, "ICollection`1") == 0)
3709 offset = icollection_offset;
3710 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3711 offset = ienumerable_offset;
3712 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3713 offset = ireadonlylist_offset;
3714 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3715 offset = ireadonlycollection_offset;
3717 g_assert_not_reached ();
3718 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3719 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3724 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3725 if (interface_offsets_full [i] != -1)
3726 interface_offsets_count ++;
3729 /* Publish the data */
3730 klass->max_interface_id = max_iid;
3732 * We might get called multiple times:
3733 * - mono_class_init ()
3734 * - mono_class_setup_vtable ().
3735 * - mono_class_setup_interface_offsets ().
3736 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3737 * means we have to overwrite those when called from other places (#4440).
3739 if (klass->interfaces_packed) {
3741 g_assert (klass->interface_offsets_count == interface_offsets_count);
3745 klass->interface_offsets_count = interface_offsets_count;
3746 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3747 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3748 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3749 #ifdef COMPRESSED_INTERFACE_BITMAP
3750 bitmap = g_malloc0 (bsize);
3752 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3754 for (i = 0; i < interface_offsets_count; i++) {
3755 guint32 id = interfaces_full [i]->interface_id;
3756 bitmap [id >> 3] |= (1 << (id & 7));
3757 klass->interfaces_packed [i] = interfaces_full [i];
3758 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3759 /*if (num_array_interfaces)
3760 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]);*/
3762 #ifdef COMPRESSED_INTERFACE_BITMAP
3763 i = mono_compress_bitmap (NULL, bitmap, bsize);
3764 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3765 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3768 klass->interface_bitmap = bitmap;
3772 mono_loader_unlock ();
3774 g_free (interfaces_full);
3775 g_free (interface_offsets_full);
3776 g_free (array_interfaces);
3777 for (i = 0; i < klass->idepth; i++) {
3778 ifaces = ifaces_array [i];
3780 g_ptr_array_free (ifaces, TRUE);
3782 g_free (ifaces_array);
3784 //printf ("JUST DONE: ");
3785 //print_implemented_interfaces (klass);
3791 * Setup interface offsets for interfaces.
3793 * - klass->max_interface_id
3794 * - klass->interface_offsets_count
3795 * - klass->interfaces_packed
3796 * - klass->interface_offsets_packed
3797 * - klass->interface_bitmap
3799 * This function can fail @class.
3802 mono_class_setup_interface_offsets (MonoClass *klass)
3804 setup_interface_offsets (klass, 0, FALSE);
3807 /*Checks if @klass has @parent as one of it's parents type gtd
3811 * Bar<T> : Foo<Bar<Bar<T>>>
3815 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3817 klass = mono_class_get_generic_type_definition (klass);
3818 parent = mono_class_get_generic_type_definition (parent);
3819 mono_class_setup_supertypes (klass);
3820 mono_class_setup_supertypes (parent);
3822 return klass->idepth >= parent->idepth &&
3823 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3827 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3829 MonoGenericInst *ginst;
3832 if (!mono_class_is_ginst (klass)) {
3833 mono_class_setup_vtable_full (klass, in_setup);
3834 return !mono_class_has_failure (klass);
3837 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3838 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3841 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3842 for (i = 0; i < ginst->type_argc; ++i) {
3844 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3846 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3847 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3848 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3850 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3851 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3859 * mono_class_setup_vtable:
3861 * Creates the generic vtable of CLASS.
3862 * Initializes the following fields in MonoClass:
3865 * Plus all the fields initialized by setup_interface_offsets ().
3866 * If there is an error during vtable construction, klass->has_failure
3867 * is set and details are stored in a MonoErrorBoxed.
3869 * LOCKING: Acquires the loader lock.
3872 mono_class_setup_vtable (MonoClass *klass)
3874 mono_class_setup_vtable_full (klass, NULL);
3878 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3881 MonoMethod **overrides;
3882 MonoGenericContext *context;
3890 if (MONO_CLASS_IS_INTERFACE (klass)) {
3891 /* This sets method->slot for all methods if this is an interface */
3892 mono_class_setup_methods (klass);
3896 if (mono_class_has_failure (klass))
3899 if (g_list_find (in_setup, klass))
3902 mono_loader_lock ();
3904 if (klass->vtable) {
3905 mono_loader_unlock ();
3909 mono_stats.generic_vtable_count ++;
3910 in_setup = g_list_prepend (in_setup, klass);
3912 if (mono_class_is_ginst (klass)) {
3913 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3914 mono_loader_unlock ();
3915 g_list_remove (in_setup, klass);
3919 context = mono_class_get_context (klass);
3920 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3922 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3923 type_token = klass->type_token;
3926 if (image_is_dynamic (klass->image)) {
3927 /* Generic instances can have zero method overrides without causing any harm.
3928 * This is true since we don't do layout all over again for them, we simply inflate
3929 * the layout of the parent.
3931 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3932 if (!is_ok (&error)) {
3933 mono_loader_unlock ();
3934 g_list_remove (in_setup, klass);
3935 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3936 mono_error_cleanup (&error);
3940 /* The following call fails if there are missing methods in the type */
3941 /* FIXME it's probably a good idea to avoid this for generic instances. */
3942 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3946 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3948 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3952 mono_loader_unlock ();
3953 g_list_remove (in_setup, klass);
3958 #define DEBUG_INTERFACE_VTABLE_CODE 0
3959 #define TRACE_INTERFACE_VTABLE_CODE 0
3960 #define VERIFY_INTERFACE_VTABLE_CODE 0
3961 #define VTABLE_SELECTOR (1)
3963 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3964 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3965 if (!(VTABLE_SELECTOR)) break; \
3969 #define DEBUG_INTERFACE_VTABLE(stmt)
3972 #if TRACE_INTERFACE_VTABLE_CODE
3973 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3974 if (!(VTABLE_SELECTOR)) break; \
3978 #define TRACE_INTERFACE_VTABLE(stmt)
3981 #if VERIFY_INTERFACE_VTABLE_CODE
3982 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3983 if (!(VTABLE_SELECTOR)) break; \
3987 #define VERIFY_INTERFACE_VTABLE(stmt)
3991 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3993 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3997 GString *res = g_string_new ("");
3999 g_string_append_c (res, '(');
4000 for (i = 0; i < sig->param_count; ++i) {
4002 g_string_append_c (res, ',');
4003 mono_type_get_desc (res, sig->params [i], include_namespace);
4005 g_string_append (res, ")=>");
4006 if (sig->ret != NULL) {
4007 mono_type_get_desc (res, sig->ret, include_namespace);
4009 g_string_append (res, "NULL");
4012 g_string_free (res, FALSE);
4016 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
4017 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
4018 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
4019 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4027 is_wcf_hack_disabled (void)
4029 static gboolean disabled;
4030 static gboolean inited = FALSE;
4032 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4039 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4041 MonoMethodSignature *cmsig, *imsig;
4042 if (strcmp (im->name, cm->name) == 0) {
4043 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4044 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4047 if (! slot_is_empty) {
4048 if (require_newslot) {
4049 if (! interface_is_explicitly_implemented_by_class) {
4050 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4053 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4054 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4058 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4061 cmsig = mono_method_signature (cm);
4062 imsig = mono_method_signature (im);
4063 if (!cmsig || !imsig) {
4064 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4068 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4069 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4070 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4071 TRACE_INTERFACE_VTABLE (printf ("]"));
4074 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4075 if (mono_security_core_clr_enabled ())
4076 mono_security_core_clr_check_override (klass, cm, im);
4078 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4079 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4080 char *body_name = mono_method_full_name (cm, TRUE);
4081 char *decl_name = mono_method_full_name (im, TRUE);
4082 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4090 MonoClass *ic = im->klass;
4091 const char *ic_name_space = ic->name_space;
4092 const char *ic_name = ic->name;
4095 if (! require_newslot) {
4096 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4099 if (cm->klass->rank == 0) {
4100 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4103 cmsig = mono_method_signature (cm);
4104 imsig = mono_method_signature (im);
4105 if (!cmsig || !imsig) {
4106 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4110 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4111 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4112 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4113 TRACE_INTERFACE_VTABLE (printf ("]"));
4116 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4117 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4120 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4121 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4124 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))) {
4125 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4129 subname = strstr (cm->name, ic_name_space);
4130 if (subname != cm->name) {
4131 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4134 subname += strlen (ic_name_space);
4135 if (subname [0] != '.') {
4136 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4140 if (strstr (subname, ic_name) != subname) {
4141 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4144 subname += strlen (ic_name);
4145 if (subname [0] != '.') {
4146 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4150 if (strcmp (subname, im->name) != 0) {
4151 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4155 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4156 if (mono_security_core_clr_enabled ())
4157 mono_security_core_clr_check_override (klass, cm, im);
4159 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4160 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4161 char *body_name = mono_method_full_name (cm, TRUE);
4162 char *decl_name = mono_method_full_name (im, TRUE);
4163 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4173 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4175 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4176 MonoMethod *method = key;
4177 MonoMethod *override = value;
4178 MonoClass *method_class = mono_method_get_class (method);
4179 MonoClass *override_class = mono_method_get_class (override);
4181 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4182 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4183 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4186 print_overrides (GHashTable *override_map, const char *message) {
4188 printf ("Override map \"%s\" START:\n", message);
4189 g_hash_table_foreach (override_map, foreach_override, NULL);
4190 printf ("Override map \"%s\" END.\n", message);
4192 printf ("Override map \"%s\" EMPTY.\n", message);
4196 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4197 char *full_name = mono_type_full_name (&klass->byval_arg);
4201 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4203 if (print_interfaces) {
4204 print_implemented_interfaces (klass);
4205 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4208 if (klass->parent) {
4209 parent_size = klass->parent->vtable_size;
4213 for (i = 0; i < size; ++i) {
4214 MonoMethod *cm = vtable [i];
4215 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4216 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4218 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4226 #if VERIFY_INTERFACE_VTABLE_CODE
4228 mono_method_try_get_vtable_index (MonoMethod *method)
4230 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4231 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4232 if (imethod->declaring->is_generic)
4233 return imethod->declaring->slot;
4235 return method->slot;
4239 mono_class_verify_vtable (MonoClass *klass)
4242 char *full_name = mono_type_full_name (&klass->byval_arg);
4244 printf ("*** Verifying VTable of class '%s' \n", full_name);
4248 if (!klass->methods)
4251 count = mono_class_method_count (klass);
4252 for (i = 0; i < count; ++i) {
4253 MonoMethod *cm = klass->methods [i];
4256 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4260 full_name = mono_method_full_name (cm, TRUE);
4262 slot = mono_method_try_get_vtable_index (cm);
4264 if (slot >= klass->vtable_size) {
4265 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4269 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4270 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4271 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4272 g_free (other_name);
4275 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4282 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
4285 char *method_signature;
4288 for (index = 0; index < onum; ++index) {
4289 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4290 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4292 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4293 type_name = mono_type_full_name (&klass->byval_arg);
4294 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4295 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4296 g_free (method_signature);
4298 mono_class_setup_methods (klass);
4299 if (mono_class_has_failure (klass)) {
4300 char *name = mono_type_get_full_name (klass);
4301 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4305 mcount = mono_class_get_method_count (klass);
4306 for (index = 0; index < mcount; ++index) {
4307 MonoMethod *cm = klass->methods [index];
4308 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4310 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4311 g_free (method_signature);
4316 mono_method_get_method_definition (MonoMethod *method)
4318 while (method->is_inflated)
4319 method = ((MonoMethodInflated*)method)->declaring;
4324 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4328 for (i = 0; i < onum; ++i) {
4329 MonoMethod *decl = overrides [i * 2];
4330 MonoMethod *body = overrides [i * 2 + 1];
4332 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4333 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4337 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4338 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4339 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4341 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4345 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4346 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4347 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4349 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4353 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4354 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4358 body = mono_method_get_method_definition (body);
4359 decl = mono_method_get_method_definition (decl);
4361 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4362 char *body_name = mono_method_full_name (body, TRUE);
4363 char *decl_name = mono_method_full_name (decl, TRUE);
4364 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4374 mono_class_need_stelemref_method (MonoClass *klass)
4376 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4380 * LOCKING: this is supposed to be called with the loader lock held.
4383 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4387 MonoMethod **vtable;
4388 int i, max_vtsize = 0, cur_slot = 0;
4390 GPtrArray *ifaces = NULL;
4391 GHashTable *override_map = NULL;
4393 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4394 int first_non_interface_slot;
4396 GSList *virt_methods = NULL, *l;
4397 int stelemref_slot = 0;
4402 if (overrides && !verify_class_overrides (klass, overrides, onum))
4405 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4406 if (!mono_error_ok (&error)) {
4407 char *name = mono_type_get_full_name (klass);
4408 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4410 mono_error_cleanup (&error);
4412 } else if (ifaces) {
4413 for (i = 0; i < ifaces->len; i++) {
4414 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4415 max_vtsize += mono_class_get_method_count (ic);
4417 g_ptr_array_free (ifaces, TRUE);
4421 if (klass->parent) {
4422 mono_class_init (klass->parent);
4423 mono_class_setup_vtable_full (klass->parent, in_setup);
4425 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4428 max_vtsize += klass->parent->vtable_size;
4429 cur_slot = klass->parent->vtable_size;
4432 max_vtsize += mono_class_get_method_count (klass);
4434 /*Array have a slot for stelemref*/
4435 if (mono_class_need_stelemref_method (klass)) {
4436 stelemref_slot = cur_slot;
4441 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4442 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4444 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4446 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4447 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4450 max_iid = klass->max_interface_id;
4451 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4453 /* Optimized version for generic instances */
4454 if (mono_class_is_ginst (klass)) {
4456 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4459 mono_class_setup_vtable_full (gklass, in_setup);
4460 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4463 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4464 klass->vtable_size = gklass->vtable_size;
4465 for (i = 0; i < gklass->vtable_size; ++i)
4466 if (gklass->vtable [i]) {
4467 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4468 if (!mono_error_ok (&error)) {
4469 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4470 mono_error_cleanup (&error);
4474 tmp [i]->slot = gklass->vtable [i]->slot;
4476 mono_memory_barrier ();
4477 klass->vtable = tmp;
4479 /* Have to set method->slot for abstract virtual methods */
4480 if (klass->methods && gklass->methods) {
4481 int mcount = mono_class_get_method_count (klass);
4482 for (i = 0; i < mcount; ++i)
4483 if (klass->methods [i]->slot == -1)
4484 klass->methods [i]->slot = gklass->methods [i]->slot;
4490 if (klass->parent && klass->parent->vtable_size) {
4491 MonoClass *parent = klass->parent;
4494 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4496 // Also inherit parent interface vtables, just as a starting point.
4497 // This is needed otherwise bug-77127.exe fails when the property methods
4498 // have different names in the iterface and the class, because for child
4499 // classes the ".override" information is not used anymore.
4500 for (i = 0; i < parent->interface_offsets_count; i++) {
4501 MonoClass *parent_interface = parent->interfaces_packed [i];
4502 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4503 /*FIXME this is now dead code as this condition will never hold true.
4504 Since interface offsets are inherited then the offset of an interface implemented
4505 by a parent will never be the out of it's vtable boundary.
4507 if (interface_offset >= parent->vtable_size) {
4508 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4511 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4512 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4513 int mcount = mono_class_get_method_count (parent_interface);
4514 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4515 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4516 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4517 parent_interface_offset + j, parent_interface_offset, j,
4518 interface_offset + j, interface_offset, j));
4525 /*Array have a slot for stelemref*/
4526 if (mono_class_need_stelemref_method (klass)) {
4527 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4529 method->slot = stelemref_slot;
4531 g_assert (method->slot == stelemref_slot);
4533 vtable [stelemref_slot] = method;
4536 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4537 /* override interface methods */
4538 for (i = 0; i < onum; i++) {
4539 MonoMethod *decl = overrides [i*2];
4540 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4542 dslot = mono_method_get_vtable_slot (decl);
4544 mono_class_set_type_load_failure (klass, "");
4548 dslot += mono_class_interface_offset (klass, decl->klass);
4549 vtable [dslot] = overrides [i*2 + 1];
4550 vtable [dslot]->slot = dslot;
4552 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4554 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4556 if (mono_security_core_clr_enabled ())
4557 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4560 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4561 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4564 * Create a list of virtual methods to avoid calling
4565 * mono_class_get_virtual_methods () which is slow because of the metadata
4569 gpointer iter = NULL;
4572 virt_methods = NULL;
4573 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4574 virt_methods = g_slist_prepend (virt_methods, cm);
4576 if (mono_class_has_failure (klass))
4580 // Loop on all implemented interfaces...
4581 for (i = 0; i < klass->interface_offsets_count; i++) {
4582 MonoClass *parent = klass->parent;
4584 gboolean interface_is_explicitly_implemented_by_class;
4587 ic = klass->interfaces_packed [i];
4588 ic_offset = mono_class_interface_offset (klass, ic);
4590 mono_class_setup_methods (ic);
4591 if (mono_class_has_failure (ic))
4594 // Check if this interface is explicitly implemented (instead of just inherited)
4595 if (parent != NULL) {
4596 int implemented_interfaces_index;
4597 interface_is_explicitly_implemented_by_class = FALSE;
4598 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4599 if (ic == klass->interfaces [implemented_interfaces_index]) {
4600 interface_is_explicitly_implemented_by_class = TRUE;
4605 interface_is_explicitly_implemented_by_class = TRUE;
4608 // Loop on all interface methods...
4609 int mcount = mono_class_get_method_count (ic);
4610 for (im_index = 0; im_index < mcount; im_index++) {
4611 MonoMethod *im = ic->methods [im_index];
4612 int im_slot = ic_offset + im->slot;
4613 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4615 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4618 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4620 // If there is an explicit implementation, just use it right away,
4621 // otherwise look for a matching method
4622 if (override_im == NULL) {
4626 // First look for a suitable method among the class methods
4627 for (l = virt_methods; l; l = l->next) {
4628 cm = (MonoMethod *)l->data;
4629 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)));
4630 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4631 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4632 vtable [im_slot] = cm;
4633 /* Why do we need this? */
4638 TRACE_INTERFACE_VTABLE (printf ("\n"));
4639 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4643 // If the slot is still empty, look in all the inherited virtual methods...
4644 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4645 MonoClass *parent = klass->parent;
4646 // Reverse order, so that last added methods are preferred
4647 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4648 MonoMethod *cm = parent->vtable [cm_index];
4650 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));
4651 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4652 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4653 vtable [im_slot] = cm;
4654 /* Why do we need this? */
4660 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4662 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4666 g_assert (vtable [im_slot] == override_im);
4671 // If the class is not abstract, check that all its interface slots are full.
4672 // The check is done here and not directly at the end of the loop above because
4673 // it can happen (for injected generic array interfaces) that the same slot is
4674 // processed multiple times (those interfaces have overlapping slots), and it
4675 // will not always be the first pass the one that fills the slot.
4676 if (!mono_class_is_abstract (klass)) {
4677 for (i = 0; i < klass->interface_offsets_count; i++) {
4681 ic = klass->interfaces_packed [i];
4682 ic_offset = mono_class_interface_offset (klass, ic);
4684 int mcount = mono_class_get_method_count (ic);
4685 for (im_index = 0; im_index < mcount; im_index++) {
4686 MonoMethod *im = ic->methods [im_index];
4687 int im_slot = ic_offset + im->slot;
4689 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4692 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4693 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4694 if (vtable [im_slot] == NULL) {
4695 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4702 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4703 for (l = virt_methods; l; l = l->next) {
4704 cm = (MonoMethod *)l->data;
4706 * If the method is REUSE_SLOT, we must check in the
4707 * base class for a method to override.
4709 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4711 for (k = klass->parent; k ; k = k->parent) {
4716 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4717 MonoMethodSignature *cmsig, *m1sig;
4719 cmsig = mono_method_signature (cm);
4720 m1sig = mono_method_signature (m1);
4722 if (!cmsig || !m1sig) {
4723 /* FIXME proper error message */
4724 mono_class_set_type_load_failure (klass, "");
4728 if (!strcmp(cm->name, m1->name) &&
4729 mono_metadata_signature_equal (cmsig, m1sig)) {
4731 if (mono_security_core_clr_enabled ())
4732 mono_security_core_clr_check_override (klass, cm, m1);
4734 slot = mono_method_get_vtable_slot (m1);
4738 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4739 char *body_name = mono_method_full_name (cm, TRUE);
4740 char *decl_name = mono_method_full_name (m1, TRUE);
4741 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4747 g_assert (cm->slot < max_vtsize);
4749 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4750 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4751 mono_method_full_name (m1, 1), m1,
4752 mono_method_full_name (cm, 1), cm));
4753 g_hash_table_insert (override_map, m1, cm);
4757 if (mono_class_has_failure (k))
4767 /*Non final newslot methods must be given a non-interface vtable slot*/
4768 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4772 cm->slot = cur_slot++;
4774 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4775 vtable [cm->slot] = cm;
4778 /* override non interface methods */
4779 for (i = 0; i < onum; i++) {
4780 MonoMethod *decl = overrides [i*2];
4781 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4782 g_assert (decl->slot != -1);
4783 vtable [decl->slot] = overrides [i*2 + 1];
4784 overrides [i * 2 + 1]->slot = decl->slot;
4786 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4787 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4788 mono_method_full_name (decl, 1), decl,
4789 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4790 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4792 if (mono_security_core_clr_enabled ())
4793 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4798 * If a method occupies more than one place in the vtable, and it is
4799 * overriden, then change the other occurances too.
4804 for (i = 0; i < max_vtsize; ++i)
4806 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4808 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4813 g_hash_table_destroy (override_map);
4814 override_map = NULL;
4817 g_slist_free (virt_methods);
4818 virt_methods = NULL;
4820 /* Ensure that all vtable slots are filled with concrete instance methods */
4821 if (!mono_class_is_abstract (klass)) {
4822 for (i = 0; i < cur_slot; ++i) {
4823 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4824 char *type_name = mono_type_get_full_name (klass);
4825 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4826 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4828 g_free (method_name);
4834 if (mono_class_is_ginst (klass)) {
4835 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4837 mono_class_init (gklass);
4839 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4841 /* Check that the vtable_size value computed in mono_class_init () is correct */
4842 if (klass->vtable_size)
4843 g_assert (cur_slot == klass->vtable_size);
4844 klass->vtable_size = cur_slot;
4847 /* Try to share the vtable with our parent. */
4848 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4849 mono_memory_barrier ();
4850 klass->vtable = klass->parent->vtable;
4852 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4853 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4854 mono_memory_barrier ();
4855 klass->vtable = tmp;
4858 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4859 if (mono_print_vtable) {
4862 print_implemented_interfaces (klass);
4864 for (i = 0; i <= max_iid; i++)
4865 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4868 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4869 klass->vtable_size, icount);
4871 for (i = 0; i < cur_slot; ++i) {
4876 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4877 mono_method_full_name (cm, TRUE));
4883 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4884 klass->name, max_iid);
4886 for (i = 0; i < klass->interface_count; i++) {
4887 ic = klass->interfaces [i];
4888 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4889 mono_class_interface_offset (klass, ic),
4890 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4893 for (k = klass->parent; k ; k = k->parent) {
4894 for (i = 0; i < k->interface_count; i++) {
4895 ic = k->interfaces [i];
4896 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4897 mono_class_interface_offset (klass, ic),
4898 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4904 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4909 char *name = mono_type_get_full_name (klass);
4910 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4913 g_hash_table_destroy (override_map);
4915 g_slist_free (virt_methods);
4920 * mono_method_get_vtable_slot:
4922 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4923 * LOCKING: Acquires the loader lock.
4925 * FIXME Use proper MonoError machinery here.
4928 mono_method_get_vtable_slot (MonoMethod *method)
4930 if (method->slot == -1) {
4931 mono_class_setup_vtable (method->klass);
4932 if (mono_class_has_failure (method->klass))
4934 if (method->slot == -1) {
4938 if (!mono_class_is_ginst (method->klass)) {
4939 g_assert (method->is_inflated);
4940 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4943 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4944 g_assert (mono_class_is_ginst (method->klass));
4945 gklass = mono_class_get_generic_class (method->klass)->container_class;
4946 mono_class_setup_methods (method->klass);
4947 g_assert (method->klass->methods);
4948 mcount = mono_class_get_method_count (method->klass);
4949 for (i = 0; i < mcount; ++i) {
4950 if (method->klass->methods [i] == method)
4953 g_assert (i < mcount);
4954 g_assert (gklass->methods);
4955 method->slot = gklass->methods [i]->slot;
4957 g_assert (method->slot != -1);
4959 return method->slot;
4963 * mono_method_get_vtable_index:
4966 * Returns the index into the runtime vtable to access the method or,
4967 * in the case of a virtual generic method, the virtual generic method
4968 * thunk. Returns -1 on failure.
4970 * FIXME Use proper MonoError machinery here.
4973 mono_method_get_vtable_index (MonoMethod *method)
4975 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4976 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4977 if (imethod->declaring->is_generic)
4978 return mono_method_get_vtable_slot (imethod->declaring);
4980 return mono_method_get_vtable_slot (method);
4983 static MonoMethod *default_ghc = NULL;
4984 static MonoMethod *default_finalize = NULL;
4985 static int finalize_slot = -1;
4986 static int ghc_slot = -1;
4989 initialize_object_slots (MonoClass *klass)
4994 if (klass == mono_defaults.object_class) {
4995 mono_class_setup_vtable (klass);
4996 for (i = 0; i < klass->vtable_size; ++i) {
4997 MonoMethod *cm = klass->vtable [i];
4999 if (!strcmp (cm->name, "GetHashCode"))
5001 else if (!strcmp (cm->name, "Finalize"))
5005 g_assert (ghc_slot > 0);
5006 default_ghc = klass->vtable [ghc_slot];
5008 g_assert (finalize_slot > 0);
5009 default_finalize = klass->vtable [finalize_slot];
5014 MonoMethod *array_method;
5016 } GenericArrayMethodInfo;
5018 static int generic_array_method_num = 0;
5019 static GenericArrayMethodInfo *generic_array_method_info = NULL;
5022 generic_array_methods (MonoClass *klass)
5024 int i, count_generic = 0, mcount;
5025 GList *list = NULL, *tmp;
5026 if (generic_array_method_num)
5027 return generic_array_method_num;
5028 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
5029 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
5030 mcount = mono_class_get_method_count (klass->parent);
5031 for (i = 0; i < mcount; i++) {
5032 MonoMethod *m = klass->parent->methods [i];
5033 if (!strncmp (m->name, "InternalArray__", 15)) {
5035 list = g_list_prepend (list, m);
5038 list = g_list_reverse (list);
5039 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5041 for (tmp = list; tmp; tmp = tmp->next) {
5042 const char *mname, *iname;
5044 MonoMethod *m = (MonoMethod *)tmp->data;
5045 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5046 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5048 generic_array_method_info [i].array_method = m;
5049 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5050 iname = "System.Collections.Generic.ICollection`1.";
5051 mname = m->name + 27;
5052 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5053 iname = "System.Collections.Generic.IEnumerable`1.";
5054 mname = m->name + 27;
5055 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5056 iname = "System.Collections.Generic.IReadOnlyList`1.";
5057 mname = m->name + strlen (ireadonlylist_prefix);
5058 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5059 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5060 mname = m->name + strlen (ireadonlycollection_prefix);
5061 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5062 iname = "System.Collections.Generic.IList`1.";
5063 mname = m->name + 15;
5065 g_assert_not_reached ();
5068 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5069 strcpy (name, iname);
5070 strcpy (name + strlen (iname), mname);
5071 generic_array_method_info [i].name = name;
5074 /*g_print ("array generic methods: %d\n", count_generic);*/
5076 generic_array_method_num = count_generic;
5078 return generic_array_method_num;
5082 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5084 MonoGenericContext tmp_context;
5087 tmp_context.class_inst = NULL;
5088 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5089 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5091 for (i = 0; i < generic_array_method_num; i++) {
5093 MonoMethod *m = generic_array_method_info [i].array_method;
5094 MonoMethod *inflated;
5096 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5097 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5098 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5103 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5105 int null_length = strlen ("(null)");
5106 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5107 char *s = (char *)mono_image_alloc (image, len);
5110 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5111 g_assert (result == len - 1);
5118 * @klass: the class to initialize
5120 * Compute the instance_size, class_size and other infos that cannot be
5121 * computed at mono_class_get() time. Also compute vtable_size if possible.
5122 * Returns TRUE on success or FALSE if there was a problem in loading
5123 * the type (incorrect assemblies, missing assemblies, methods, etc).
5124 * Initializes the following fields in @klass:
5125 * - all the fields initialized by mono_class_init_sizes ()
5130 * LOCKING: Acquires the loader lock.
5133 mono_class_init (MonoClass *klass)
5135 int i, vtable_size = 0, array_method_count = 0;
5136 MonoCachedClassInfo cached_info;
5137 gboolean has_cached_info;
5138 gboolean locked = FALSE;
5139 gboolean ghcimpl = FALSE;
5140 gboolean has_cctor = FALSE;
5141 int first_iface_slot = 0;
5145 /* Double-checking locking pattern */
5146 if (klass->inited || mono_class_has_failure (klass))
5147 return !mono_class_has_failure (klass);
5149 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5152 * This function can recursively call itself.
5154 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5155 if (g_slist_find (init_list, klass)) {
5156 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5159 init_list = g_slist_prepend (init_list, klass);
5160 mono_native_tls_set_value (init_pending_tls_id, init_list);
5163 * We want to avoid doing complicated work inside locks, so we compute all the required
5164 * information and write it to @klass inside a lock.
5167 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5168 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5172 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5173 MonoClass *element_class = klass->element_class;
5174 if (!element_class->inited)
5175 mono_class_init (element_class);
5176 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5180 mono_stats.initialized_class_count++;
5182 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5183 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5185 mono_class_init (gklass);
5186 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5189 mono_class_setup_interface_id (klass);
5192 if (klass->parent && !klass->parent->inited)
5193 mono_class_init (klass->parent);
5195 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5197 /* Compute instance size etc. */
5198 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5199 if (mono_class_has_failure (klass))
5202 mono_class_setup_supertypes (klass);
5205 initialize_object_slots (klass);
5208 * Initialize the rest of the data without creating a generic vtable if possible.
5209 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5210 * also avoid computing a generic vtable.
5212 if (has_cached_info) {
5214 vtable_size = cached_info.vtable_size;
5215 ghcimpl = cached_info.ghcimpl;
5216 has_cctor = cached_info.has_cctor;
5217 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5218 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5219 * The first slot if for array with.
5221 static int szarray_vtable_size[2] = { 0 };
5223 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5226 if (!szarray_vtable_size [slot]) {
5227 mono_class_setup_vtable (klass);
5228 szarray_vtable_size [slot] = klass->vtable_size;
5229 vtable_size = klass->vtable_size;
5231 vtable_size = szarray_vtable_size[slot];
5233 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5234 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5236 /* Generic instance case */
5237 ghcimpl = gklass->ghcimpl;
5238 has_cctor = gklass->has_cctor;
5240 mono_class_setup_vtable (gklass);
5241 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5244 vtable_size = gklass->vtable_size;
5248 /* ghcimpl is not currently used
5250 if (klass->parent) {
5251 MonoMethod *cmethod = klass->vtable [ghc_slot];
5252 if (cmethod->is_inflated)
5253 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5254 if (cmethod == default_ghc) {
5260 /* C# doesn't allow interfaces to have cctors */
5261 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5262 MonoMethod *cmethod = NULL;
5264 if (mono_class_is_ginst (klass)) {
5265 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5267 /* Generic instance case */
5268 ghcimpl = gklass->ghcimpl;
5269 has_cctor = gklass->has_cctor;
5270 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5271 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5272 /* The find_method function ignores the 'flags' argument */
5273 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5276 mono_class_setup_methods (klass);
5277 if (mono_class_has_failure (klass))
5280 int mcount = mono_class_get_method_count (klass);
5281 for (i = 0; i < mcount; ++i) {
5282 MonoMethod *method = klass->methods [i];
5283 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5284 (strcmp (".cctor", method->name) == 0)) {
5294 array_method_count = 3 + (klass->rank > 1? 2: 1);
5296 if (klass->interface_count) {
5297 int count_generic = generic_array_methods (klass);
5298 array_method_count += klass->interface_count * count_generic;
5302 if (klass->parent) {
5303 if (!klass->parent->vtable_size)
5304 mono_class_setup_vtable (klass->parent);
5305 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5307 g_assert (klass->parent->vtable_size);
5308 first_iface_slot = klass->parent->vtable_size;
5309 if (mono_class_need_stelemref_method (klass))
5314 * Do the actual changes to @klass inside the loader lock
5316 mono_loader_lock ();
5319 if (klass->inited || mono_class_has_failure (klass)) {
5320 mono_loader_unlock ();
5321 /* Somebody might have gotten in before us */
5322 return !mono_class_has_failure (klass);
5325 mono_stats.initialized_class_count++;
5327 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5328 mono_stats.generic_class_count++;
5330 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5331 klass->nested_classes_inited = TRUE;
5332 klass->ghcimpl = ghcimpl;
5333 klass->has_cctor = has_cctor;
5335 klass->vtable_size = vtable_size;
5336 if (has_cached_info) {
5337 klass->has_finalize = cached_info.has_finalize;
5338 klass->has_finalize_inited = TRUE;
5341 mono_class_set_method_count (klass, array_method_count);
5343 mono_loader_unlock ();
5346 setup_interface_offsets (klass, first_iface_slot, TRUE);
5348 if (mono_security_core_clr_enabled ())
5349 mono_security_core_clr_check_inheritance (klass);
5351 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5352 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5357 init_list = g_slist_remove (init_list, klass);
5358 mono_native_tls_set_value (init_pending_tls_id, init_list);
5360 /* Because of the double-checking locking pattern */
5361 mono_memory_barrier ();
5365 mono_loader_unlock ();
5367 return !mono_class_has_failure (klass);
5371 * mono_class_has_finalizer:
5373 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5377 mono_class_has_finalizer (MonoClass *klass)
5379 gboolean has_finalize = FALSE;
5381 if (klass->has_finalize_inited)
5382 return klass->has_finalize;
5384 /* Interfaces and valuetypes are not supposed to have finalizers */
5385 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5386 MonoMethod *cmethod = NULL;
5388 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5389 } else if (mono_class_is_ginst (klass)) {
5390 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5392 has_finalize = mono_class_has_finalizer (gklass);
5393 } else if (klass->parent && klass->parent->has_finalize) {
5394 has_finalize = TRUE;
5396 if (klass->parent) {
5398 * Can't search in metadata for a method named Finalize, because that
5399 * ignores overrides.
5401 mono_class_setup_vtable (klass);
5402 if (mono_class_has_failure (klass))
5405 cmethod = klass->vtable [finalize_slot];
5409 g_assert (klass->vtable_size > finalize_slot);
5411 if (klass->parent) {
5412 if (cmethod->is_inflated)
5413 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5414 if (cmethod != default_finalize)
5415 has_finalize = TRUE;
5421 mono_image_lock (klass->image);
5423 if (!klass->has_finalize_inited) {
5424 klass->has_finalize = has_finalize ? 1 : 0;
5426 mono_memory_barrier ();
5427 klass->has_finalize_inited = TRUE;
5430 mono_image_unlock (klass->image);
5432 return klass->has_finalize;
5436 mono_is_corlib_image (MonoImage *image)
5438 return image == mono_defaults.corlib;
5442 * LOCKING: this assumes the loader lock is held
5445 mono_class_setup_mono_type (MonoClass *klass)
5447 const char *name = klass->name;
5448 const char *nspace = klass->name_space;
5449 gboolean is_corlib = mono_is_corlib_image (klass->image);
5451 klass->this_arg.byref = 1;
5452 klass->this_arg.data.klass = klass;
5453 klass->this_arg.type = MONO_TYPE_CLASS;
5454 klass->byval_arg.data.klass = klass;
5455 klass->byval_arg.type = MONO_TYPE_CLASS;
5457 if (is_corlib && !strcmp (nspace, "System")) {
5458 if (!strcmp (name, "ValueType")) {
5460 * do not set the valuetype bit for System.ValueType.
5461 * klass->valuetype = 1;
5463 klass->blittable = TRUE;
5464 } else if (!strcmp (name, "Enum")) {
5466 * do not set the valuetype bit for System.Enum.
5467 * klass->valuetype = 1;
5469 klass->valuetype = 0;
5470 klass->enumtype = 0;
5471 } else if (!strcmp (name, "Object")) {
5472 klass->byval_arg.type = MONO_TYPE_OBJECT;
5473 klass->this_arg.type = MONO_TYPE_OBJECT;
5474 } else if (!strcmp (name, "String")) {
5475 klass->byval_arg.type = MONO_TYPE_STRING;
5476 klass->this_arg.type = MONO_TYPE_STRING;
5477 } else if (!strcmp (name, "TypedReference")) {
5478 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5479 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5483 if (klass->valuetype) {
5484 int t = MONO_TYPE_VALUETYPE;
5486 if (is_corlib && !strcmp (nspace, "System")) {
5489 if (!strcmp (name, "Boolean")) {
5490 t = MONO_TYPE_BOOLEAN;
5491 } else if (!strcmp(name, "Byte")) {
5493 klass->blittable = TRUE;
5497 if (!strcmp (name, "Char")) {
5502 if (!strcmp (name, "Double")) {
5504 klass->blittable = TRUE;
5508 if (!strcmp (name, "Int32")) {
5510 klass->blittable = TRUE;
5511 } else if (!strcmp(name, "Int16")) {
5513 klass->blittable = TRUE;
5514 } else if (!strcmp(name, "Int64")) {
5516 klass->blittable = TRUE;
5517 } else if (!strcmp(name, "IntPtr")) {
5519 klass->blittable = TRUE;
5523 if (!strcmp (name, "Single")) {
5525 klass->blittable = TRUE;
5526 } else if (!strcmp(name, "SByte")) {
5528 klass->blittable = TRUE;
5532 if (!strcmp (name, "UInt32")) {
5534 klass->blittable = TRUE;
5535 } else if (!strcmp(name, "UInt16")) {
5537 klass->blittable = TRUE;
5538 } else if (!strcmp(name, "UInt64")) {
5540 klass->blittable = TRUE;
5541 } else if (!strcmp(name, "UIntPtr")) {
5543 klass->blittable = TRUE;
5547 if (!strcmp (name, "TypedReference")) {
5548 t = MONO_TYPE_TYPEDBYREF;
5549 klass->blittable = TRUE;
5553 if (!strcmp (name, "Void")) {
5561 klass->byval_arg.type = (MonoTypeEnum)t;
5562 klass->this_arg.type = (MonoTypeEnum)t;
5565 if (MONO_CLASS_IS_INTERFACE (klass))
5566 klass->interface_id = mono_get_unique_iid (klass);
5571 * COM initialization is delayed until needed.
5572 * However when a [ComImport] attribute is present on a type it will trigger
5573 * the initialization. This is not a problem unless the BCL being executed
5574 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5577 init_com_from_comimport (MonoClass *klass)
5579 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5580 if (mono_security_core_clr_enabled ()) {
5581 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5582 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5583 /* but it can not be made available for application (i.e. user code) since all COM calls
5584 * are considered native calls. In this case we fail with a TypeLoadException (just like
5585 * Silverlight 2 does */
5586 mono_class_set_type_load_failure (klass, "");
5591 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5593 #endif /*DISABLE_COM*/
5596 * LOCKING: this assumes the loader lock is held
5599 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5601 gboolean system_namespace;
5602 gboolean is_corlib = mono_is_corlib_image (klass->image);
5604 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5606 /* if root of the hierarchy */
5607 if (system_namespace && !strcmp (klass->name, "Object")) {
5608 klass->parent = NULL;
5609 klass->instance_size = sizeof (MonoObject);
5612 if (!strcmp (klass->name, "<Module>")) {
5613 klass->parent = NULL;
5614 klass->instance_size = 0;
5618 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5619 /* Imported COM Objects always derive from __ComObject. */
5621 if (MONO_CLASS_IS_IMPORT (klass)) {
5622 init_com_from_comimport (klass);
5623 if (parent == mono_defaults.object_class)
5624 parent = mono_class_get_com_object_class ();
5628 /* set the parent to something useful and safe, but mark the type as broken */
5629 parent = mono_defaults.object_class;
5630 mono_class_set_type_load_failure (klass, "");
5634 klass->parent = parent;
5636 if (mono_class_is_ginst (parent) && !parent->name) {
5638 * If the parent is a generic instance, we may get
5639 * called before it is fully initialized, especially
5640 * before it has its name.
5645 #ifndef DISABLE_REMOTING
5646 klass->marshalbyref = parent->marshalbyref;
5647 klass->contextbound = parent->contextbound;
5650 klass->delegate = parent->delegate;
5652 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5653 mono_class_set_is_com_object (klass);
5655 if (system_namespace) {
5656 #ifndef DISABLE_REMOTING
5657 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5658 klass->marshalbyref = 1;
5660 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5661 klass->contextbound = 1;
5663 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5664 klass->delegate = 1;
5667 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5668 (strcmp (klass->parent->name_space, "System") == 0)))
5669 klass->valuetype = 1;
5670 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5671 klass->valuetype = klass->enumtype = 1;
5673 /*klass->enumtype = klass->parent->enumtype; */
5675 /* initialize com types if COM interfaces are present */
5677 if (MONO_CLASS_IS_IMPORT (klass))
5678 init_com_from_comimport (klass);
5680 klass->parent = NULL;
5686 * mono_class_setup_supertypes:
5689 * Build the data structure needed to make fast type checks work.
5690 * This currently sets two fields in @class:
5691 * - idepth: distance between @class and System.Object in the type
5693 * - supertypes: array of classes: each element has a class in the hierarchy
5694 * starting from @class up to System.Object
5696 * LOCKING: Acquires the loader lock.
5699 mono_class_setup_supertypes (MonoClass *klass)
5702 MonoClass **supertypes;
5704 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5708 if (klass->parent && !klass->parent->supertypes)
5709 mono_class_setup_supertypes (klass->parent);
5711 idepth = klass->parent->idepth + 1;
5715 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5716 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5718 if (klass->parent) {
5719 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5722 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5723 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5725 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5728 mono_memory_barrier ();
5730 mono_loader_lock ();
5731 klass->idepth = idepth;
5732 /* Needed so idepth is visible before supertypes is set */
5733 mono_memory_barrier ();
5734 klass->supertypes = supertypes;
5735 mono_loader_unlock ();
5739 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5741 MonoClass *gtd = (MonoClass*)user_data;
5742 /* Only try to fix generic instances of @gtd */
5743 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5746 /* Check if the generic instance has no parent. */
5747 if (gtd->parent && !gclass->parent)
5748 mono_generic_class_setup_parent (gclass, gtd);
5754 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5756 mono_class_set_type_load_failure (klass, "%s", msg);
5757 mono_error_set_type_load_class (error, klass, "%s", msg);
5761 * mono_class_create_from_typedef:
5762 * @image: image where the token is valid
5763 * @type_token: typedef token
5764 * @error: used to return any error found while creating the type
5766 * Create the MonoClass* representing the specified type token.
5767 * @type_token must be a TypeDef token.
5769 * FIXME: don't return NULL on failure, just the the caller figure it out.
5772 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5774 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5775 MonoClass *klass, *parent = NULL;
5776 guint32 cols [MONO_TYPEDEF_SIZE];
5777 guint32 cols_next [MONO_TYPEDEF_SIZE];
5778 guint tidx = mono_metadata_token_index (type_token);
5779 MonoGenericContext *context = NULL;
5780 const char *name, *nspace;
5782 MonoClass **interfaces;
5783 guint32 field_last, method_last;
5784 guint32 nesting_tokeen;
5786 mono_error_init (error);
5788 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5789 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5793 mono_loader_lock ();
5795 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5796 mono_loader_unlock ();
5800 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5802 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5803 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5805 if (mono_metadata_has_generic_params (image, type_token)) {
5806 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5807 klass->class_kind = MONO_CLASS_GTD;
5808 classes_size += sizeof (MonoClassGtd);
5811 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5812 klass->class_kind = MONO_CLASS_DEF;
5813 classes_size += sizeof (MonoClassDef);
5818 klass->name_space = nspace;
5820 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5822 klass->image = image;
5823 klass->type_token = type_token;
5824 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5826 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5829 * Check whether we're a generic type definition.
5831 if (mono_class_is_gtd (klass)) {
5832 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5833 generic_container->owner.klass = klass;
5834 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5835 context = &generic_container->context;
5836 mono_class_set_generic_container (klass, generic_container);
5837 enable_gclass_recording ();
5840 if (cols [MONO_TYPEDEF_EXTENDS]) {
5842 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5844 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5845 /*WARNING: this must satisfy mono_metadata_type_hash*/
5846 klass->this_arg.byref = 1;
5847 klass->this_arg.data.klass = klass;
5848 klass->this_arg.type = MONO_TYPE_CLASS;
5849 klass->byval_arg.data.klass = klass;
5850 klass->byval_arg.type = MONO_TYPE_CLASS;
5852 parent = mono_class_get_checked (image, parent_token, error);
5853 if (parent && context) /* Always inflate */
5854 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5856 if (parent == NULL) {
5857 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5858 goto parent_failure;
5861 for (tmp = parent; tmp; tmp = tmp->parent) {
5863 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5864 goto parent_failure;
5866 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5867 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5868 goto parent_failure;
5873 mono_class_setup_parent (klass, parent);
5875 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5876 mono_class_setup_mono_type (klass);
5878 if (mono_class_is_gtd (klass))
5879 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5882 * This might access klass->byval_arg for recursion generated by generic constraints,
5883 * so it has to come after setup_mono_type ().
5885 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5886 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5887 if (!mono_error_ok (error)) {
5888 /*FIXME implement a mono_class_set_failure_from_mono_error */
5889 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5890 mono_loader_unlock ();
5891 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5896 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5900 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5904 klass->cast_class = klass->element_class = klass;
5906 if (!klass->enumtype) {
5907 if (!mono_metadata_interfaces_from_typedef_full (
5908 image, type_token, &interfaces, &icount, FALSE, context, error)){
5910 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5911 mono_loader_unlock ();
5912 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5916 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5917 g_assert(icount <= 65535);
5919 klass->interfaces = interfaces;
5920 klass->interface_count = icount;
5921 klass->interfaces_inited = 1;
5924 /*g_print ("Load class %s\n", name);*/
5927 * Compute the field and method lists
5929 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5930 mono_class_set_first_field_idx (klass, first_field_idx);
5931 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5932 mono_class_set_first_method_idx (klass, first_method_idx);
5934 if (tt->rows > tidx){
5935 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5936 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5937 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5939 field_last = image->tables [MONO_TABLE_FIELD].rows;
5940 method_last = image->tables [MONO_TABLE_METHOD].rows;
5943 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5944 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5945 mono_class_set_field_count (klass, field_last - first_field_idx);
5946 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5947 mono_class_set_method_count (klass, method_last - first_method_idx);
5949 /* reserve space to store vector pointer in arrays */
5950 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5951 klass->instance_size += 2 * sizeof (gpointer);
5952 g_assert (mono_class_get_field_count (klass) == 0);
5955 if (klass->enumtype) {
5956 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5957 if (!enum_basetype) {
5958 /*set it to a default value as the whole runtime can't handle this to be null*/
5959 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5960 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5961 mono_loader_unlock ();
5962 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5965 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5969 * If we're a generic type definition, load the constraints.
5970 * We must do this after the class has been constructed to make certain recursive scenarios
5973 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5974 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5975 mono_loader_unlock ();
5976 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5980 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5981 if (!strncmp (name, "Vector", 6))
5982 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");
5985 mono_loader_unlock ();
5987 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5992 mono_class_setup_mono_type (klass);
5993 mono_loader_unlock ();
5994 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5998 /** Is klass a Nullable<T> ginst? */
6000 mono_class_is_nullable (MonoClass *klass)
6002 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
6003 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
6007 /** if klass is T? return T */
6009 mono_class_get_nullable_param (MonoClass *klass)
6011 g_assert (mono_class_is_nullable (klass));
6012 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
6016 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6020 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
6022 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6023 if (!mono_error_ok (&error)) {
6024 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6025 klass->parent = mono_defaults.object_class;
6026 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
6027 mono_error_cleanup (&error);
6031 mono_class_setup_parent (klass, klass->parent);
6033 if (klass->enumtype) {
6034 klass->cast_class = gtd->cast_class;
6035 klass->element_class = gtd->element_class;
6041 * Create the `MonoClass' for an instantiation of a generic type.
6042 * We only do this if we actually need it.
6045 mono_generic_class_get_class (MonoGenericClass *gclass)
6047 MonoClass *klass, *gklass;
6049 if (gclass->cached_class)
6050 return gclass->cached_class;
6052 mono_loader_lock ();
6053 if (gclass->cached_class) {
6054 mono_loader_unlock ();
6055 return gclass->cached_class;
6058 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6060 gklass = gclass->container_class;
6062 if (record_gclass_instantiation > 0)
6063 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6065 if (gklass->nested_in) {
6066 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6067 klass->nested_in = gklass->nested_in;
6070 klass->name = gklass->name;
6071 klass->name_space = gklass->name_space;
6073 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6075 klass->image = gklass->image;
6076 klass->type_token = gklass->type_token;
6078 klass->class_kind = MONO_CLASS_GINST;
6080 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6082 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6083 klass->this_arg.type = klass->byval_arg.type;
6084 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6085 klass->this_arg.byref = TRUE;
6086 klass->enumtype = gklass->enumtype;
6087 klass->valuetype = gklass->valuetype;
6089 klass->cast_class = klass->element_class = klass;
6091 if (mono_class_is_nullable (klass))
6092 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6095 * We're not interested in the nested classes of a generic instance.
6096 * We use the generic type definition to look for nested classes.
6099 mono_generic_class_setup_parent (klass, gklass);
6101 if (gclass->is_dynamic) {
6103 * 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.
6104 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6105 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6107 if (!gklass->wastypebuilder)
6110 mono_class_setup_supertypes (klass);
6112 if (klass->enumtype) {
6114 * For enums, gklass->fields might not been set, but instance_size etc. is
6115 * already set in mono_reflection_create_internal_class (). For non-enums,
6116 * these will be computed normally in mono_class_layout_fields ().
6118 klass->instance_size = gklass->instance_size;
6119 klass->sizes.class_size = gklass->sizes.class_size;
6120 mono_memory_barrier ();
6121 klass->size_inited = 1;
6125 mono_memory_barrier ();
6126 gclass->cached_class = klass;
6128 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6130 ++class_ginst_count;
6131 inflated_classes_size += sizeof (MonoClassGenericInst);
6133 mono_loader_unlock ();
6139 get_image_for_container (MonoGenericContainer *container)
6142 if (container->is_anonymous) {
6143 result = container->owner.image;
6146 if (container->is_method) {
6147 MonoMethod *method = container->owner.method;
6148 g_assert_checked (method);
6149 klass = method->klass;
6151 klass = container->owner.klass;
6153 g_assert_checked (klass);
6154 result = klass->image;
6161 get_image_for_generic_param (MonoGenericParam *param)
6163 MonoGenericContainer *container = mono_generic_param_owner (param);
6164 g_assert_checked (container);
6165 return get_image_for_container (container);
6168 // Make a string in the designated image consisting of a single integer.
6169 #define INT_STRING_SIZE 16
6171 make_generic_name_string (MonoImage *image, int num)
6173 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6174 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6178 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6179 // pinfo is derived from param by the caller for us.
6181 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6183 MonoClass *klass, **ptr;
6185 MonoGenericContainer *container = mono_generic_param_owner (param);
6186 g_assert_checked (container);
6188 MonoImage *image = get_image_for_container (container);
6189 gboolean is_mvar = container->is_method;
6190 gboolean is_anonymous = container->is_anonymous;
6192 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6193 klass->class_kind = MONO_CLASS_GPARAM;
6194 classes_size += sizeof (MonoClassGenericParam);
6195 ++class_gparam_count;
6198 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6200 int n = mono_generic_param_num (param);
6201 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6205 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6206 } else if (is_mvar) {
6207 MonoMethod *omethod = container->owner.method;
6208 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6210 MonoClass *oklass = container->owner.klass;
6211 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6214 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6216 // Count non-NULL items in pinfo->constraints
6219 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6223 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6224 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6226 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6227 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6229 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6232 if (count - pos > 0) {
6233 klass->interface_count = count - pos;
6234 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6235 klass->interfaces_inited = TRUE;
6236 for (i = pos; i < count; i++)
6237 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6240 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6242 klass->inited = TRUE;
6243 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6244 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6246 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6247 klass->this_arg.type = klass->byval_arg.type;
6248 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6249 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6250 klass->this_arg.byref = TRUE;
6252 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6253 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6255 /*Init these fields to sane values*/
6256 klass->min_align = 1;
6258 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6259 * constrained to, the JIT depends on this.
6261 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6262 mono_memory_barrier ();
6263 klass->size_inited = 1;
6265 mono_class_setup_supertypes (klass);
6267 if (count - pos > 0) {
6268 mono_class_setup_vtable (klass->parent);
6269 if (mono_class_has_failure (klass->parent))
6270 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6272 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6278 #define FAST_CACHE_SIZE 16
6281 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6282 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6283 * we cache the MonoClasses.
6284 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6285 * LOCKING: Takes the image lock depending on @take_lock.
6288 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6290 int n = mono_generic_param_num (param);
6291 MonoImage *image = get_image_for_generic_param (param);
6292 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6293 MonoClass *klass = NULL;
6298 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6299 // For high numbers or constraints we have to use pointer hashes.
6300 if (param->gshared_constraint) {
6301 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6304 mono_image_lock (image);
6305 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6307 mono_image_unlock (image);
6312 if (n < FAST_CACHE_SIZE) {
6314 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6316 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6318 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6321 mono_image_lock (image);
6322 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6324 mono_image_unlock (image);
6331 * LOCKING: Image lock (param->image) must be held
6334 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6336 int n = mono_generic_param_num (param);
6337 MonoImage *image = get_image_for_generic_param (param);
6338 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6342 if (param->gshared_constraint) {
6343 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6345 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6346 mono_memory_barrier ();
6348 image->mvar_cache_constrained = ht;
6350 image->var_cache_constrained = ht;
6352 g_hash_table_insert (ht, param, klass);
6353 } else if (n < FAST_CACHE_SIZE) {
6355 /* Requires locking to avoid droping an already published class */
6356 if (!image->mvar_cache_fast)
6357 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6358 image->mvar_cache_fast [n] = klass;
6360 if (!image->var_cache_fast)
6361 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6362 image->var_cache_fast [n] = klass;
6365 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6367 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6369 ht = g_hash_table_new (NULL, NULL);
6370 mono_memory_barrier ();
6372 image->mvar_cache_slow = ht;
6374 image->var_cache_slow = ht;
6377 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6382 * LOCKING: Acquires the image lock (@image).
6385 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6387 MonoImage *image = get_image_for_generic_param (param);
6388 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6389 MonoClass *klass, *klass2;
6391 // If a klass already exists for this object and is cached, return it.
6392 if (pinfo) // Non-anonymous
6393 klass = pinfo->pklass;
6395 klass = get_anon_gparam_class (param, TRUE);
6400 // Create a new klass
6401 klass = make_generic_param_class (param, pinfo);
6403 // Now we need to cache the klass we created.
6404 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6405 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6406 // and allow our newly-created klass object to just leak.
6407 mono_memory_barrier ();
6409 mono_image_lock (image);
6411 // Here "klass2" refers to the klass potentially created by the other thread.
6412 if (pinfo) // Repeat check from above
6413 klass2 = pinfo->pklass;
6415 klass2 = get_anon_gparam_class (param, FALSE);
6422 pinfo->pklass = klass;
6424 set_anon_gparam_class (param, klass);
6426 mono_image_unlock (image);
6428 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6430 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6432 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6438 * mono_class_from_generic_parameter:
6439 * @param: Parameter to find/construct a class for.
6440 * @arg2: Is ignored.
6441 * @arg3: Is ignored.
6444 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6446 return mono_class_from_generic_parameter_internal (param);
6451 mono_ptr_class_get (MonoType *type)
6454 MonoClass *el_class;
6458 el_class = mono_class_from_mono_type (type);
6459 image = el_class->image;
6461 mono_image_lock (image);
6462 if (image->ptr_cache) {
6463 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6464 mono_image_unlock (image);
6468 mono_image_unlock (image);
6470 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6472 classes_size += sizeof (MonoClassPointer);
6473 ++class_pointer_count;
6475 result->parent = NULL; /* no parent for PTR types */
6476 result->name_space = el_class->name_space;
6477 name = g_strdup_printf ("%s*", el_class->name);
6478 result->name = mono_image_strdup (image, name);
6479 result->class_kind = MONO_CLASS_POINTER;
6482 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6484 result->image = el_class->image;
6485 result->inited = TRUE;
6486 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6487 result->cast_class = result->element_class = el_class;
6488 result->blittable = TRUE;
6490 result->byval_arg.type = MONO_TYPE_PTR;
6491 result->this_arg.type = result->byval_arg.type;
6492 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6493 result->this_arg.byref = TRUE;
6495 mono_class_setup_supertypes (result);
6497 mono_image_lock (image);
6498 if (image->ptr_cache) {
6500 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6501 mono_image_unlock (image);
6502 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6506 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6508 g_hash_table_insert (image->ptr_cache, el_class, result);
6509 mono_image_unlock (image);
6511 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6517 mono_fnptr_class_get (MonoMethodSignature *sig)
6520 static GHashTable *ptr_hash = NULL;
6522 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6524 mono_loader_lock ();
6527 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6529 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6530 mono_loader_unlock ();
6533 result = g_new0 (MonoClass, 1);
6535 classes_size += sizeof (MonoClassPointer);
6536 ++class_pointer_count;
6538 result->parent = NULL; /* no parent for PTR types */
6539 result->name_space = "System";
6540 result->name = "MonoFNPtrFakeClass";
6541 result->class_kind = MONO_CLASS_POINTER;
6543 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6545 result->image = mono_defaults.corlib; /* need to fix... */
6546 result->inited = TRUE;
6547 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6548 result->cast_class = result->element_class = result;
6549 result->blittable = TRUE;
6551 result->byval_arg.type = MONO_TYPE_FNPTR;
6552 result->this_arg.type = result->byval_arg.type;
6553 result->this_arg.data.method = result->byval_arg.data.method = sig;
6554 result->this_arg.byref = TRUE;
6555 result->blittable = TRUE;
6557 mono_class_setup_supertypes (result);
6559 g_hash_table_insert (ptr_hash, sig, result);
6561 mono_loader_unlock ();
6563 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6569 * mono_class_from_mono_type:
6570 * @type: describes the type to return
6572 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6575 mono_class_from_mono_type (MonoType *type)
6577 switch (type->type) {
6578 case MONO_TYPE_OBJECT:
6579 return type->data.klass? type->data.klass: mono_defaults.object_class;
6580 case MONO_TYPE_VOID:
6581 return type->data.klass? type->data.klass: mono_defaults.void_class;
6582 case MONO_TYPE_BOOLEAN:
6583 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6584 case MONO_TYPE_CHAR:
6585 return type->data.klass? type->data.klass: mono_defaults.char_class;
6587 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6589 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6591 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6593 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6595 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6597 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6599 return type->data.klass? type->data.klass: mono_defaults.int_class;
6601 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6603 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6605 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6607 return type->data.klass? type->data.klass: mono_defaults.single_class;
6609 return type->data.klass? type->data.klass: mono_defaults.double_class;
6610 case MONO_TYPE_STRING:
6611 return type->data.klass? type->data.klass: mono_defaults.string_class;
6612 case MONO_TYPE_TYPEDBYREF:
6613 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6614 case MONO_TYPE_ARRAY:
6615 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6617 return mono_ptr_class_get (type->data.type);
6618 case MONO_TYPE_FNPTR:
6619 return mono_fnptr_class_get (type->data.method);
6620 case MONO_TYPE_SZARRAY:
6621 return mono_array_class_get (type->data.klass, 1);
6622 case MONO_TYPE_CLASS:
6623 case MONO_TYPE_VALUETYPE:
6624 return type->data.klass;
6625 case MONO_TYPE_GENERICINST:
6626 return mono_generic_class_get_class (type->data.generic_class);
6627 case MONO_TYPE_MVAR:
6629 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6631 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6632 g_assert_not_reached ();
6635 // Yes, this returns NULL, even if it is documented as not doing so, but there
6636 // is no way for the code to make it this far, due to the assert above.
6641 * mono_type_retrieve_from_typespec
6642 * @image: context where the image is created
6643 * @type_spec: typespec token
6644 * @context: the generic context used to evaluate generic instantiations in
6647 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6649 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6651 *did_inflate = FALSE;
6656 if (context && (context->class_inst || context->method_inst)) {
6657 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6659 if (!mono_error_ok (error)) {
6665 *did_inflate = TRUE;
6672 * mono_class_create_from_typespec
6673 * @image: context where the image is created
6674 * @type_spec: typespec token
6675 * @context: the generic context used to evaluate generic instantiations in
6678 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6681 gboolean inflated = FALSE;
6682 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6683 return_val_if_nok (error, NULL);
6684 ret = mono_class_from_mono_type (t);
6686 mono_metadata_free_type (t);
6691 * mono_bounded_array_class_get:
6692 * @element_class: element class
6693 * @rank: the dimension of the array class
6694 * @bounded: whenever the array has non-zero bounds
6696 * Returns: A class object describing the array with element type @element_type and
6700 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6704 MonoClass *parent = NULL;
6705 GSList *list, *rootlist = NULL;
6709 g_assert (rank <= 255);
6712 /* bounded only matters for one-dimensional arrays */
6715 image = eclass->image;
6717 if (rank == 1 && !bounded) {
6719 * This case is very frequent not just during compilation because of calls
6720 * from mono_class_from_mono_type (), mono_array_new (),
6721 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6723 mono_os_mutex_lock (&image->szarray_cache_lock);
6724 if (!image->szarray_cache)
6725 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6726 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6727 mono_os_mutex_unlock (&image->szarray_cache_lock);
6731 mono_loader_lock ();
6733 mono_loader_lock ();
6735 if (!image->array_cache)
6736 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6738 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6739 for (; list; list = list->next) {
6740 klass = (MonoClass *)list->data;
6741 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6742 mono_loader_unlock ();
6749 parent = mono_defaults.array_class;
6750 if (!parent->inited)
6751 mono_class_init (parent);
6753 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6755 klass->image = image;
6756 klass->name_space = eclass->name_space;
6757 klass->class_kind = MONO_CLASS_ARRAY;
6759 nsize = strlen (eclass->name);
6760 name = (char *)g_malloc (nsize + 2 + rank + 1);
6761 memcpy (name, eclass->name, nsize);
6764 memset (name + nsize + 1, ',', rank - 1);
6766 name [nsize + rank] = '*';
6767 name [nsize + rank + bounded] = ']';
6768 name [nsize + rank + bounded + 1] = 0;
6769 klass->name = mono_image_strdup (image, name);
6772 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6774 classes_size += sizeof (MonoClassArray);
6775 ++class_array_count;
6777 klass->type_token = 0;
6778 klass->parent = parent;
6779 klass->instance_size = mono_class_instance_size (klass->parent);
6781 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6782 /*Arrays of those two types are invalid.*/
6783 MonoError prepared_error;
6784 mono_error_init (&prepared_error);
6785 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6786 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6787 mono_error_cleanup (&prepared_error);
6788 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6789 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6790 if (!ref_info_handle || eclass->wastypebuilder) {
6791 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6792 g_assert (ref_info_handle && !eclass->wastypebuilder);
6794 /* element_size -1 is ok as this is not an instantitable type*/
6795 klass->sizes.element_size = -1;
6797 klass->sizes.element_size = mono_class_array_element_size (eclass);
6799 mono_class_setup_supertypes (klass);
6801 if (mono_class_is_ginst (eclass))
6802 mono_class_init (eclass);
6803 if (!eclass->size_inited)
6804 mono_class_setup_fields (eclass);
6805 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6806 /*FIXME we fail the array type, but we have to let other fields be set.*/
6808 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6812 if (eclass->enumtype)
6813 klass->cast_class = eclass->element_class;
6815 klass->cast_class = eclass;
6817 switch (klass->cast_class->byval_arg.type) {
6819 klass->cast_class = mono_defaults.byte_class;
6822 klass->cast_class = mono_defaults.int16_class;
6825 #if SIZEOF_VOID_P == 4
6829 klass->cast_class = mono_defaults.int32_class;
6832 #if SIZEOF_VOID_P == 8
6836 klass->cast_class = mono_defaults.int64_class;
6842 klass->element_class = eclass;
6844 if ((rank > 1) || bounded) {
6845 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6846 klass->byval_arg.type = MONO_TYPE_ARRAY;
6847 klass->byval_arg.data.array = at;
6848 at->eklass = eclass;
6850 /* FIXME: complete.... */
6852 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6853 klass->byval_arg.data.klass = eclass;
6855 klass->this_arg = klass->byval_arg;
6856 klass->this_arg.byref = 1;
6858 //WTF was this? it's wrong
6859 // klass->generic_container = eclass->generic_container;
6861 if (rank == 1 && !bounded) {
6862 MonoClass *prev_class;
6864 mono_os_mutex_lock (&image->szarray_cache_lock);
6865 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6867 /* Someone got in before us */
6870 g_hash_table_insert (image->szarray_cache, eclass, klass);
6871 mono_os_mutex_unlock (&image->szarray_cache_lock);
6873 list = g_slist_append (rootlist, klass);
6874 g_hash_table_insert (image->array_cache, eclass, list);
6877 mono_loader_unlock ();
6879 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6885 * mono_array_class_get:
6886 * @element_class: element class
6887 * @rank: the dimension of the array class
6889 * Returns: A class object describing the array with element type @element_type and
6893 mono_array_class_get (MonoClass *eclass, guint32 rank)
6895 return mono_bounded_array_class_get (eclass, rank, FALSE);
6899 * mono_class_instance_size:
6902 * Use to get the size of a class in bytes.
6904 * Returns: The size of an object instance
6907 mono_class_instance_size (MonoClass *klass)
6909 if (!klass->size_inited)
6910 mono_class_init (klass);
6912 return klass->instance_size;
6916 * mono_class_min_align:
6919 * Use to get the computed minimum alignment requirements for the specified class.
6921 * Returns: minimum alignment requirements
6924 mono_class_min_align (MonoClass *klass)
6926 if (!klass->size_inited)
6927 mono_class_init (klass);
6929 return klass->min_align;
6933 * mono_class_value_size:
6936 * This function is used for value types, and return the
6937 * space and the alignment to store that kind of value object.
6939 * Returns: the size of a value of kind @klass
6942 mono_class_value_size (MonoClass *klass, guint32 *align)
6946 /* fixme: check disable, because we still have external revereces to
6947 * mscorlib and Dummy Objects
6949 /*g_assert (klass->valuetype);*/
6951 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6954 *align = klass->min_align;
6960 * mono_class_data_size:
6963 * Returns: The size of the static class data
6966 mono_class_data_size (MonoClass *klass)
6969 mono_class_init (klass);
6970 /* This can happen with dynamically created types */
6971 if (!klass->fields_inited)
6972 mono_class_setup_fields (klass);
6974 /* in arrays, sizes.class_size is unioned with element_size
6975 * and arrays have no static fields
6979 return klass->sizes.class_size;
6983 * Auxiliary routine to mono_class_get_field
6985 * Takes a field index instead of a field token.
6987 static MonoClassField *
6988 mono_class_get_field_idx (MonoClass *klass, int idx)
6990 mono_class_setup_fields (klass);
6991 if (mono_class_has_failure (klass))
6995 int first_field_idx = mono_class_get_first_field_idx (klass);
6996 int fcount = mono_class_get_field_count (klass);
6997 if (klass->image->uncompressed_metadata) {
6999 * first_field_idx points to the FieldPtr table, while idx points into the
7000 * Field table, so we have to do a search.
7002 /*FIXME this is broken for types with multiple fields with the same name.*/
7003 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7006 for (i = 0; i < fcount; ++i)
7007 if (mono_field_get_name (&klass->fields [i]) == name)
7008 return &klass->fields [i];
7009 g_assert_not_reached ();
7012 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
7013 return &klass->fields [idx - first_field_idx];
7017 klass = klass->parent;
7023 * mono_class_get_field:
7024 * @class: the class to lookup the field.
7025 * @field_token: the field token
7027 * Returns: A MonoClassField representing the type and offset of
7028 * the field, or a NULL value if the field does not belong to this
7032 mono_class_get_field (MonoClass *klass, guint32 field_token)
7034 int idx = mono_metadata_token_index (field_token);
7036 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7038 return mono_class_get_field_idx (klass, idx - 1);
7042 * mono_class_get_field_from_name:
7043 * @klass: the class to lookup the field.
7044 * @name: the field name
7046 * Search the class @klass and it's parents for a field with the name @name.
7048 * Returns: The MonoClassField pointer of the named field or NULL
7051 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7053 return mono_class_get_field_from_name_full (klass, name, NULL);
7057 * mono_class_get_field_from_name_full:
7058 * @klass: the class to lookup the field.
7059 * @name: the field name
7060 * @type: the type of the fields. This optional.
7062 * Search the class @klass and it's parents for a field with the name @name and type @type.
7064 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7065 * of its generic type definition.
7067 * Returns: The MonoClassField pointer of the named field or NULL
7070 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7074 mono_class_setup_fields (klass);
7075 if (mono_class_has_failure (klass))
7079 int fcount = mono_class_get_field_count (klass);
7080 for (i = 0; i < fcount; ++i) {
7081 MonoClassField *field = &klass->fields [i];
7083 if (strcmp (name, mono_field_get_name (field)) != 0)
7087 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7088 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7093 klass = klass->parent;
7099 * mono_class_get_field_token:
7100 * @field: the field we need the token of
7102 * Get the token of a field. Note that the tokesn is only valid for the image
7103 * the field was loaded from. Don't use this function for fields in dynamic types.
7105 * Returns: The token representing the field in the image it was loaded from.
7108 mono_class_get_field_token (MonoClassField *field)
7110 MonoClass *klass = field->parent;
7113 mono_class_setup_fields (klass);
7118 int first_field_idx = mono_class_get_first_field_idx (klass);
7119 int fcount = mono_class_get_field_count (klass);
7120 for (i = 0; i < fcount; ++i) {
7121 if (&klass->fields [i] == field) {
7122 int idx = first_field_idx + i + 1;
7124 if (klass->image->uncompressed_metadata)
7125 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7126 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7129 klass = klass->parent;
7132 g_assert_not_reached ();
7137 mono_field_get_index (MonoClassField *field)
7139 int index = field - field->parent->fields;
7140 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
7146 * mono_class_get_field_default_value:
7148 * Return the default value of the field as a pointer into the metadata blob.
7151 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7154 guint32 constant_cols [MONO_CONSTANT_SIZE];
7156 MonoClass *klass = field->parent;
7158 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7160 MonoClassExt *ext = mono_class_get_ext (klass);
7161 if (!ext || !ext->field_def_values) {
7162 MonoFieldDefaultValue *def_values;
7164 mono_class_alloc_ext (klass);
7165 ext = mono_class_get_ext (klass);
7167 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7169 mono_image_lock (klass->image);
7170 mono_memory_barrier ();
7171 if (!ext->field_def_values)
7172 ext->field_def_values = def_values;
7173 mono_image_unlock (klass->image);
7176 field_index = mono_field_get_index (field);
7178 if (!ext->field_def_values [field_index].data) {
7179 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7183 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7185 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7186 ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7187 ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7190 *def_type = ext->field_def_values [field_index].def_type;
7191 return ext->field_def_values [field_index].data;
7195 mono_property_get_index (MonoProperty *prop)
7197 MonoClassExt *ext = mono_class_get_ext (prop->parent);
7198 int index = prop - ext->properties;
7200 g_assert (index >= 0 && index < ext->property.count);
7206 * mono_class_get_property_default_value:
7208 * Return the default value of the field as a pointer into the metadata blob.
7211 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7214 guint32 constant_cols [MONO_CONSTANT_SIZE];
7215 MonoClass *klass = property->parent;
7217 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7219 * We don't cache here because it is not used by C# so it's quite rare, but
7220 * we still do the lookup in klass->ext because that is where the data
7221 * is stored for dynamic assemblies.
7224 if (image_is_dynamic (klass->image)) {
7225 MonoClassExt *ext = mono_class_get_ext (klass);
7226 int prop_index = mono_property_get_index (property);
7227 if (ext->prop_def_values && ext->prop_def_values [prop_index].data) {
7228 *def_type = ext->prop_def_values [prop_index].def_type;
7229 return ext->prop_def_values [prop_index].data;
7233 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7237 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7238 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7239 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7243 mono_class_get_event_token (MonoEvent *event)
7245 MonoClass *klass = event->parent;
7249 MonoClassExt *ext = mono_class_get_ext (klass);
7251 for (i = 0; i < ext->event.count; ++i) {
7252 if (&ext->events [i] == event)
7253 return mono_metadata_make_token (MONO_TABLE_EVENT, ext->event.first + i + 1);
7256 klass = klass->parent;
7259 g_assert_not_reached ();
7264 * mono_class_get_property_from_name:
7266 * @name: name of the property to lookup in the specified class
7268 * Use this method to lookup a property in a class
7269 * Returns: the MonoProperty with the given name, or NULL if the property
7270 * does not exist on the @klass.
7273 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7277 gpointer iter = NULL;
7278 while ((p = mono_class_get_properties (klass, &iter))) {
7279 if (! strcmp (name, p->name))
7282 klass = klass->parent;
7288 * mono_class_get_property_token:
7289 * @prop: MonoProperty to query
7291 * Returns: The ECMA token for the specified property.
7294 mono_class_get_property_token (MonoProperty *prop)
7296 MonoClass *klass = prop->parent;
7300 gpointer iter = NULL;
7301 MonoClassExt *ext = mono_class_get_ext (klass);
7302 while ((p = mono_class_get_properties (klass, &iter))) {
7303 if (&ext->properties [i] == prop)
7304 return mono_metadata_make_token (MONO_TABLE_PROPERTY, ext->property.first + i + 1);
7308 klass = klass->parent;
7311 g_assert_not_reached ();
7316 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7318 const char *name, *nspace;
7319 if (image_is_dynamic (image))
7320 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7322 switch (type_token & 0xff000000){
7323 case MONO_TOKEN_TYPE_DEF: {
7324 guint32 cols [MONO_TYPEDEF_SIZE];
7325 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7326 guint tidx = mono_metadata_token_index (type_token);
7328 if (tidx > tt->rows)
7329 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7331 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7332 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7333 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7334 if (strlen (nspace) == 0)
7335 return g_strdup_printf ("%s", name);
7337 return g_strdup_printf ("%s.%s", nspace, name);
7340 case MONO_TOKEN_TYPE_REF: {
7342 guint32 cols [MONO_TYPEREF_SIZE];
7343 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7344 guint tidx = mono_metadata_token_index (type_token);
7347 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7349 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7350 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7351 mono_error_cleanup (&error);
7355 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7356 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7357 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7358 if (strlen (nspace) == 0)
7359 return g_strdup_printf ("%s", name);
7361 return g_strdup_printf ("%s.%s", nspace, name);
7364 case MONO_TOKEN_TYPE_SPEC:
7365 return g_strdup_printf ("Typespec 0x%08x", type_token);
7367 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7372 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7374 if (image_is_dynamic (image))
7375 return g_strdup_printf ("DynamicAssembly %s", image->name);
7377 switch (type_token & 0xff000000){
7378 case MONO_TOKEN_TYPE_DEF:
7379 if (image->assembly)
7380 return mono_stringify_assembly_name (&image->assembly->aname);
7381 else if (image->assembly_name)
7382 return g_strdup (image->assembly_name);
7383 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7384 case MONO_TOKEN_TYPE_REF: {
7386 MonoAssemblyName aname;
7387 guint32 cols [MONO_TYPEREF_SIZE];
7388 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7389 guint32 idx = mono_metadata_token_index (type_token);
7392 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7394 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7395 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7396 mono_error_cleanup (&error);
7399 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7401 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7402 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7403 case MONO_RESOLUTION_SCOPE_MODULE:
7405 return g_strdup ("");
7406 case MONO_RESOLUTION_SCOPE_MODULEREF:
7408 return g_strdup ("");
7409 case MONO_RESOLUTION_SCOPE_TYPEREF:
7411 return g_strdup ("");
7412 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7413 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7414 return mono_stringify_assembly_name (&aname);
7416 g_assert_not_reached ();
7420 case MONO_TOKEN_TYPE_SPEC:
7422 return g_strdup ("");
7424 g_assert_not_reached ();
7431 * mono_class_get_full:
7432 * @image: the image where the class resides
7433 * @type_token: the token for the class
7434 * @context: the generic context used to evaluate generic instantiations in
7435 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7437 * Returns: The MonoClass that represents @type_token in @image
7440 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7444 klass = mono_class_get_checked (image, type_token, &error);
7446 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7447 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7449 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7455 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7459 mono_error_init (error);
7460 klass = mono_class_get_checked (image, type_token, error);
7462 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7463 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7468 * mono_class_get_checked:
7469 * @image: the image where the class resides
7470 * @type_token: the token for the class
7471 * @error: error object to return any error
7473 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7476 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7478 MonoClass *klass = NULL;
7480 mono_error_init (error);
7482 if (image_is_dynamic (image)) {
7483 int table = mono_metadata_token_table (type_token);
7485 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7486 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7489 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7493 switch (type_token & 0xff000000){
7494 case MONO_TOKEN_TYPE_DEF:
7495 klass = mono_class_create_from_typedef (image, type_token, error);
7497 case MONO_TOKEN_TYPE_REF:
7498 klass = mono_class_from_typeref_checked (image, type_token, error);
7500 case MONO_TOKEN_TYPE_SPEC:
7501 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7504 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7508 /* Generic case, should be avoided for when a better error is possible. */
7509 if (!klass && mono_error_ok (error)) {
7510 char *name = mono_class_name_from_token (image, type_token);
7511 char *assembly = mono_assembly_name_from_token (image, type_token);
7512 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7520 * mono_type_get_checked:
7521 * @image: the image where the type resides
7522 * @type_token: the token for the type
7523 * @context: the generic context used to evaluate generic instantiations in
7524 * @error: Error handling context
7526 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7528 * Returns: The MonoType that represents @type_token in @image
7531 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7533 MonoType *type = NULL;
7534 gboolean inflated = FALSE;
7536 mono_error_init (error);
7538 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7539 if (image_is_dynamic (image)) {
7540 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7541 return_val_if_nok (error, NULL);
7542 return mono_class_get_type (klass);
7545 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7546 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7553 return mono_class_get_type (klass);
7556 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7563 MonoType *tmp = type;
7564 type = mono_class_get_type (mono_class_from_mono_type (type));
7565 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7566 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7567 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7569 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7571 if (type->type != tmp->type)
7574 mono_metadata_free_type (tmp);
7581 * @image: image where the class token will be looked up.
7582 * @type_token: a type token from the image
7584 * Returns the MonoClass with the given @type_token on the @image
7587 mono_class_get (MonoImage *image, guint32 type_token)
7589 return mono_class_get_full (image, type_token, NULL);
7593 * mono_image_init_name_cache:
7595 * Initializes the class name cache stored in image->name_cache.
7597 * LOCKING: Acquires the corresponding image lock.
7600 mono_image_init_name_cache (MonoImage *image)
7602 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7603 guint32 cols [MONO_TYPEDEF_SIZE];
7606 guint32 i, visib, nspace_index;
7607 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7609 if (image->name_cache)
7612 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7614 if (image_is_dynamic (image)) {
7615 mono_image_lock (image);
7616 if (image->name_cache) {
7617 /* Somebody initialized it before us */
7618 g_hash_table_destroy (the_name_cache);
7620 mono_atomic_store_release (&image->name_cache, the_name_cache);
7622 mono_image_unlock (image);
7626 /* Temporary hash table to avoid lookups in the nspace_table */
7627 name_cache2 = g_hash_table_new (NULL, NULL);
7629 for (i = 1; i <= t->rows; ++i) {
7630 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7631 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7633 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7634 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7636 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7638 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7639 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7641 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7642 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7643 if (!nspace_table) {
7644 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7645 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7646 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7649 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7652 /* Load type names from EXPORTEDTYPES table */
7654 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7655 guint32 cols [MONO_EXP_TYPE_SIZE];
7658 for (i = 0; i < t->rows; ++i) {
7659 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7661 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7662 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7666 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7667 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7669 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7670 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7671 if (!nspace_table) {
7672 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7673 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7674 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7677 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7681 g_hash_table_destroy (name_cache2);
7683 mono_image_lock (image);
7684 if (image->name_cache) {
7685 /* Somebody initialized it before us */
7686 g_hash_table_destroy (the_name_cache);
7688 mono_atomic_store_release (&image->name_cache, the_name_cache);
7690 mono_image_unlock (image);
7693 /*FIXME Only dynamic assemblies should allow this operation.*/
7695 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7696 const char *name, guint32 index)
7698 GHashTable *nspace_table;
7699 GHashTable *name_cache;
7702 mono_image_init_name_cache (image);
7703 mono_image_lock (image);
7705 name_cache = image->name_cache;
7706 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7707 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7708 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7711 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7712 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7714 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7716 mono_image_unlock (image);
7725 find_nocase (gpointer key, gpointer value, gpointer user_data)
7727 char *name = (char*)key;
7728 FindUserData *data = (FindUserData*)user_data;
7730 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7731 data->value = value;
7735 * mono_class_from_name_case:
7736 * @image: The MonoImage where the type is looked up in
7737 * @name_space: the type namespace
7738 * @name: the type short name.
7739 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7741 * Obtains a MonoClass with a given namespace and a given name which
7742 * is located in the given MonoImage. The namespace and name
7743 * lookups are case insensitive.
7746 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7749 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7750 mono_error_cleanup (&error);
7756 * mono_class_from_name_case:
7757 * @image: The MonoImage where the type is looked up in
7758 * @name_space: the type namespace
7759 * @name: the type short name.
7762 * Obtains a MonoClass with a given namespace and a given name which
7763 * is located in the given MonoImage. The namespace and name
7764 * lookups are case insensitive.
7766 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7767 * was not found. The @error object will contain information about the problem
7771 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7773 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7774 guint32 cols [MONO_TYPEDEF_SIZE];
7779 mono_error_init (error);
7781 if (image_is_dynamic (image)) {
7783 FindUserData user_data;
7785 mono_image_init_name_cache (image);
7786 mono_image_lock (image);
7788 user_data.key = name_space;
7789 user_data.value = NULL;
7790 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7792 if (user_data.value) {
7793 GHashTable *nspace_table = (GHashTable*)user_data.value;
7795 user_data.key = name;
7796 user_data.value = NULL;
7798 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7800 if (user_data.value)
7801 token = GPOINTER_TO_UINT (user_data.value);
7804 mono_image_unlock (image);
7807 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7813 /* add a cache if needed */
7814 for (i = 1; i <= t->rows; ++i) {
7815 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7816 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7818 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7819 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7821 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7823 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7824 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7825 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7826 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7832 return_nested_in (MonoClass *klass, char *nested)
7835 char *s = strchr (nested, '/');
7836 gpointer iter = NULL;
7843 while ((found = mono_class_get_nested_types (klass, &iter))) {
7844 if (strcmp (found->name, nested) == 0) {
7846 return return_nested_in (found, s);
7854 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7856 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7857 MonoImage *file_image;
7861 mono_error_init (error);
7864 * The EXPORTEDTYPES table only contains public types, so have to search the
7866 * Note: image->modules contains the contents of the MODULEREF table, while
7867 * the real module list is in the FILE table.
7869 for (i = 0; i < file_table->rows; i++) {
7870 guint32 cols [MONO_FILE_SIZE];
7871 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7872 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7875 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7877 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7878 if (klass || !is_ok (error))
7887 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7889 GHashTable *nspace_table;
7890 MonoImage *loaded_image;
7897 mono_error_init (error);
7899 // Checking visited images avoids stack overflows when cyclic references exist.
7900 if (g_hash_table_lookup (visited_images, image))
7903 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7905 if ((nested = strchr (name, '/'))) {
7906 int pos = nested - name;
7907 int len = strlen (name);
7910 memcpy (buf, name, len + 1);
7912 nested = buf + pos + 1;
7916 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7917 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7918 gboolean res = get_class_from_name (image, name_space, name, &klass);
7921 klass = search_modules (image, name_space, name, error);
7926 return klass ? return_nested_in (klass, nested) : NULL;
7932 mono_image_init_name_cache (image);
7933 mono_image_lock (image);
7935 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7938 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7940 mono_image_unlock (image);
7942 if (!token && image_is_dynamic (image) && image->modules) {
7943 /* Search modules as well */
7944 for (i = 0; i < image->module_count; ++i) {
7945 MonoImage *module = image->modules [i];
7947 klass = mono_class_from_name_checked (module, name_space, name, error);
7948 if (klass || !is_ok (error))
7954 klass = search_modules (image, name_space, name, error);
7955 if (klass || !is_ok (error))
7960 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7961 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7962 guint32 cols [MONO_EXP_TYPE_SIZE];
7965 idx = mono_metadata_token_index (token);
7967 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7969 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7970 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7971 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7974 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7976 return klass ? return_nested_in (klass, nested) : NULL;
7978 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7979 guint32 assembly_idx;
7981 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7983 mono_assembly_load_reference (image, assembly_idx - 1);
7984 g_assert (image->references [assembly_idx - 1]);
7985 if (image->references [assembly_idx - 1] == (gpointer)-1)
7987 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7989 return klass ? return_nested_in (klass, nested) : NULL;
7992 g_assert_not_reached ();
7996 token = MONO_TOKEN_TYPE_DEF | token;
7998 klass = mono_class_get_checked (image, token, error);
8000 return return_nested_in (klass, nested);
8005 * mono_class_from_name_checked:
8006 * @image: The MonoImage where the type is looked up in
8007 * @name_space: the type namespace
8008 * @name: the type short name.
8010 * Obtains a MonoClass with a given namespace and a given name which
8011 * is located in the given MonoImage.
8013 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
8014 * set if the class was not found or it will return NULL and set the error if there was a loading error.
8017 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8020 GHashTable *visited_images;
8022 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8024 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
8026 g_hash_table_destroy (visited_images);
8032 * mono_class_from_name:
8033 * @image: The MonoImage where the type is looked up in
8034 * @name_space: the type namespace
8035 * @name: the type short name.
8037 * Obtains a MonoClass with a given namespace and a given name which
8038 * is located in the given MonoImage.
8040 * To reference nested classes, use the "/" character as a separator.
8041 * For example use "Foo/Bar" to reference the class Bar that is nested
8042 * inside Foo, like this: "class Foo { class Bar {} }".
8045 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8050 klass = mono_class_from_name_checked (image, name_space, name, &error);
8051 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8057 * mono_class_load_from_name:
8058 * @image: The MonoImage where the type is looked up in
8059 * @name_space: the type namespace
8060 * @name: the type short name.
8062 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8063 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8064 * If they are missing. Thing of System.Object or System.String.
8067 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8072 klass = mono_class_from_name_checked (image, name_space, name, &error);
8074 g_error ("Runtime critical type %s.%s not found", name_space, name);
8075 if (!mono_error_ok (&error))
8076 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8081 * mono_class_try_load_from_name:
8082 * @image: The MonoImage where the type is looked up in
8083 * @name_space: the type namespace
8084 * @name: the type short name.
8086 * This function tries to load a type, returning the class was found or NULL otherwise.
8087 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8089 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8090 * a type that we would otherwise assume to be available but was not due some error.
8094 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8099 klass = mono_class_from_name_checked (image, name_space, name, &error);
8100 if (!mono_error_ok (&error))
8101 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8107 * mono_class_is_subclass_of:
8108 * @klass: class to probe if it is a subclass of another one
8109 * @klassc: the class we suspect is the base class
8110 * @check_interfaces: whether we should perform interface checks
8112 * This method determines whether @klass is a subclass of @klassc.
8114 * If the @check_interfaces flag is set, then if @klassc is an interface
8115 * this method return TRUE if the @klass implements the interface or
8116 * if @klass is an interface, if one of its base classes is @klass.
8118 * If @check_interfaces is false then, then if @klass is not an interface
8119 * then it returns TRUE if the @klass is a subclass of @klassc.
8121 * if @klass is an interface and @klassc is System.Object, then this function
8126 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8127 gboolean check_interfaces)
8129 /* FIXME test for interfaces with variant generic arguments */
8130 mono_class_init (klass);
8131 mono_class_init (klassc);
8133 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8134 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8136 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8139 for (i = 0; i < klass->interface_count; i ++) {
8140 MonoClass *ic = klass->interfaces [i];
8145 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8150 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8153 if (klassc == mono_defaults.object_class)
8160 mono_type_is_generic_argument (MonoType *type)
8162 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8166 mono_class_has_variant_generic_params (MonoClass *klass)
8169 MonoGenericContainer *container;
8171 if (!mono_class_is_ginst (klass))
8174 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8176 for (i = 0; i < container->type_argc; ++i)
8177 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8184 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8186 if (target == candidate)
8189 if (check_for_reference_conv &&
8190 mono_type_is_generic_argument (&target->byval_arg) &&
8191 mono_type_is_generic_argument (&candidate->byval_arg)) {
8192 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8193 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8195 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8198 if (!mono_class_is_assignable_from (target, candidate))
8204 * @container the generic container from the GTD
8205 * @klass: the class to be assigned to
8206 * @oklass: the source class
8208 * Both @klass and @oklass must be instances of the same generic interface.
8210 * Returns: TRUE if @klass can be assigned to a @klass variable
8213 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8216 MonoType **klass_argv, **oklass_argv;
8217 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8218 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8220 if (klass == oklass)
8223 /*Viable candidates are instances of the same generic interface*/
8224 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8227 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8228 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8230 for (j = 0; j < container->type_argc; ++j) {
8231 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8232 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8234 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8238 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8239 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8241 if (param1_class != param2_class) {
8242 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8243 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8245 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8246 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8256 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8258 MonoGenericParam *gparam, *ogparam;
8259 MonoGenericParamInfo *tinfo, *cinfo;
8260 MonoClass **candidate_class;
8261 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8264 if (target == candidate)
8266 if (target->byval_arg.type != candidate->byval_arg.type)
8269 gparam = target->byval_arg.data.generic_param;
8270 ogparam = candidate->byval_arg.data.generic_param;
8271 tinfo = mono_generic_param_info (gparam);
8272 cinfo = mono_generic_param_info (ogparam);
8274 class_constraint_satisfied = FALSE;
8275 valuetype_constraint_satisfied = FALSE;
8277 /*candidate must have a super set of target's special constraints*/
8278 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8279 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8281 if (cinfo->constraints) {
8282 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8283 MonoClass *cc = *candidate_class;
8285 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8286 class_constraint_satisfied = TRUE;
8287 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8288 valuetype_constraint_satisfied = TRUE;
8291 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8292 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8294 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8296 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8298 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8299 valuetype_constraint_satisfied)) {
8304 /*candidate type constraints must be a superset of target's*/
8305 if (tinfo->constraints) {
8306 MonoClass **target_class;
8307 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8308 MonoClass *tc = *target_class;
8311 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8312 * check it's constraints since it satisfy the constraint by itself.
8314 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8317 if (!cinfo->constraints)
8320 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8321 MonoClass *cc = *candidate_class;
8323 if (mono_class_is_assignable_from (tc, cc))
8327 * This happens when we have the following:
8329 * Bar<K> where K : IFace
8330 * Foo<T, U> where T : U where U : IFace
8332 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8335 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8336 if (mono_gparam_is_assignable_from (target, cc))
8340 if (!*candidate_class)
8345 /*candidate itself must have a constraint that satisfy target*/
8346 if (cinfo->constraints) {
8347 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8348 MonoClass *cc = *candidate_class;
8349 if (mono_class_is_assignable_from (target, cc))
8357 * mono_class_is_assignable_from:
8358 * @klass: the class to be assigned to
8359 * @oklass: the source class
8361 * Returns: TRUE if an instance of object oklass can be assigned to an
8362 * instance of object @klass
8365 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8368 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8370 mono_class_init (klass);
8372 if (!oklass->inited)
8373 mono_class_init (oklass);
8375 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8378 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8379 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8381 return mono_gparam_is_assignable_from (klass, oklass);
8384 if (MONO_CLASS_IS_INTERFACE (klass)) {
8385 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8386 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8387 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8391 for (i = 0; constraints [i]; ++i) {
8392 if (mono_class_is_assignable_from (klass, constraints [i]))
8400 /* interface_offsets might not be set for dynamic classes */
8401 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8403 * oklass might be a generic type parameter but they have
8404 * interface_offsets set.
8406 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8407 if (!is_ok (&error)) {
8408 mono_error_cleanup (&error);
8413 if (!oklass->interface_bitmap)
8414 /* Happens with generic instances of not-yet created dynamic types */
8416 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8419 if (mono_class_has_variant_generic_params (klass)) {
8421 mono_class_setup_interfaces (oklass, &error);
8422 if (!mono_error_ok (&error)) {
8423 mono_error_cleanup (&error);
8427 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8428 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8429 MonoClass *iface = oklass->interfaces_packed [i];
8431 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8436 } else if (klass->delegate) {
8437 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8439 }else if (klass->rank) {
8440 MonoClass *eclass, *eoclass;
8442 if (oklass->rank != klass->rank)
8445 /* vectors vs. one dimensional arrays */
8446 if (oklass->byval_arg.type != klass->byval_arg.type)
8449 eclass = klass->cast_class;
8450 eoclass = oklass->cast_class;
8453 * a is b does not imply a[] is b[] when a is a valuetype, and
8454 * b is a reference type.
8457 if (eoclass->valuetype) {
8458 if ((eclass == mono_defaults.enum_class) ||
8459 (eclass == mono_defaults.enum_class->parent) ||
8460 (eclass == mono_defaults.object_class))
8464 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8465 } else if (mono_class_is_nullable (klass)) {
8466 if (mono_class_is_nullable (oklass))
8467 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8469 return mono_class_is_assignable_from (klass->cast_class, oklass);
8470 } else if (klass == mono_defaults.object_class)
8473 return mono_class_has_parent (oklass, klass);
8476 /*Check if @oklass is variant compatible with @klass.*/
8478 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8481 MonoType **klass_argv, **oklass_argv;
8482 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8483 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8485 /*Viable candidates are instances of the same generic interface*/
8486 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8489 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8490 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8492 for (j = 0; j < container->type_argc; ++j) {
8493 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8494 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8496 if (param1_class->valuetype != param2_class->valuetype)
8500 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8501 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8503 if (param1_class != param2_class) {
8504 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8505 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8507 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8508 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8516 /*Check if @candidate implements the interface @target*/
8518 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8522 gboolean is_variant = mono_class_has_variant_generic_params (target);
8524 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8525 if (mono_class_is_variant_compatible_slow (target, candidate))
8530 if (candidate == target)
8533 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8534 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8535 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8537 if (tb && tb->interfaces) {
8538 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8539 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8540 MonoClass *iface_class;
8542 /* we can't realize the type here since it can do pretty much anything. */
8545 iface_class = mono_class_from_mono_type (iface->type);
8546 if (iface_class == target)
8548 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8550 if (mono_class_implement_interface_slow (target, iface_class))
8555 /*setup_interfaces don't mono_class_init anything*/
8556 /*FIXME this doesn't handle primitive type arrays.
8557 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8558 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8560 mono_class_setup_interfaces (candidate, &error);
8561 if (!mono_error_ok (&error)) {
8562 mono_error_cleanup (&error);
8566 for (i = 0; i < candidate->interface_count; ++i) {
8567 if (candidate->interfaces [i] == target)
8570 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8573 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8577 candidate = candidate->parent;
8578 } while (candidate);
8584 * Check if @oklass can be assigned to @klass.
8585 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8588 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8590 if (candidate == target)
8592 if (target == mono_defaults.object_class)
8595 if (mono_class_has_parent (candidate, target))
8598 /*If target is not an interface there is no need to check them.*/
8599 if (MONO_CLASS_IS_INTERFACE (target))
8600 return mono_class_implement_interface_slow (target, candidate);
8602 if (target->delegate && mono_class_has_variant_generic_params (target))
8603 return mono_class_is_variant_compatible (target, candidate, FALSE);
8606 MonoClass *eclass, *eoclass;
8608 if (target->rank != candidate->rank)
8611 /* vectors vs. one dimensional arrays */
8612 if (target->byval_arg.type != candidate->byval_arg.type)
8615 eclass = target->cast_class;
8616 eoclass = candidate->cast_class;
8619 * a is b does not imply a[] is b[] when a is a valuetype, and
8620 * b is a reference type.
8623 if (eoclass->valuetype) {
8624 if ((eclass == mono_defaults.enum_class) ||
8625 (eclass == mono_defaults.enum_class->parent) ||
8626 (eclass == mono_defaults.object_class))
8630 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8632 /*FIXME properly handle nullables */
8633 /*FIXME properly handle (M)VAR */
8638 * mono_class_get_cctor:
8639 * @klass: A MonoClass pointer
8641 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8644 mono_class_get_cctor (MonoClass *klass)
8646 MonoCachedClassInfo cached_info;
8648 if (image_is_dynamic (klass->image)) {
8650 * has_cctor is not set for these classes because mono_class_init () is
8653 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8656 if (!klass->has_cctor)
8659 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8661 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8662 if (!mono_error_ok (&error))
8663 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8667 if (mono_class_is_ginst (klass) && !klass->methods)
8668 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8670 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8674 * mono_class_get_finalizer:
8675 * @klass: The MonoClass pointer
8677 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8680 mono_class_get_finalizer (MonoClass *klass)
8682 MonoCachedClassInfo cached_info;
8685 mono_class_init (klass);
8686 if (!mono_class_has_finalizer (klass))
8689 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8691 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8692 if (!mono_error_ok (&error))
8693 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8696 mono_class_setup_vtable (klass);
8697 return klass->vtable [finalize_slot];
8702 * mono_class_needs_cctor_run:
8703 * @klass: the MonoClass pointer
8704 * @caller: a MonoMethod describing the caller
8706 * Determines whenever the class has a static constructor and whenever it
8707 * needs to be called when executing CALLER.
8710 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8714 method = mono_class_get_cctor (klass);
8716 return (method == caller) ? FALSE : TRUE;
8722 * mono_class_array_element_size:
8725 * Returns: The number of bytes an element of type @klass
8726 * uses when stored into an array.
8729 mono_class_array_element_size (MonoClass *klass)
8731 MonoType *type = &klass->byval_arg;
8734 switch (type->type) {
8737 case MONO_TYPE_BOOLEAN:
8741 case MONO_TYPE_CHAR:
8750 case MONO_TYPE_CLASS:
8751 case MONO_TYPE_STRING:
8752 case MONO_TYPE_OBJECT:
8753 case MONO_TYPE_SZARRAY:
8754 case MONO_TYPE_ARRAY:
8755 return sizeof (gpointer);
8760 case MONO_TYPE_VALUETYPE:
8761 if (type->data.klass->enumtype) {
8762 type = mono_class_enum_basetype (type->data.klass);
8763 klass = klass->element_class;
8766 return mono_class_instance_size (klass) - sizeof (MonoObject);
8767 case MONO_TYPE_GENERICINST:
8768 type = &type->data.generic_class->container_class->byval_arg;
8771 case MONO_TYPE_MVAR: {
8774 return mono_type_size (type, &align);
8776 case MONO_TYPE_VOID:
8780 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8786 * mono_array_element_size:
8787 * @ac: pointer to a #MonoArrayClass
8789 * Returns: The size of single array element.
8792 mono_array_element_size (MonoClass *ac)
8794 g_assert (ac->rank);
8795 return ac->sizes.element_size;
8799 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8800 MonoGenericContext *context)
8803 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8804 g_assert (mono_error_ok (&error));
8809 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8810 MonoGenericContext *context, MonoError *error)
8812 mono_error_init (error);
8814 if (image_is_dynamic (image)) {
8815 MonoClass *tmp_handle_class;
8816 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8818 mono_error_assert_ok (error);
8819 g_assert (tmp_handle_class);
8821 *handle_class = tmp_handle_class;
8823 if (tmp_handle_class == mono_defaults.typehandle_class)
8824 return &((MonoClass*)obj)->byval_arg;
8829 switch (token & 0xff000000) {
8830 case MONO_TOKEN_TYPE_DEF:
8831 case MONO_TOKEN_TYPE_REF:
8832 case MONO_TOKEN_TYPE_SPEC: {
8835 *handle_class = mono_defaults.typehandle_class;
8836 type = mono_type_get_checked (image, token, context, error);
8840 mono_class_init (mono_class_from_mono_type (type));
8841 /* We return a MonoType* as handle */
8844 case MONO_TOKEN_FIELD_DEF: {
8846 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8848 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8852 *handle_class = mono_defaults.fieldhandle_class;
8853 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8857 mono_class_init (klass);
8858 return mono_class_get_field (klass, token);
8860 case MONO_TOKEN_METHOD_DEF:
8861 case MONO_TOKEN_METHOD_SPEC: {
8863 meth = mono_get_method_checked (image, token, NULL, context, error);
8865 *handle_class = mono_defaults.methodhandle_class;
8871 case MONO_TOKEN_MEMBER_REF: {
8872 guint32 cols [MONO_MEMBERREF_SIZE];
8874 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8875 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8876 mono_metadata_decode_blob_size (sig, &sig);
8877 if (*sig == 0x6) { /* it's a field */
8879 MonoClassField *field;
8880 field = mono_field_from_token_checked (image, token, &klass, context, error);
8882 *handle_class = mono_defaults.fieldhandle_class;
8886 meth = mono_get_method_checked (image, token, NULL, context, error);
8888 *handle_class = mono_defaults.methodhandle_class;
8893 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8899 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8901 MonoClass *handle_class;
8902 mono_error_init (error);
8903 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8907 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8909 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8912 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8915 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8917 get_cached_class_info = func;
8921 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8923 if (!get_cached_class_info)
8926 return get_cached_class_info (klass, res);
8930 mono_install_get_class_from_name (MonoGetClassFromName func)
8932 get_class_from_name = func;
8936 * mono_class_get_image:
8938 * Use this method to get the `MonoImage*` where this class came from.
8940 * Returns: The image where this class is defined.
8943 mono_class_get_image (MonoClass *klass)
8945 return klass->image;
8949 * mono_class_get_element_class:
8950 * @klass: the MonoClass to act on
8952 * Use this function to get the element class of an array.
8954 * Returns: The element class of an array.
8957 mono_class_get_element_class (MonoClass *klass)
8959 return klass->element_class;
8963 * mono_class_is_valuetype:
8964 * @klass: the MonoClass to act on
8966 * Use this method to determine if the provided `MonoClass*` represents a value type,
8967 * or a reference type.
8969 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8972 mono_class_is_valuetype (MonoClass *klass)
8974 return klass->valuetype;
8978 * mono_class_is_enum:
8979 * @klass: the MonoClass to act on
8981 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8983 * Returns: TRUE if the MonoClass represents an enumeration.
8986 mono_class_is_enum (MonoClass *klass)
8988 return klass->enumtype;
8992 * mono_class_enum_basetype:
8993 * @klass: the MonoClass to act on
8995 * Use this function to get the underlying type for an enumeration value.
8997 * Returns: The underlying type representation for an enumeration.
9000 mono_class_enum_basetype (MonoClass *klass)
9002 if (klass->element_class == klass)
9003 /* SRE or broken types */
9006 return &klass->element_class->byval_arg;
9010 * mono_class_get_parent
9011 * @klass: the MonoClass to act on
9013 * Returns: The parent class for this class.
9016 mono_class_get_parent (MonoClass *klass)
9018 return klass->parent;
9022 * mono_class_get_nesting_type:
9023 * @klass: the MonoClass to act on
9025 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9027 * If the return is NULL, this indicates that this class is not nested.
9029 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9032 mono_class_get_nesting_type (MonoClass *klass)
9034 return klass->nested_in;
9038 * mono_class_get_rank:
9039 * @klass: the MonoClass to act on
9041 * Returns: The rank for the array (the number of dimensions).
9044 mono_class_get_rank (MonoClass *klass)
9050 * mono_class_get_name
9051 * @klass: the MonoClass to act on
9053 * Returns: The name of the class.
9056 mono_class_get_name (MonoClass *klass)
9062 * mono_class_get_namespace:
9063 * @klass: the MonoClass to act on
9065 * Returns: The namespace of the class.
9068 mono_class_get_namespace (MonoClass *klass)
9070 return klass->name_space;
9074 * mono_class_get_type:
9075 * @klass: the MonoClass to act on
9077 * This method returns the internal Type representation for the class.
9079 * Returns: The MonoType from the class.
9082 mono_class_get_type (MonoClass *klass)
9084 return &klass->byval_arg;
9088 * mono_class_get_type_token:
9089 * @klass: the MonoClass to act on
9091 * This method returns type token for the class.
9093 * Returns: The type token for the class.
9096 mono_class_get_type_token (MonoClass *klass)
9098 return klass->type_token;
9102 * mono_class_get_byref_type:
9103 * @klass: the MonoClass to act on
9108 mono_class_get_byref_type (MonoClass *klass)
9110 return &klass->this_arg;
9114 * mono_class_num_fields:
9115 * @klass: the MonoClass to act on
9117 * Returns: The number of static and instance fields in the class.
9120 mono_class_num_fields (MonoClass *klass)
9122 return mono_class_get_field_count (klass);
9126 * mono_class_num_methods:
9127 * @klass: the MonoClass to act on
9129 * Returns: The number of methods in the class.
9132 mono_class_num_methods (MonoClass *klass)
9134 return mono_class_get_method_count (klass);
9138 * mono_class_num_properties
9139 * @klass: the MonoClass to act on
9141 * Returns: The number of properties in the class.
9144 mono_class_num_properties (MonoClass *klass)
9146 mono_class_setup_properties (klass);
9148 return mono_class_get_ext (klass)->property.count;
9152 * mono_class_num_events:
9153 * @klass: the MonoClass to act on
9155 * Returns: The number of events in the class.
9158 mono_class_num_events (MonoClass *klass)
9160 mono_class_setup_events (klass);
9162 return mono_class_get_ext (klass)->event.count;
9166 * mono_class_get_fields:
9167 * @klass: the MonoClass to act on
9169 * This routine is an iterator routine for retrieving the fields in a class.
9171 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9172 * iterate over all of the elements. When no more values are
9173 * available, the return value is NULL.
9175 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9178 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9180 MonoClassField* field;
9184 mono_class_setup_fields (klass);
9185 if (mono_class_has_failure (klass))
9187 /* start from the first */
9188 if (mono_class_get_field_count (klass)) {
9189 *iter = &klass->fields [0];
9190 return &klass->fields [0];
9196 field = (MonoClassField *)*iter;
9198 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9206 * mono_class_get_methods
9207 * @klass: the MonoClass to act on
9209 * This routine is an iterator routine for retrieving the fields in a class.
9211 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9212 * iterate over all of the elements. When no more values are
9213 * available, the return value is NULL.
9215 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9218 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9220 MonoMethod** method;
9224 mono_class_setup_methods (klass);
9227 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9228 * FIXME we should better report this error to the caller
9230 if (!klass->methods)
9232 /* start from the first */
9233 if (mono_class_get_method_count (klass)) {
9234 *iter = &klass->methods [0];
9235 return klass->methods [0];
9241 method = (MonoMethod **)*iter;
9243 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9251 * mono_class_get_virtual_methods:
9253 * Iterate over the virtual methods of KLASS.
9255 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9258 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9260 MonoMethod** method;
9263 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9265 mono_class_setup_methods (klass);
9267 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9268 * FIXME we should better report this error to the caller
9270 if (!klass->methods)
9272 /* start from the first */
9273 method = &klass->methods [0];
9275 method = (MonoMethod **)*iter;
9278 int mcount = mono_class_get_method_count (klass);
9279 while (method < &klass->methods [mcount]) {
9280 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9284 if (method < &klass->methods [mcount]) {
9291 /* Search directly in metadata to avoid calling setup_methods () */
9292 MonoMethod *res = NULL;
9298 start_index = GPOINTER_TO_UINT (*iter);
9301 int first_idx = mono_class_get_first_method_idx (klass);
9302 int mcount = mono_class_get_method_count (klass);
9303 for (i = start_index; i < mcount; ++i) {
9306 /* first_idx points into the methodptr table */
9307 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9309 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9315 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9316 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9318 /* Add 1 here so the if (*iter) check fails */
9319 *iter = GUINT_TO_POINTER (i + 1);
9328 * mono_class_get_properties:
9329 * @klass: the MonoClass to act on
9331 * This routine is an iterator routine for retrieving the properties in a class.
9333 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9334 * iterate over all of the elements. When no more values are
9335 * available, the return value is NULL.
9337 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9340 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9342 MonoProperty* property;
9346 mono_class_setup_properties (klass);
9347 MonoClassExt *ext = mono_class_get_ext (klass);
9348 /* start from the first */
9349 if (ext->property.count) {
9350 *iter = &ext->properties [0];
9351 return (MonoProperty *)*iter;
9357 property = (MonoProperty *)*iter;
9359 MonoClassExt *ext = mono_class_get_ext (klass);
9360 if (property < &ext->properties [ext->property.count]) {
9362 return (MonoProperty *)*iter;
9368 * mono_class_get_events:
9369 * @klass: the MonoClass to act on
9371 * This routine is an iterator routine for retrieving the properties in a class.
9373 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9374 * iterate over all of the elements. When no more values are
9375 * available, the return value is NULL.
9377 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9380 mono_class_get_events (MonoClass* klass, gpointer *iter)
9386 mono_class_setup_events (klass);
9387 MonoClassExt *ext = mono_class_get_ext (klass);
9388 /* start from the first */
9389 if (ext->event.count) {
9390 *iter = &ext->events [0];
9391 return (MonoEvent *)*iter;
9397 event = (MonoEvent *)*iter;
9399 MonoClassExt *ext = mono_class_get_ext (klass);
9400 if (event < &ext->events [ext->event.count]) {
9402 return (MonoEvent *)*iter;
9408 * mono_class_get_interfaces
9409 * @klass: the MonoClass to act on
9411 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9413 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9414 * iterate over all of the elements. When no more values are
9415 * available, the return value is NULL.
9417 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9420 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9428 mono_class_init (klass);
9429 if (!klass->interfaces_inited) {
9430 mono_class_setup_interfaces (klass, &error);
9431 if (!mono_error_ok (&error)) {
9432 mono_error_cleanup (&error);
9436 /* start from the first */
9437 if (klass->interface_count) {
9438 *iter = &klass->interfaces [0];
9439 return klass->interfaces [0];
9445 iface = (MonoClass **)*iter;
9447 if (iface < &klass->interfaces [klass->interface_count]) {
9455 setup_nested_types (MonoClass *klass)
9458 GList *classes, *nested_classes, *l;
9461 if (klass->nested_classes_inited)
9464 if (!klass->type_token)
9465 klass->nested_classes_inited = TRUE;
9467 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9471 guint32 cols [MONO_NESTED_CLASS_SIZE];
9472 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9473 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9474 if (!mono_error_ok (&error)) {
9475 /*FIXME don't swallow the error message*/
9476 mono_error_cleanup (&error);
9478 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9482 classes = g_list_prepend (classes, nclass);
9484 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9487 mono_class_alloc_ext (klass);
9489 nested_classes = NULL;
9490 for (l = classes; l; l = l->next)
9491 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9492 g_list_free (classes);
9494 mono_image_lock (klass->image);
9496 mono_memory_barrier ();
9497 if (!klass->nested_classes_inited) {
9498 mono_class_get_ext (klass)->nested_classes = nested_classes;
9499 mono_memory_barrier ();
9500 klass->nested_classes_inited = TRUE;
9503 mono_image_unlock (klass->image);
9507 * mono_class_get_nested_types
9508 * @klass: the MonoClass to act on
9510 * This routine is an iterator routine for retrieving the nested types of a class.
9511 * This works only if @klass is non-generic, or a generic type definition.
9513 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9514 * iterate over all of the elements. When no more values are
9515 * available, the return value is NULL.
9517 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9520 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9526 if (!klass->nested_classes_inited)
9527 setup_nested_types (klass);
9530 MonoClassExt *ext = mono_class_get_ext (klass);
9531 /* start from the first */
9532 if (ext && ext->nested_classes) {
9533 *iter = ext->nested_classes;
9534 return (MonoClass *)ext->nested_classes->data;
9536 /* no nested types */
9540 item = (GList *)*iter;
9544 return (MonoClass *)item->data;
9551 * mono_class_is_delegate
9552 * @klass: the MonoClass to act on
9554 * Returns: TRUE if the MonoClass represents a System.Delegate.
9557 mono_class_is_delegate (MonoClass *klass)
9559 return klass->delegate;
9563 * mono_class_implements_interface
9564 * @klass: The MonoClass to act on
9565 * @interface: The interface to check if @klass implements.
9567 * Returns: TRUE if @klass implements @interface.
9570 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9572 return mono_class_is_assignable_from (iface, klass);
9576 * mono_field_get_name:
9577 * @field: the MonoClassField to act on
9579 * Returns: The name of the field.
9582 mono_field_get_name (MonoClassField *field)
9588 * mono_field_get_type:
9589 * @field: the MonoClassField to act on
9591 * Returns: MonoType of the field.
9594 mono_field_get_type (MonoClassField *field)
9597 MonoType *type = mono_field_get_type_checked (field, &error);
9598 if (!mono_error_ok (&error)) {
9599 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9600 mono_error_cleanup (&error);
9607 * mono_field_get_type_checked:
9608 * @field: the MonoClassField to act on
9609 * @error: used to return any erro found while retrieving @field type
9611 * Returns: MonoType of the field.
9614 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9616 mono_error_init (error);
9618 mono_field_resolve_type (field, error);
9623 * mono_field_get_parent:
9624 * @field: the MonoClassField to act on
9626 * Returns: MonoClass where the field was defined.
9629 mono_field_get_parent (MonoClassField *field)
9631 return field->parent;
9635 * mono_field_get_flags;
9636 * @field: the MonoClassField to act on
9638 * The metadata flags for a field are encoded using the
9639 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9641 * Returns: The flags for the field.
9644 mono_field_get_flags (MonoClassField *field)
9647 return mono_field_resolve_flags (field);
9648 return field->type->attrs;
9652 * mono_field_get_offset:
9653 * @field: the MonoClassField to act on
9655 * Returns: The field offset.
9658 mono_field_get_offset (MonoClassField *field)
9660 return field->offset;
9664 mono_field_get_rva (MonoClassField *field)
9668 MonoClass *klass = field->parent;
9669 MonoFieldDefaultValue *field_def_values;
9671 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9673 MonoClassExt *ext = mono_class_get_ext (klass);
9674 if (!ext || !ext->field_def_values) {
9675 mono_class_alloc_ext (klass);
9676 ext = mono_class_get_ext (klass);
9678 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9680 mono_image_lock (klass->image);
9681 if (!ext->field_def_values)
9682 ext->field_def_values = field_def_values;
9683 mono_image_unlock (klass->image);
9686 field_index = mono_field_get_index (field);
9688 if (!ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9689 int first_field_idx = mono_class_get_first_field_idx (klass);
9690 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9692 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9693 ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9696 return ext->field_def_values [field_index].data;
9700 * mono_field_get_data:
9701 * @field: the MonoClassField to act on
9703 * Returns: A pointer to the metadata constant value or to the field
9704 * data if it has an RVA flag.
9707 mono_field_get_data (MonoClassField *field)
9709 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9710 MonoTypeEnum def_type;
9712 return mono_class_get_field_default_value (field, &def_type);
9713 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9714 return mono_field_get_rva (field);
9721 * mono_property_get_name:
9722 * @prop: the MonoProperty to act on
9724 * Returns: The name of the property
9727 mono_property_get_name (MonoProperty *prop)
9733 * mono_property_get_set_method
9734 * @prop: the MonoProperty to act on.
9736 * Returns: The setter method of the property (A MonoMethod)
9739 mono_property_get_set_method (MonoProperty *prop)
9745 * mono_property_get_get_method
9746 * @prop: the MonoProperty to act on.
9748 * Returns: The setter method of the property (A MonoMethod)
9751 mono_property_get_get_method (MonoProperty *prop)
9757 * mono_property_get_parent:
9758 * @prop: the MonoProperty to act on.
9760 * Returns: The MonoClass where the property was defined.
9763 mono_property_get_parent (MonoProperty *prop)
9765 return prop->parent;
9769 * mono_property_get_flags:
9770 * @prop: the MonoProperty to act on.
9772 * The metadata flags for a property are encoded using the
9773 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9775 * Returns: The flags for the property.
9778 mono_property_get_flags (MonoProperty *prop)
9784 * mono_event_get_name:
9785 * @event: the MonoEvent to act on
9787 * Returns: The name of the event.
9790 mono_event_get_name (MonoEvent *event)
9796 * mono_event_get_add_method:
9797 * @event: The MonoEvent to act on.
9799 * Returns: The @add' method for the event (a MonoMethod).
9802 mono_event_get_add_method (MonoEvent *event)
9808 * mono_event_get_remove_method:
9809 * @event: The MonoEvent to act on.
9811 * Returns: The @remove method for the event (a MonoMethod).
9814 mono_event_get_remove_method (MonoEvent *event)
9816 return event->remove;
9820 * mono_event_get_raise_method:
9821 * @event: The MonoEvent to act on.
9823 * Returns: The @raise method for the event (a MonoMethod).
9826 mono_event_get_raise_method (MonoEvent *event)
9828 return event->raise;
9832 * mono_event_get_parent:
9833 * @event: the MonoEvent to act on.
9835 * Returns: The MonoClass where the event is defined.
9838 mono_event_get_parent (MonoEvent *event)
9840 return event->parent;
9844 * mono_event_get_flags
9845 * @event: the MonoEvent to act on.
9847 * The metadata flags for an event are encoded using the
9848 * EVENT_* constants. See the tabledefs.h file for details.
9850 * Returns: The flags for the event.
9853 mono_event_get_flags (MonoEvent *event)
9855 return event->attrs;
9859 * mono_class_get_method_from_name:
9860 * @klass: where to look for the method
9861 * @name: name of the method
9862 * @param_count: number of parameters. -1 for any number.
9864 * Obtains a MonoMethod with a given name and number of parameters.
9865 * It only works if there are no multiple signatures for any given method name.
9868 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9870 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9874 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9876 MonoMethod *res = NULL;
9879 /* Search directly in the metadata to avoid calling setup_methods () */
9880 int first_idx = mono_class_get_first_method_idx (klass);
9881 int mcount = mono_class_get_method_count (klass);
9882 for (i = 0; i < mcount; ++i) {
9884 guint32 cols [MONO_METHOD_SIZE];
9886 MonoMethodSignature *sig;
9888 /* first_idx points into the methodptr table */
9889 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9891 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9892 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9894 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9897 if (param_count == -1) {
9901 sig = mono_method_signature_checked (method, &error);
9903 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9906 if (sig->param_count == param_count) {
9917 * mono_class_get_method_from_name_flags:
9918 * @klass: where to look for the method
9919 * @name_space: name of the method
9920 * @param_count: number of parameters. -1 for any number.
9921 * @flags: flags which must be set in the method
9923 * Obtains a MonoMethod with a given name and number of parameters.
9924 * It only works if there are no multiple signatures for any given method name.
9927 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9929 MonoMethod *res = NULL;
9932 mono_class_init (klass);
9934 if (mono_class_is_ginst (klass) && !klass->methods) {
9935 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9938 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9939 if (!mono_error_ok (&error))
9940 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9945 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9946 mono_class_setup_methods (klass);
9948 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9949 See mono/tests/array_load_exception.il
9950 FIXME we should better report this error to the caller
9952 if (!klass->methods)
9954 int mcount = mono_class_get_method_count (klass);
9955 for (i = 0; i < mcount; ++i) {
9956 MonoMethod *method = klass->methods [i];
9958 if (method->name[0] == name [0] &&
9959 !strcmp (name, method->name) &&
9960 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9961 ((method->flags & flags) == flags)) {
9968 res = find_method_in_metadata (klass, name, param_count, flags);
9975 * mono_class_set_failure:
9976 * @klass: class in which the failure was detected
9977 * @ex_type: the kind of exception/error to be thrown (later)
9978 * @ex_data: exception data (specific to each type of exception/error)
9980 * Keep a detected failure informations in the class for later processing.
9981 * Note that only the first failure is kept.
9983 * LOCKING: Acquires the loader lock.
9986 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9988 g_assert (boxed_error != NULL);
9990 if (mono_class_has_failure (klass))
9993 mono_loader_lock ();
9994 klass->has_failure = 1;
9995 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9996 mono_loader_unlock ();
10002 mono_class_has_failure (const MonoClass *klass)
10004 g_assert (klass != NULL);
10005 return klass->has_failure != 0;
10010 * mono_class_set_type_load_failure:
10011 * @klass: class in which the failure was detected
10012 * @fmt: Printf-style error message string.
10014 * Collect detected failure informaion in the class for later processing.
10015 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
10016 * Note that only the first failure is kept.
10018 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
10020 * LOCKING: Acquires the loader lock.
10023 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
10025 MonoError prepare_error;
10028 if (mono_class_has_failure (klass))
10031 mono_error_init (&prepare_error);
10033 va_start (args, fmt);
10034 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
10037 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
10038 mono_error_cleanup (&prepare_error);
10039 return mono_class_set_failure (klass, box);
10043 * mono_class_get_exception_data:
10045 * Return the exception_data property of KLASS.
10047 * LOCKING: Acquires the loader lock.
10050 mono_class_get_exception_data (const MonoClass *klass)
10052 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10056 * mono_classes_init:
10058 * Initialize the resources used by this module.
10061 mono_classes_init (void)
10063 mono_os_mutex_init (&classes_mutex);
10065 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10066 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10068 mono_counters_register ("MonoClassDef count",
10069 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
10070 mono_counters_register ("MonoClassGtd count",
10071 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
10072 mono_counters_register ("MonoClassGenericInst count",
10073 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
10074 mono_counters_register ("MonoClassGenericParam count",
10075 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
10076 mono_counters_register ("MonoClassArray count",
10077 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
10078 mono_counters_register ("MonoClassPointer count",
10079 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
10080 mono_counters_register ("Inflated methods size",
10081 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10082 mono_counters_register ("Inflated classes size",
10083 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10084 mono_counters_register ("MonoClass size",
10085 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10086 mono_counters_register ("MonoClassExt size",
10087 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10089 mono_counters_register ("MonoClassExt count",
10090 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_count);
10094 * mono_classes_cleanup:
10096 * Free the resources used by this module.
10099 mono_classes_cleanup (void)
10101 mono_native_tls_free (setup_fields_tls_id);
10102 mono_native_tls_free (init_pending_tls_id);
10104 if (global_interface_bitset)
10105 mono_bitset_free (global_interface_bitset);
10106 global_interface_bitset = NULL;
10107 mono_os_mutex_destroy (&classes_mutex);
10111 * mono_class_get_exception_for_failure:
10112 * @klass: class in which the failure was detected
10114 * Return a constructed MonoException than the caller can then throw
10115 * using mono_raise_exception - or NULL if no failure is present (or
10116 * doesn't result in an exception).
10119 mono_class_get_exception_for_failure (MonoClass *klass)
10121 if (!mono_class_has_failure (klass))
10123 MonoError unboxed_error;
10124 mono_error_init (&unboxed_error);
10125 mono_error_set_for_class_failure (&unboxed_error, klass);
10126 return mono_error_convert_to_exception (&unboxed_error);
10130 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10132 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10133 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10135 if (outer_klass == inner_klass)
10137 inner_klass = inner_klass->nested_in;
10138 } while (inner_klass);
10143 mono_class_get_generic_type_definition (MonoClass *klass)
10145 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10146 return gklass ? gklass->container_class : klass;
10150 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10152 * Generic instantiations are ignored for all super types of @klass.
10154 * Visibility checks ignoring generic instantiations.
10157 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10160 klass = mono_class_get_generic_type_definition (klass);
10161 parent = mono_class_get_generic_type_definition (parent);
10162 mono_class_setup_supertypes (klass);
10164 for (i = 0; i < klass->idepth; ++i) {
10165 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10171 * Subtype can only access parent members with family protection if the site object
10172 * is subclass of Subtype. For example:
10173 * class A { protected int x; }
10175 * void valid_access () {
10179 * void invalid_access () {
10186 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10188 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10191 if (context_klass == NULL)
10193 /*if access_klass is not member_klass context_klass must be type compat*/
10194 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10200 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10203 if (accessing == accessed)
10205 if (!accessed || !accessing)
10208 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10209 * anywhere so untrusted friends are not safe to access platform's code internals */
10210 if (mono_security_core_clr_enabled ()) {
10211 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10215 mono_assembly_load_friends (accessed);
10216 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10217 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10218 /* Be conservative with checks */
10219 if (!friend_->name)
10221 if (strcmp (accessing->aname.name, friend_->name))
10223 if (friend_->public_key_token [0]) {
10224 if (!accessing->aname.public_key_token [0])
10226 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10235 * If klass is a generic type or if it is derived from a generic type, return the
10236 * MonoClass of the generic definition
10237 * Returns NULL if not found
10240 get_generic_definition_class (MonoClass *klass)
10243 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10244 if (gklass && gklass->container_class)
10245 return gklass->container_class;
10246 klass = klass->parent;
10252 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10255 for (i = 0; i < ginst->type_argc; ++i) {
10256 MonoType *type = ginst->type_argv[i];
10257 switch (type->type) {
10258 case MONO_TYPE_SZARRAY:
10259 if (!can_access_type (access_klass, type->data.klass))
10262 case MONO_TYPE_ARRAY:
10263 if (!can_access_type (access_klass, type->data.array->eklass))
10266 case MONO_TYPE_PTR:
10267 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10270 case MONO_TYPE_CLASS:
10271 case MONO_TYPE_VALUETYPE:
10272 case MONO_TYPE_GENERICINST:
10273 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10283 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10287 if (access_klass == member_klass)
10290 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10293 if (access_klass->element_class && !access_klass->enumtype)
10294 access_klass = access_klass->element_class;
10296 if (member_klass->element_class && !member_klass->enumtype)
10297 member_klass = member_klass->element_class;
10299 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10301 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10304 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10307 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10310 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10313 /*Non nested type with nested visibility. We just fail it.*/
10314 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10317 switch (access_level) {
10318 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10319 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10321 case TYPE_ATTRIBUTE_PUBLIC:
10324 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10327 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10328 return is_nesting_type (member_klass, access_klass);
10330 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10331 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10333 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10334 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10336 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10337 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10338 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10340 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10341 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10342 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10347 /* FIXME: check visibility of type, too */
10349 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10351 MonoClass *member_generic_def;
10352 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10355 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10356 if (((access_gklass && access_gklass->container_class) ||
10357 mono_class_is_gtd (access_klass)) &&
10358 (member_generic_def = get_generic_definition_class (member_klass))) {
10359 MonoClass *access_container;
10361 if (mono_class_is_gtd (access_klass))
10362 access_container = access_klass;
10364 access_container = access_gklass->container_class;
10366 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10370 /* Partition I 8.5.3.2 */
10371 /* the access level values are the same for fields and methods */
10372 switch (access_level) {
10373 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10374 /* same compilation unit */
10375 return access_klass->image == member_klass->image;
10376 case FIELD_ATTRIBUTE_PRIVATE:
10377 return access_klass == member_klass;
10378 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10379 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10380 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10383 case FIELD_ATTRIBUTE_ASSEMBLY:
10384 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10385 case FIELD_ATTRIBUTE_FAMILY:
10386 if (is_valid_family_access (access_klass, member_klass, context_klass))
10389 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10390 if (is_valid_family_access (access_klass, member_klass, context_klass))
10392 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10393 case FIELD_ATTRIBUTE_PUBLIC:
10400 * mono_method_can_access_field:
10401 * @method: Method that will attempt to access the field
10402 * @field: the field to access
10404 * Used to determine if a method is allowed to access the specified field.
10406 * Returns: TRUE if the given @method is allowed to access the @field while following
10407 * the accessibility rules of the CLI.
10410 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10412 /* FIXME: check all overlapping fields */
10413 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10415 MonoClass *nested = method->klass->nested_in;
10417 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10420 nested = nested->nested_in;
10427 * mono_method_can_access_method:
10428 * @method: Method that will attempt to access the other method
10429 * @called: the method that we want to probe for accessibility.
10431 * Used to determine if the @method is allowed to access the specified @called method.
10433 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10434 * the accessibility rules of the CLI.
10437 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10439 method = mono_method_get_method_definition (method);
10440 called = mono_method_get_method_definition (called);
10441 return mono_method_can_access_method_full (method, called, NULL);
10445 * mono_method_can_access_method_full:
10446 * @method: The caller method
10447 * @called: The called method
10448 * @context_klass: The static type on stack of the owner @called object used
10450 * This function must be used with instance calls, as they have more strict family accessibility.
10451 * It can be used with static methods, but context_klass should be NULL.
10453 * Returns: TRUE if caller have proper visibility and acessibility to @called
10456 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10458 /* Wrappers are except from access checks */
10459 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10462 MonoClass *access_class = method->klass;
10463 MonoClass *member_class = called->klass;
10464 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10466 MonoClass *nested = access_class->nested_in;
10468 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10471 nested = nested->nested_in;
10478 can = can_access_type (access_class, member_class);
10480 MonoClass *nested = access_class->nested_in;
10482 can = can_access_type (nested, member_class);
10485 nested = nested->nested_in;
10492 if (called->is_inflated) {
10493 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10494 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10503 * mono_method_can_access_field_full:
10504 * @method: The caller method
10505 * @field: The accessed field
10506 * @context_klass: The static type on stack of the owner @field object used
10508 * This function must be used with instance fields, as they have more strict family accessibility.
10509 * It can be used with static fields, but context_klass should be NULL.
10511 * Returns: TRUE if caller have proper visibility and acessibility to @field
10514 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10516 MonoClass *access_class = method->klass;
10517 MonoClass *member_class = field->parent;
10518 /* FIXME: check all overlapping fields */
10519 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10521 MonoClass *nested = access_class->nested_in;
10523 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10526 nested = nested->nested_in;
10533 can = can_access_type (access_class, member_class);
10535 MonoClass *nested = access_class->nested_in;
10537 can = can_access_type (nested, member_class);
10540 nested = nested->nested_in;
10550 * mono_class_can_access_class:
10551 * @source_class: The source class
10552 * @target_class: The accessed class
10554 * This function returns is @target_class is visible to @source_class
10556 * Returns: TRUE if source have proper visibility and acessibility to target
10559 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10561 return can_access_type (source_class, target_class);
10565 * mono_type_is_valid_enum_basetype:
10566 * @type: The MonoType to check
10568 * Returns: TRUE if the type can be used as the basetype of an enum
10570 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10571 switch (type->type) {
10574 case MONO_TYPE_BOOLEAN:
10577 case MONO_TYPE_CHAR:
10591 * mono_class_is_valid_enum:
10592 * @klass: An enum class to be validated
10594 * This method verify the required properties an enum should have.
10596 * Returns: TRUE if the informed enum class is valid
10598 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10599 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10600 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10603 mono_class_is_valid_enum (MonoClass *klass)
10605 MonoClassField * field;
10606 gpointer iter = NULL;
10607 gboolean found_base_field = FALSE;
10609 g_assert (klass->enumtype);
10610 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10611 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10615 if (!mono_class_is_auto_layout (klass))
10618 while ((field = mono_class_get_fields (klass, &iter))) {
10619 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10620 if (found_base_field)
10622 found_base_field = TRUE;
10623 if (!mono_type_is_valid_enum_basetype (field->type))
10628 if (!found_base_field)
10631 if (mono_class_get_method_count (klass) > 0)
10638 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10640 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10644 * mono_class_setup_interface_id:
10646 * Initializes MonoClass::interface_id if required.
10648 * LOCKING: Acquires the loader lock.
10651 mono_class_setup_interface_id (MonoClass *klass)
10653 mono_loader_lock ();
10654 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10655 klass->interface_id = mono_get_unique_iid (klass);
10656 mono_loader_unlock ();
10660 * mono_class_alloc_ext:
10662 * Allocate klass->ext if not already done.
10665 mono_class_alloc_ext (MonoClass *klass)
10669 if (mono_class_get_ext (klass))
10672 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10673 mono_image_lock (klass->image);
10674 mono_memory_barrier ();
10675 if (!mono_class_get_ext (klass))
10676 mono_class_set_ext (klass, ext);
10677 class_ext_size += sizeof (MonoClassExt);
10679 mono_image_unlock (klass->image);
10683 * mono_class_setup_interfaces:
10685 * Initialize klass->interfaces/interfaces_count.
10686 * LOCKING: Acquires the loader lock.
10687 * This function can fail the type.
10690 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10692 int i, interface_count;
10693 MonoClass **interfaces;
10695 mono_error_init (error);
10697 if (klass->interfaces_inited)
10700 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10701 MonoType *args [1];
10703 /* generic IList, ICollection, IEnumerable */
10704 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10705 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10707 args [0] = &klass->element_class->byval_arg;
10708 interfaces [0] = mono_class_bind_generic_parameters (
10709 mono_defaults.generic_ilist_class, 1, args, FALSE);
10710 if (interface_count > 1)
10711 interfaces [1] = mono_class_bind_generic_parameters (
10712 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10713 } else if (mono_class_is_ginst (klass)) {
10714 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10716 mono_class_setup_interfaces (gklass, error);
10717 if (!mono_error_ok (error)) {
10718 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10722 interface_count = gklass->interface_count;
10723 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10724 for (i = 0; i < interface_count; i++) {
10725 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10726 if (!mono_error_ok (error)) {
10727 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10732 interface_count = 0;
10736 mono_image_lock (klass->image);
10738 if (!klass->interfaces_inited) {
10739 klass->interface_count = interface_count;
10740 klass->interfaces = interfaces;
10742 mono_memory_barrier ();
10744 klass->interfaces_inited = TRUE;
10747 mono_image_unlock (klass->image);
10751 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10753 MonoClass *klass = field->parent;
10754 MonoImage *image = klass->image;
10755 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10757 int field_idx = field - klass->fields;
10759 mono_error_init (error);
10762 MonoClassField *gfield = >d->fields [field_idx];
10763 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10764 if (!mono_error_ok (error)) {
10765 char *full_name = mono_type_get_full_name (gtd);
10766 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));
10767 g_free (full_name);
10770 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10771 if (!mono_error_ok (error)) {
10772 char *full_name = mono_type_get_full_name (klass);
10773 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));
10774 g_free (full_name);
10778 guint32 cols [MONO_FIELD_SIZE];
10779 MonoGenericContainer *container = NULL;
10780 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10782 /*FIXME, in theory we do not lazy load SRE fields*/
10783 g_assert (!image_is_dynamic (image));
10785 if (mono_class_is_gtd (klass)) {
10786 container = mono_class_get_generic_container (klass);
10788 container = mono_class_get_generic_container (gtd);
10789 g_assert (container);
10792 /* first_field_idx and idx points into the fieldptr table */
10793 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10795 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10796 char *full_name = mono_type_get_full_name (klass);
10797 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10798 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10799 g_free (full_name);
10803 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10805 mono_metadata_decode_value (sig, &sig);
10806 /* FIELD signature == 0x06 */
10807 g_assert (*sig == 0x06);
10809 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10811 char *full_name = mono_type_get_full_name (klass);
10812 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));
10813 g_free (full_name);
10816 mono_memory_barrier ();
10817 field->type = ftype;
10821 mono_field_resolve_flags (MonoClassField *field)
10823 MonoClass *klass = field->parent;
10824 MonoImage *image = klass->image;
10825 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10826 int field_idx = field - klass->fields;
10830 MonoClassField *gfield = >d->fields [field_idx];
10831 return mono_field_get_flags (gfield);
10833 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10835 /*FIXME, in theory we do not lazy load SRE fields*/
10836 g_assert (!image_is_dynamic (image));
10838 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10843 * mono_class_get_fields_lazy:
10844 * @klass: the MonoClass to act on
10846 * This routine is an iterator routine for retrieving the fields in a class.
10847 * Only minimal information about fields are loaded. Accessors must be used
10848 * for all MonoClassField returned.
10850 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10851 * iterate over all of the elements. When no more values are
10852 * available, the return value is NULL.
10854 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10857 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10859 MonoClassField* field;
10863 mono_class_setup_basic_field_info (klass);
10864 if (!klass->fields)
10866 /* start from the first */
10867 if (mono_class_get_field_count (klass)) {
10868 *iter = &klass->fields [0];
10869 return (MonoClassField *)*iter;
10875 field = (MonoClassField *)*iter;
10877 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10879 return (MonoClassField *)*iter;
10885 mono_class_full_name (MonoClass *klass)
10887 return mono_type_full_name (&klass->byval_arg);
10890 /* Declare all shared lazy type lookup functions */
10891 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)