2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* Low level lock which protects data structures in this module */
56 static mono_mutex_t classes_mutex;
58 /* Function supplied by the runtime to find classes by name using information from the AOT file */
59 static MonoGetClassFromName get_class_from_name = NULL;
61 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
62 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
63 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
64 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
65 static int generic_array_methods (MonoClass *class);
66 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
68 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
69 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
70 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
71 static guint32 mono_field_resolve_flags (MonoClassField *field);
72 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
73 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
76 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
80 We use gclass recording to allow recursive system f types to be referenced by a parent.
82 Given the following type hierarchy:
84 class TextBox : TextBoxBase<TextBox> {}
85 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
86 class TextInput<T> : Input<T> where T: TextInput<T> {}
89 The runtime tries to load TextBoxBase<>.
90 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
91 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
92 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
94 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
95 at this point, iow, both are registered in the type map and both and a NULL parent. This means
96 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
98 To fix that what we do is to record all generic instantes created while resolving the parent of
99 any generic type definition and, after resolved, correct the parent field if needed.
102 static int record_gclass_instantiation;
103 static GSList *gclass_recorded_list;
104 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
109 mono_locks_acquire (&classes_mutex, ClassesLock);
113 classes_unlock (void)
115 mono_locks_release (&classes_mutex, ClassesLock);
119 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
122 enable_gclass_recording (void)
124 ++record_gclass_instantiation;
128 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
131 disable_gclass_recording (gclass_record_func func, void *user_data)
133 GSList **head = &gclass_recorded_list;
135 g_assert (record_gclass_instantiation > 0);
136 --record_gclass_instantiation;
139 GSList *node = *head;
140 if (func ((MonoClass*)node->data, user_data)) {
142 g_slist_free_1 (node);
148 /* We automatically discard all recorded gclasses when disabled. */
149 if (!record_gclass_instantiation && gclass_recorded_list) {
150 g_slist_free (gclass_recorded_list);
151 gclass_recorded_list = NULL;
156 * mono_class_from_typeref:
157 * @image: a MonoImage
158 * @type_token: a TypeRef token
160 * Creates the MonoClass* structure representing the type defined by
161 * the typeref token valid inside @image.
162 * Returns: the MonoClass* representing the typeref token, NULL ifcould
166 mono_class_from_typeref (MonoImage *image, guint32 type_token)
169 MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
170 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
175 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
177 guint32 cols [MONO_TYPEREF_SIZE];
178 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
180 const char *name, *nspace;
181 MonoClass *res = NULL;
184 mono_error_init (error);
186 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
189 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
191 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
192 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
194 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
195 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
196 case MONO_RESOLUTION_SCOPE_MODULE:
198 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
199 This is not the observed behavior of existing implementations.
200 The defacto behavior is that it's just a typedef in disguise.
202 /* a typedef in disguise */
203 res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
206 case MONO_RESOLUTION_SCOPE_MODULEREF:
207 module = mono_image_load_module (image, idx);
209 res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
212 case MONO_RESOLUTION_SCOPE_TYPEREF: {
213 MonoClass *enclosing;
216 if (idx == mono_metadata_token_index (type_token)) {
217 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
221 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
222 if (!mono_error_ok (error))
225 if (enclosing->nested_classes_inited && enclosing->ext) {
226 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
227 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
229 if (strcmp (res->name, name) == 0)
233 /* Don't call mono_class_init as we might've been called by it recursively */
234 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
236 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
237 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
238 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
240 if (strcmp (nname, name) == 0)
241 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
243 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
246 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
249 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
253 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
254 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
258 if (!image->references || !image->references [idx - 1])
259 mono_assembly_load_reference (image, idx - 1);
260 g_assert (image->references [idx - 1]);
262 /* If the assembly did not load, register this as a type load exception */
263 if (image->references [idx - 1] == REFERENCE_MISSING){
264 MonoAssemblyName aname;
267 mono_assembly_get_assemblyref (image, idx - 1, &aname);
268 human_name = mono_stringify_assembly_name (&aname);
269 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
273 res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
276 /* Generic case, should be avoided for when a better error is possible. */
277 if (!res && mono_error_ok (error)) {
278 char *name = mono_class_name_from_token (image, type_token);
279 char *assembly = mono_assembly_name_from_token (image, type_token);
280 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
287 mono_image_memdup (MonoImage *image, void *data, guint size)
289 void *res = mono_image_alloc (image, size);
290 memcpy (res, data, size);
294 /* Copy everything mono_metadata_free_array free. */
296 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
299 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
301 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
303 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
305 a = g_memdup (a, sizeof (MonoArrayType));
307 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
309 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
314 /* Copy everything mono_metadata_free_method_signature free. */
316 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
320 sig = mono_metadata_signature_dup_full (image, sig);
322 sig->ret = mono_metadata_type_dup (image, sig->ret);
323 for (i = 0; i < sig->param_count; ++i)
324 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
330 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
332 MonoAssembly *ta = klass->image->assembly;
335 name = mono_stringify_assembly_name (&ta->aname);
336 g_string_append_printf (str, ", %s", name);
341 mono_type_name_check_byref (MonoType *type, GString *str)
344 g_string_append_c (str, '&');
348 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
349 MonoTypeNameFormat format)
353 switch (type->type) {
354 case MONO_TYPE_ARRAY: {
355 int i, rank = type->data.array->rank;
356 MonoTypeNameFormat nested_format;
358 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
359 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
361 mono_type_get_name_recurse (
362 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
363 g_string_append_c (str, '[');
365 g_string_append_c (str, '*');
366 for (i = 1; i < rank; i++)
367 g_string_append_c (str, ',');
368 g_string_append_c (str, ']');
370 mono_type_name_check_byref (type, str);
372 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
373 _mono_type_get_assembly_name (type->data.array->eklass, str);
376 case MONO_TYPE_SZARRAY: {
377 MonoTypeNameFormat nested_format;
379 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
380 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
382 mono_type_get_name_recurse (
383 &type->data.klass->byval_arg, str, FALSE, nested_format);
384 g_string_append (str, "[]");
386 mono_type_name_check_byref (type, str);
388 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
389 _mono_type_get_assembly_name (type->data.klass, str);
392 case MONO_TYPE_PTR: {
393 MonoTypeNameFormat nested_format;
395 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
396 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
398 mono_type_get_name_recurse (
399 type->data.type, str, FALSE, nested_format);
400 g_string_append_c (str, '*');
402 mono_type_name_check_byref (type, str);
404 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
405 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
410 if (!mono_generic_param_info (type->data.generic_param))
411 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
413 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
415 mono_type_name_check_byref (type, str);
419 klass = mono_class_from_mono_type (type);
420 if (klass->nested_in) {
421 mono_type_get_name_recurse (
422 &klass->nested_in->byval_arg, str, TRUE, format);
423 if (format == MONO_TYPE_NAME_FORMAT_IL)
424 g_string_append_c (str, '.');
426 g_string_append_c (str, '+');
427 } else if (*klass->name_space) {
428 g_string_append (str, klass->name_space);
429 g_string_append_c (str, '.');
431 if (format == MONO_TYPE_NAME_FORMAT_IL) {
432 char *s = strchr (klass->name, '`');
433 int len = s ? s - klass->name : strlen (klass->name);
435 g_string_append_len (str, klass->name, len);
437 g_string_append (str, klass->name);
440 if (klass->generic_class) {
441 MonoGenericClass *gclass = klass->generic_class;
442 MonoGenericInst *inst = gclass->context.class_inst;
443 MonoTypeNameFormat nested_format;
446 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
447 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
449 if (format == MONO_TYPE_NAME_FORMAT_IL)
450 g_string_append_c (str, '<');
452 g_string_append_c (str, '[');
453 for (i = 0; i < inst->type_argc; i++) {
454 MonoType *t = inst->type_argv [i];
457 g_string_append_c (str, ',');
458 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
459 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
460 g_string_append_c (str, '[');
461 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
462 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
463 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
464 g_string_append_c (str, ']');
466 if (format == MONO_TYPE_NAME_FORMAT_IL)
467 g_string_append_c (str, '>');
469 g_string_append_c (str, ']');
470 } else if (klass->generic_container &&
471 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
472 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
475 if (format == MONO_TYPE_NAME_FORMAT_IL)
476 g_string_append_c (str, '<');
478 g_string_append_c (str, '[');
479 for (i = 0; i < klass->generic_container->type_argc; i++) {
481 g_string_append_c (str, ',');
482 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
484 if (format == MONO_TYPE_NAME_FORMAT_IL)
485 g_string_append_c (str, '>');
487 g_string_append_c (str, ']');
490 mono_type_name_check_byref (type, str);
492 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
493 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
494 _mono_type_get_assembly_name (klass, str);
500 * mono_type_get_name_full:
502 * @format: the format for the return string.
505 * Returns: the string representation in a number of formats:
507 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
508 * returned in the formatrequired by System.Reflection, this is the
509 * inverse of mono_reflection_parse_type ().
511 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
512 * be used by the IL assembler.
514 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
516 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
519 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
523 result = g_string_new ("");
525 mono_type_get_name_recurse (type, result, FALSE, format);
527 return g_string_free (result, FALSE);
531 * mono_type_get_full_name:
534 * Returns: the string representation for type as required by System.Reflection.
535 * The inverse of mono_reflection_parse_type ().
538 mono_type_get_full_name (MonoClass *class)
540 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
544 * mono_type_get_name:
547 * Returns: the string representation for type as it would be represented in IL code.
550 mono_type_get_name (MonoType *type)
552 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
556 * mono_type_get_underlying_type:
559 * Returns: the MonoType for the underlying integer type if @type
560 * is an enum and byref is false, otherwise the type itself.
563 mono_type_get_underlying_type (MonoType *type)
565 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
566 return mono_class_enum_basetype (type->data.klass);
567 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
568 return mono_class_enum_basetype (type->data.generic_class->container_class);
573 * mono_class_is_open_constructed_type:
576 * Returns TRUE if type represents a generics open constructed type.
577 * IOW, not all type parameters required for the instantiation have
578 * been provided or it's a generic type definition.
580 * An open constructed type means it's a non realizable type. Not to
581 * be mixed up with an abstract type - we can't cast or dispatch to
582 * an open type, for example.
585 mono_class_is_open_constructed_type (MonoType *t)
591 case MONO_TYPE_SZARRAY:
592 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
593 case MONO_TYPE_ARRAY:
594 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
596 return mono_class_is_open_constructed_type (t->data.type);
597 case MONO_TYPE_GENERICINST:
598 return t->data.generic_class->context.class_inst->is_open;
599 case MONO_TYPE_CLASS:
600 case MONO_TYPE_VALUETYPE:
601 return t->data.klass->generic_container != NULL;
608 This is a simple function to catch the most common bad instances of generic types.
609 Specially those that might lead to further failures in the runtime.
612 is_valid_generic_argument (MonoType *type)
614 switch (type->type) {
616 //case MONO_TYPE_TYPEDBYREF:
623 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
625 mono_error_init (error);
627 switch (type->type) {
628 case MONO_TYPE_MVAR: {
630 int num = mono_type_get_generic_param_num (type);
631 MonoGenericInst *inst = context->method_inst;
632 if (!inst || !inst->type_argv)
634 if (num >= inst->type_argc) {
635 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
636 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
637 num, info ? info->name : "", inst->type_argc);
641 if (!is_valid_generic_argument (inst->type_argv [num])) {
642 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
643 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
644 num, info ? info->name : "", inst->type_argv [num]->type);
648 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
649 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
650 * ->byref and ->attrs from @type are propagated to the returned type.
652 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
653 nt->byref = type->byref;
654 nt->attrs = type->attrs;
657 case MONO_TYPE_VAR: {
659 int num = mono_type_get_generic_param_num (type);
660 MonoGenericInst *inst = context->class_inst;
663 if (num >= inst->type_argc) {
664 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
665 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
666 num, info ? info->name : "", inst->type_argc);
669 if (!is_valid_generic_argument (inst->type_argv [num])) {
670 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
671 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
672 num, info ? info->name : "", inst->type_argv [num]->type);
675 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
676 nt->byref = type->byref;
677 nt->attrs = type->attrs;
680 case MONO_TYPE_SZARRAY: {
681 MonoClass *eclass = type->data.klass;
682 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
683 if (!inflated || !mono_error_ok (error))
685 nt = mono_metadata_type_dup (image, type);
686 nt->data.klass = mono_class_from_mono_type (inflated);
687 mono_metadata_free_type (inflated);
690 case MONO_TYPE_ARRAY: {
691 MonoClass *eclass = type->data.array->eklass;
692 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
693 if (!inflated || !mono_error_ok (error))
695 nt = mono_metadata_type_dup (image, type);
696 nt->data.array->eklass = mono_class_from_mono_type (inflated);
697 mono_metadata_free_type (inflated);
700 case MONO_TYPE_GENERICINST: {
701 MonoGenericClass *gclass = type->data.generic_class;
702 MonoGenericInst *inst;
704 if (!gclass->context.class_inst->is_open)
707 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
708 if (!mono_error_ok (error))
710 if (inst != gclass->context.class_inst)
711 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
713 if (gclass == type->data.generic_class)
716 nt = mono_metadata_type_dup (image, type);
717 nt->data.generic_class = gclass;
720 case MONO_TYPE_CLASS:
721 case MONO_TYPE_VALUETYPE: {
722 MonoClass *klass = type->data.klass;
723 MonoGenericContainer *container = klass->generic_container;
724 MonoGenericInst *inst;
725 MonoGenericClass *gclass = NULL;
731 /* We can't use context->class_inst directly, since it can have more elements */
732 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
733 if (!mono_error_ok (error))
735 if (inst == container->context.class_inst)
738 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
740 nt = mono_metadata_type_dup (image, type);
741 nt->type = MONO_TYPE_GENERICINST;
742 nt->data.generic_class = gclass;
752 mono_generic_class_get_context (MonoGenericClass *gclass)
754 return &gclass->context;
758 mono_class_get_context (MonoClass *class)
760 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
764 * mono_class_get_generic_container:
766 * Return the generic container of KLASS which should be a generic type definition.
768 MonoGenericContainer*
769 mono_class_get_generic_container (MonoClass *klass)
771 g_assert (klass->is_generic);
773 return klass->generic_container;
777 * mono_class_get_generic_class:
779 * Return the MonoGenericClass of KLASS, which should be a generic instance.
782 mono_class_get_generic_class (MonoClass *klass)
784 g_assert (klass->is_inflated);
786 return klass->generic_class;
790 * mono_class_inflate_generic_type_with_mempool:
791 * @mempool: a mempool
793 * @context: a generics context
794 * @error: error context
796 * The same as mono_class_inflate_generic_type, but allocates the MonoType
797 * from mempool if it is non-NULL. If it is NULL, the MonoType is
798 * allocated on the heap and is owned by the caller.
799 * The returned type can potentially be the same as TYPE, so it should not be
800 * modified by the caller, and it should be freed using mono_metadata_free_type ().
803 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
805 MonoType *inflated = NULL;
806 mono_error_init (error);
809 inflated = inflate_generic_type (image, type, context, error);
810 if (!mono_error_ok (error))
814 MonoType *shared = mono_metadata_get_shared_type (type);
819 return mono_metadata_type_dup (image, type);
823 mono_stats.inflated_type_count++;
828 * mono_class_inflate_generic_type:
830 * @context: a generics context
832 * If @type is a generic type and @context is not NULL, instantiate it using the
833 * generics context @context.
835 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
836 * on the heap and is owned by the caller. Returns NULL on error.
838 * @deprecated Please use mono_class_inflate_generic_type_checked instead
841 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
845 result = mono_class_inflate_generic_type_checked (type, context, &error);
847 if (!mono_error_ok (&error)) {
848 mono_error_cleanup (&error);
855 * mono_class_inflate_generic_type:
857 * @context: a generics context
858 * @error: error context to use
860 * If @type is a generic type and @context is not NULL, instantiate it using the
861 * generics context @context.
863 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
864 * on the heap and is owned by the caller.
867 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
869 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
873 * mono_class_inflate_generic_type_no_copy:
875 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
879 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
881 MonoType *inflated = NULL;
883 mono_error_init (error);
885 inflated = inflate_generic_type (image, type, context, error);
886 if (!mono_error_ok (error))
893 mono_stats.inflated_type_count++;
898 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
903 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
904 if (!mono_error_ok (error))
907 res = mono_class_from_mono_type (inflated);
908 mono_metadata_free_type (inflated);
913 * mono_class_inflate_generic_class:
915 * Inflate the class GKLASS with CONTEXT.
918 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
923 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
924 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
931 static MonoGenericContext
932 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
934 MonoGenericInst *class_inst = NULL;
935 MonoGenericInst *method_inst = NULL;
936 MonoGenericContext res = { NULL, NULL };
938 mono_error_init (error);
940 if (context->class_inst) {
941 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
942 if (!mono_error_ok (error))
946 if (context->method_inst) {
947 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
948 if (!mono_error_ok (error))
952 res.class_inst = class_inst;
953 res.method_inst = method_inst;
959 * mono_class_inflate_generic_method:
960 * @method: a generic method
961 * @context: a generics context
963 * Instantiate the generic method @method using the generics context @context.
965 * Returns: the new instantiated method
968 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
970 return mono_class_inflate_generic_method_full (method, NULL, context);
974 * mono_class_inflate_generic_method_full:
976 * Instantiate method @method with the generic context @context.
977 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
978 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
981 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
984 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
985 if (!mono_error_ok (&error))
986 /*FIXME do proper error handling - on this case, kill this function. */
987 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
993 * mono_class_inflate_generic_method_full_checked:
994 * Same as mono_class_inflate_generic_method_full but return failure using @error.
997 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1000 MonoMethodInflated *iresult, *cached;
1001 MonoMethodSignature *sig;
1002 MonoGenericContext tmp_context;
1003 gboolean is_mb_open = FALSE;
1005 mono_error_init (error);
1007 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1008 while (method->is_inflated) {
1009 MonoGenericContext *method_context = mono_method_get_context (method);
1010 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1012 tmp_context = inflate_generic_context (method_context, context, error);
1013 if (!mono_error_ok (error))
1015 context = &tmp_context;
1017 if (mono_metadata_generic_context_equal (method_context, context))
1020 method = imethod->declaring;
1024 * A method only needs to be inflated if the context has argument for which it is
1027 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1028 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1031 if (!((method->is_generic && context->method_inst) ||
1032 (method->klass->generic_container && context->class_inst)))
1036 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1037 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1038 * This is opposite to the way non-SRE MethodInfos behave.
1040 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1042 * void Example<T> () {
1046 * In Example, the method token must be encoded as: "void Example<!!0>()"
1048 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1049 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1051 * On the other hand, inflating a non-SRE generic method with its own arguments should
1052 * return itself. For example:
1054 * MethodInfo m = ... //m is a generic method definition
1055 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1058 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1059 * what happens with regular methods.
1061 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1062 * everything should behave like a regular type or method.
1065 is_mb_open = method->is_generic &&
1066 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1067 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1069 iresult = g_new0 (MonoMethodInflated, 1);
1070 iresult->context = *context;
1071 iresult->declaring = method;
1072 iresult->method.method.is_mb_open = is_mb_open;
1074 if (!context->method_inst && method->is_generic)
1075 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1077 if (!context->class_inst) {
1078 g_assert (!iresult->declaring->klass->generic_class);
1079 if (iresult->declaring->klass->generic_container)
1080 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1081 else if (iresult->declaring->klass->generic_class)
1082 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1085 mono_loader_lock ();
1086 cached = mono_method_inflated_lookup (iresult, FALSE);
1088 mono_loader_unlock ();
1090 return (MonoMethod*)cached;
1093 mono_stats.inflated_method_count++;
1095 inflated_methods_size += sizeof (MonoMethodInflated);
1097 sig = mono_method_signature (method);
1099 char *name = mono_type_get_full_name (method->klass);
1100 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1106 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1108 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1111 result = (MonoMethod *) iresult;
1112 result->is_inflated = TRUE;
1113 result->is_generic = FALSE;
1114 result->sre_method = FALSE;
1115 result->signature = NULL;
1116 result->is_mb_open = is_mb_open;
1118 if (!context->method_inst) {
1119 /* Set the generic_container of the result to the generic_container of method */
1120 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1122 if (generic_container) {
1123 result->is_generic = 1;
1124 mono_method_set_generic_container (result, generic_container);
1128 if (!klass_hint || !klass_hint->generic_class ||
1129 klass_hint->generic_class->container_class != method->klass ||
1130 klass_hint->generic_class->context.class_inst != context->class_inst)
1133 if (method->klass->generic_container)
1134 result->klass = klass_hint;
1136 if (!result->klass) {
1137 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1138 if (!mono_error_ok (error))
1141 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1143 mono_metadata_free_type (inflated);
1147 * FIXME: This should hold, but it doesn't:
1149 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1150 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1151 * g_assert (result->is_generic);
1154 * Fixing this here causes other things to break, hence a very
1155 * ugly hack in mini-trampolines.c - see
1156 * is_generic_method_definition().
1159 mono_method_inflated_lookup (iresult, TRUE);
1160 mono_loader_unlock ();
1164 mono_loader_unlock ();
1170 * mono_get_inflated_method:
1172 * Obsolete. We keep it around since it's mentioned in the public API.
1175 mono_get_inflated_method (MonoMethod *method)
1181 * mono_method_get_context_general:
1183 * @uninflated: handle uninflated methods?
1185 * Returns the generic context of a method or NULL if it doesn't have
1186 * one. For an inflated method that's the context stored in the
1187 * method. Otherwise it's in the method's generic container or in the
1188 * generic container of the method's class.
1191 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1193 if (method->is_inflated) {
1194 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1195 return &imethod->context;
1199 if (method->is_generic)
1200 return &(mono_method_get_generic_container (method)->context);
1201 if (method->klass->generic_container)
1202 return &method->klass->generic_container->context;
1207 * mono_method_get_context:
1210 * Returns the generic context for method if it's inflated, otherwise
1214 mono_method_get_context (MonoMethod *method)
1216 return mono_method_get_context_general (method, FALSE);
1220 * mono_method_get_generic_container:
1222 * Returns the generic container of METHOD, which should be a generic method definition.
1223 * Returns NULL if METHOD is not a generic method definition.
1224 * LOCKING: Acquires the loader lock.
1226 MonoGenericContainer*
1227 mono_method_get_generic_container (MonoMethod *method)
1229 MonoGenericContainer *container;
1231 if (!method->is_generic)
1234 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1235 g_assert (container);
1241 * mono_method_set_generic_container:
1243 * Sets the generic container of METHOD to CONTAINER.
1244 * LOCKING: Acquires the loader lock.
1247 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1249 g_assert (method->is_generic);
1251 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1255 * mono_class_find_enum_basetype:
1256 * @class: The enum class
1258 * Determine the basetype of an enum by iterating through its fields. We do this
1259 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1262 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1264 MonoGenericContainer *container = NULL;
1265 MonoImage *m = class->image;
1266 const int top = class->field.count;
1269 g_assert (class->enumtype);
1271 mono_error_init (error);
1273 if (class->generic_container)
1274 container = class->generic_container;
1275 else if (class->generic_class) {
1276 MonoClass *gklass = class->generic_class->container_class;
1278 container = gklass->generic_container;
1279 g_assert (container);
1283 * Fetch all the field information.
1285 for (i = 0; i < top; i++){
1287 guint32 cols [MONO_FIELD_SIZE];
1288 int idx = class->field.first + i;
1291 /* class->field.first and idx points into the fieldptr table */
1292 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1294 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1297 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1298 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1302 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1303 mono_metadata_decode_value (sig, &sig);
1304 /* FIELD signature == 0x06 */
1306 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1310 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1312 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1313 mono_error_set_from_loader_error (error);
1315 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1318 if (class->generic_class) {
1319 //FIXME do we leak here?
1320 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1321 if (!mono_error_ok (error))
1323 ftype->attrs = cols [MONO_FIELD_FLAGS];
1328 mono_error_set_type_load_class (error, class, "Could not find base type");
1331 g_assert (!mono_loader_get_last_error ());
1336 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1339 mono_type_has_exceptions (MonoType *type)
1341 switch (type->type) {
1342 case MONO_TYPE_CLASS:
1343 case MONO_TYPE_VALUETYPE:
1344 case MONO_TYPE_SZARRAY:
1345 return type->data.klass->exception_type;
1346 case MONO_TYPE_ARRAY:
1347 return type->data.array->eklass->exception_type;
1348 case MONO_TYPE_GENERICINST:
1349 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1357 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1361 mono_class_alloc (MonoClass *class, int size)
1363 if (class->generic_class)
1364 return mono_image_set_alloc (class->generic_class->owner, size);
1366 return mono_image_alloc (class->image, size);
1370 mono_class_alloc0 (MonoClass *class, int size)
1374 res = mono_class_alloc (class, size);
1375 memset (res, 0, size);
1379 #define mono_class_new0(class,struct_type, n_structs) \
1380 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1383 * mono_class_setup_basic_field_info:
1384 * @class: The class to initialize
1386 * Initializes the class->fields.
1387 * LOCKING: Assumes the loader lock is held.
1390 mono_class_setup_basic_field_info (MonoClass *class)
1392 MonoClassField *field;
1400 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1401 image = class->image;
1402 top = class->field.count;
1404 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1406 * This happens when a generic instance of an unfinished generic typebuilder
1407 * is used as an element type for creating an array type. We can't initialize
1408 * the fields of this class using the fields of gklass, since gklass is not
1409 * finished yet, fields could be added to it later.
1415 mono_class_setup_basic_field_info (gtd);
1417 top = gtd->field.count;
1418 class->field.first = gtd->field.first;
1419 class->field.count = gtd->field.count;
1422 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1425 * Fetch all the field information.
1427 for (i = 0; i < top; i++){
1428 field = &class->fields [i];
1429 field->parent = class;
1432 field->name = mono_field_get_name (>d->fields [i]);
1434 int idx = class->field.first + i;
1435 /* class->field.first and idx points into the fieldptr table */
1436 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1437 /* The name is needed for fieldrefs */
1438 field->name = mono_metadata_string_heap (image, name_idx);
1444 * mono_class_setup_fields:
1445 * @class: The class to initialize
1447 * Initializes the class->fields.
1448 * LOCKING: Assumes the loader lock is held.
1451 mono_class_setup_fields (MonoClass *class)
1454 MonoImage *m = class->image;
1456 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1457 int i, blittable = TRUE;
1458 guint32 real_size = 0;
1459 guint32 packing_size = 0;
1460 gboolean explicit_size;
1461 MonoClassField *field;
1462 MonoGenericContainer *container = NULL;
1463 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1466 * FIXME: We have a race condition here. It's possible that this function returns
1467 * to its caller with `instance_size` set to `0` instead of the actual size. This
1468 * is not a problem when the function is called recursively on the same class,
1469 * because the size will be initialized by the outer invocation. What follows is a
1470 * description of how it can occur in other cases, too. There it is a problem,
1471 * because it can lead to the GC being asked to allocate an object of size `0`,
1472 * which SGen chokes on. The race condition is triggered infrequently by
1473 * `tests/sgen-suspend.cs`.
1475 * This function is called for a class whenever one of its subclasses is inited.
1476 * For example, it's called for every subclass of Object. What it does is this:
1478 * if (class->setup_fields_called)
1481 * class->instance_size = 0;
1483 * class->setup_fields_called = 1;
1484 * ... critical point
1485 * class->instance_size = actual_instance_size;
1487 * The last two steps are sometimes reversed, but that only changes the way in which
1488 * the race condition works.
1490 * Assume thread A goes through this function and makes it to the critical point.
1491 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1492 * immediately, but `instance_size` is incorrect.
1494 * The other case looks like this:
1496 * if (class->setup_fields_called)
1498 * ... critical point X
1499 * class->instance_size = 0;
1500 * ... critical point Y
1501 * class->instance_size = actual_instance_size;
1503 * class->setup_fields_called = 1;
1505 * Assume thread A goes through the function and makes it to critical point X. Now
1506 * thread B runs through the whole of the function, returning, assuming
1507 * `instance_size` is set. At that point thread A gets to run and makes it to
1508 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1511 if (class->setup_fields_called)
1514 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1516 * This happens when a generic instance of an unfinished generic typebuilder
1517 * is used as an element type for creating an array type. We can't initialize
1518 * the fields of this class using the fields of gklass, since gklass is not
1519 * finished yet, fields could be added to it later.
1524 mono_class_setup_basic_field_info (class);
1525 top = class->field.count;
1528 mono_class_setup_fields (gtd);
1529 if (gtd->exception_type) {
1530 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1535 class->instance_size = 0;
1537 class->sizes.class_size = 0;
1539 if (class->parent) {
1540 /* For generic instances, class->parent might not have been initialized */
1541 mono_class_init (class->parent);
1542 if (!class->parent->size_inited) {
1543 mono_class_setup_fields (class->parent);
1544 if (class->parent->exception_type) {
1545 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1549 class->instance_size += class->parent->instance_size;
1550 class->min_align = class->parent->min_align;
1551 /* we use |= since it may have been set already */
1552 class->has_references |= class->parent->has_references;
1553 blittable = class->parent->blittable;
1555 class->instance_size = sizeof (MonoObject);
1556 class->min_align = 1;
1559 /* We can't really enable 16 bytes alignment until the GC supports it.
1560 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1561 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1562 Bug #506144 is an example of this issue.
1564 if (class->simd_type)
1565 class->min_align = 16;
1567 /* Get the real size */
1568 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1570 if (explicit_size) {
1571 if ((packing_size & 0xfffffff0) != 0) {
1572 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1573 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1576 class->packing_size = packing_size;
1577 real_size += class->instance_size;
1581 if (explicit_size && real_size) {
1582 class->instance_size = MAX (real_size, class->instance_size);
1584 class->blittable = blittable;
1585 mono_memory_barrier ();
1586 class->size_inited = 1;
1587 class->fields_inited = 1;
1588 class->setup_fields_called = 1;
1592 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1595 /* Prevent infinite loops if the class references itself */
1596 class->setup_fields_called = 1;
1598 if (class->generic_container) {
1599 container = class->generic_container;
1601 container = gtd->generic_container;
1602 g_assert (container);
1606 * Fetch all the field information.
1608 for (i = 0; i < top; i++){
1609 int idx = class->field.first + i;
1610 field = &class->fields [i];
1612 field->parent = class;
1615 mono_field_resolve_type (field, &error);
1616 if (!mono_error_ok (&error)) {
1617 /*mono_field_resolve_type already failed class*/
1618 mono_error_cleanup (&error);
1622 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1623 g_assert (field->type);
1626 if (mono_field_is_deleted (field))
1629 MonoClassField *gfield = >d->fields [i];
1630 field->offset = gfield->offset;
1632 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1634 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1635 field->offset = offset;
1637 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1638 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1641 if (field->offset < -1) { /*-1 is used to encode special static fields */
1642 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1645 if (class->generic_container) {
1646 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1652 /* Only do these checks if we still think this type is blittable */
1653 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1654 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1657 MonoClass *field_class = mono_class_from_mono_type (field->type);
1659 mono_class_setup_fields (field_class);
1660 if (field_class->exception_type) {
1661 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1665 if (!field_class || !field_class->blittable)
1670 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1671 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1672 blittable = class->element_class->blittable;
1675 if (mono_type_has_exceptions (field->type)) {
1676 char *class_name = mono_type_get_full_name (class);
1677 char *type_name = mono_type_full_name (field->type);
1679 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1680 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1681 g_free (class_name);
1685 /* The def_value of fields is compute lazily during vtable creation */
1688 if (class == mono_defaults.string_class)
1691 class->blittable = blittable;
1693 if (class->enumtype && !mono_class_enum_basetype (class)) {
1694 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1697 if (explicit_size && real_size) {
1698 class->instance_size = MAX (real_size, class->instance_size);
1701 if (class->exception_type)
1703 mono_class_layout_fields (class);
1705 /*valuetypes can't be neither bigger than 1Mb or empty. */
1706 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1707 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1709 mono_memory_barrier ();
1710 class->fields_inited = 1;
1714 * mono_class_setup_fields_locking:
1715 * @class: The class to initialize
1717 * Initializes the class->fields array of fields.
1718 * Aquires the loader lock.
1721 mono_class_setup_fields_locking (MonoClass *class)
1723 /* This can be checked without locks */
1724 if (class->fields_inited)
1726 mono_loader_lock ();
1727 mono_class_setup_fields (class);
1728 mono_loader_unlock ();
1732 * mono_class_has_references:
1734 * Returns whenever @klass->has_references is set, initializing it if needed.
1735 * Aquires the loader lock.
1738 mono_class_has_references (MonoClass *klass)
1740 if (klass->init_pending) {
1741 /* Be conservative */
1744 mono_class_init (klass);
1746 return klass->has_references;
1751 * mono_type_get_basic_type_from_generic:
1754 * Returns a closed type corresponding to the possibly open type
1758 mono_type_get_basic_type_from_generic (MonoType *type)
1760 /* When we do generic sharing we let type variables stand for reference types. */
1761 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1762 return &mono_defaults.object_class->byval_arg;
1767 * mono_class_layout_fields:
1770 * Compute the placement of fields inside an object or struct, according to
1771 * the layout rules and set the following fields in @class:
1772 * - has_references (if the class contains instance references firled or structs that contain references)
1773 * - has_static_refs (same, but for static fields)
1774 * - instance_size (size of the object in memory)
1775 * - class_size (size needed for the static fields)
1776 * - size_inited (flag set when the instance_size is set)
1778 * LOCKING: this is supposed to be called with the loader lock held.
1781 mono_class_layout_fields (MonoClass *class)
1784 const int top = class->field.count;
1785 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1786 guint32 pass, passes, real_size;
1787 gboolean gc_aware_layout = FALSE;
1788 gboolean has_static_fields = FALSE;
1789 MonoClassField *field;
1792 * When we do generic sharing we need to have layout
1793 * information for open generic classes (either with a generic
1794 * context containing type variables or with a generic
1795 * container), so we don't return in that case anymore.
1799 * Enable GC aware auto layout: in this mode, reference
1800 * fields are grouped together inside objects, increasing collector
1802 * Requires that all classes whose layout is known to native code be annotated
1803 * with [StructLayout (LayoutKind.Sequential)]
1804 * Value types have gc_aware_layout disabled by default, as per
1805 * what the default is for other runtimes.
1807 /* corlib is missing [StructLayout] directives in many places */
1808 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1809 if (!class->valuetype)
1810 gc_aware_layout = TRUE;
1813 /* Compute klass->has_references */
1815 * Process non-static fields first, since static fields might recursively
1816 * refer to the class itself.
1818 for (i = 0; i < top; i++) {
1821 field = &class->fields [i];
1823 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1824 ftype = mono_type_get_underlying_type (field->type);
1825 ftype = mono_type_get_basic_type_from_generic (ftype);
1826 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1827 class->has_references = TRUE;
1831 for (i = 0; i < top; i++) {
1834 field = &class->fields [i];
1836 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1837 ftype = mono_type_get_underlying_type (field->type);
1838 ftype = mono_type_get_basic_type_from_generic (ftype);
1839 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1840 class->has_static_refs = TRUE;
1844 for (i = 0; i < top; i++) {
1847 field = &class->fields [i];
1849 ftype = mono_type_get_underlying_type (field->type);
1850 ftype = mono_type_get_basic_type_from_generic (ftype);
1851 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1852 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1853 class->has_static_refs = TRUE;
1855 class->has_references = TRUE;
1860 * Compute field layout and total size (not considering static fields)
1864 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1865 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1867 if (gc_aware_layout)
1872 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1875 if (class->parent) {
1876 mono_class_setup_fields (class->parent);
1877 if (class->parent->exception_type) {
1878 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1881 real_size = class->parent->instance_size;
1883 real_size = sizeof (MonoObject);
1886 for (pass = 0; pass < passes; ++pass) {
1887 for (i = 0; i < top; i++){
1892 field = &class->fields [i];
1894 if (mono_field_is_deleted (field))
1896 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1899 ftype = mono_type_get_underlying_type (field->type);
1900 ftype = mono_type_get_basic_type_from_generic (ftype);
1901 if (gc_aware_layout) {
1902 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1911 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1912 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1913 /* This field is a hack inserted by MCS to empty structures */
1917 size = mono_type_size (field->type, &align);
1919 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1920 align = class->packing_size ? MIN (class->packing_size, align): align;
1921 /* if the field has managed references, we need to force-align it
1924 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1925 align = MAX (align, sizeof (gpointer));
1927 class->min_align = MAX (align, class->min_align);
1928 field->offset = real_size;
1930 field->offset += align - 1;
1931 field->offset &= ~(align - 1);
1933 /*TypeBuilders produce all sort of weird things*/
1934 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1935 real_size = field->offset + size;
1938 class->instance_size = MAX (real_size, class->instance_size);
1940 if (class->instance_size & (class->min_align - 1)) {
1941 class->instance_size += class->min_align - 1;
1942 class->instance_size &= ~(class->min_align - 1);
1946 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1950 for (i = 0; i < top; i++) {
1955 field = &class->fields [i];
1958 * There must be info about all the fields in a type if it
1959 * uses explicit layout.
1961 if (mono_field_is_deleted (field))
1963 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1966 size = mono_type_size (field->type, &align);
1967 align = class->packing_size ? MIN (class->packing_size, align): align;
1968 class->min_align = MAX (align, class->min_align);
1971 * When we get here, field->offset is already set by the
1972 * loader (for either runtime fields or fields loaded from metadata).
1973 * The offset is from the start of the object: this works for both
1974 * classes and valuetypes.
1976 field->offset += sizeof (MonoObject);
1977 ftype = mono_type_get_underlying_type (field->type);
1978 ftype = mono_type_get_basic_type_from_generic (ftype);
1979 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1980 if (field->offset % sizeof (gpointer)) {
1981 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1988 real_size = MAX (real_size, size + field->offset);
1991 if (class->has_references) {
1992 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
1994 /* Check for overlapping reference and non-reference fields */
1995 for (i = 0; i < top; i++) {
1998 field = &class->fields [i];
2000 if (mono_field_is_deleted (field))
2002 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2004 ftype = mono_type_get_underlying_type (field->type);
2005 if (MONO_TYPE_IS_REFERENCE (ftype))
2006 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2008 for (i = 0; i < top; i++) {
2009 field = &class->fields [i];
2011 if (mono_field_is_deleted (field))
2013 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2016 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2017 char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
2018 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2021 g_free (ref_bitmap);
2024 class->instance_size = MAX (real_size, class->instance_size);
2025 if (class->instance_size & (class->min_align - 1)) {
2026 class->instance_size += class->min_align - 1;
2027 class->instance_size &= ~(class->min_align - 1);
2033 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2035 * For small structs, set min_align to at least the struct size to improve
2036 * performance, and since the JIT memset/memcpy code assumes this and generates
2037 * unaligned accesses otherwise. See #78990 for a testcase.
2039 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2040 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2043 mono_memory_barrier ();
2044 class->size_inited = 1;
2047 * Compute static field layout and size
2049 for (i = 0; i < top; i++){
2053 field = &class->fields [i];
2055 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2057 if (mono_field_is_deleted (field))
2060 if (mono_type_has_exceptions (field->type)) {
2061 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2065 has_static_fields = TRUE;
2067 size = mono_type_size (field->type, &align);
2068 field->offset = class->sizes.class_size;
2069 /*align is always non-zero here*/
2070 field->offset += align - 1;
2071 field->offset &= ~(align - 1);
2072 class->sizes.class_size = field->offset + size;
2075 if (has_static_fields && class->sizes.class_size == 0)
2076 /* Simplify code which depends on class_size != 0 if the class has static fields */
2077 class->sizes.class_size = 8;
2081 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2085 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2086 method->klass = class;
2087 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2088 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2089 method->signature = sig;
2090 method->name = name;
2093 if (name [0] == '.') {
2094 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2096 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2102 * mono_class_setup_methods:
2105 * Initializes the 'methods' array in CLASS.
2106 * Calling this method should be avoided if possible since it allocates a lot
2107 * of long-living MonoMethod structures.
2108 * Methods belonging to an interface are assigned a sequential slot starting
2111 * On failure this function sets class->exception_type
2114 mono_class_setup_methods (MonoClass *class)
2117 MonoMethod **methods;
2122 if (class->generic_class) {
2124 MonoClass *gklass = class->generic_class->container_class;
2126 mono_class_init (gklass);
2127 if (!gklass->exception_type)
2128 mono_class_setup_methods (gklass);
2129 if (gklass->exception_type) {
2130 /* FIXME make exception_data less opaque so it's possible to dup it here */
2131 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2135 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2136 count = gklass->method.count;
2137 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2139 for (i = 0; i < count; i++) {
2140 methods [i] = mono_class_inflate_generic_method_full_checked (
2141 gklass->methods [i], class, mono_class_get_context (class), &error);
2142 if (!mono_error_ok (&error)) {
2143 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2144 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2147 mono_error_cleanup (&error);
2151 } else if (class->rank) {
2153 MonoMethod *amethod;
2154 MonoMethodSignature *sig;
2155 int count_generic = 0, first_generic = 0;
2158 count = 3 + (class->rank > 1? 2: 1);
2160 mono_class_setup_interfaces (class, &error);
2161 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2163 if (class->interface_count) {
2164 count_generic = generic_array_methods (class);
2165 first_generic = count;
2166 count += class->interface_count * count_generic;
2169 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2171 sig = mono_metadata_signature_alloc (class->image, class->rank);
2172 sig->ret = &mono_defaults.void_class->byval_arg;
2173 sig->pinvoke = TRUE;
2174 sig->hasthis = TRUE;
2175 for (i = 0; i < class->rank; ++i)
2176 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2178 amethod = create_array_method (class, ".ctor", sig);
2179 methods [method_num++] = amethod;
2180 if (class->rank > 1) {
2181 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2182 sig->ret = &mono_defaults.void_class->byval_arg;
2183 sig->pinvoke = TRUE;
2184 sig->hasthis = TRUE;
2185 for (i = 0; i < class->rank * 2; ++i)
2186 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2188 amethod = create_array_method (class, ".ctor", sig);
2189 methods [method_num++] = amethod;
2191 /* element Get (idx11, [idx2, ...]) */
2192 sig = mono_metadata_signature_alloc (class->image, class->rank);
2193 sig->ret = &class->element_class->byval_arg;
2194 sig->pinvoke = TRUE;
2195 sig->hasthis = TRUE;
2196 for (i = 0; i < class->rank; ++i)
2197 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2198 amethod = create_array_method (class, "Get", sig);
2199 methods [method_num++] = amethod;
2200 /* element& Address (idx11, [idx2, ...]) */
2201 sig = mono_metadata_signature_alloc (class->image, class->rank);
2202 sig->ret = &class->element_class->this_arg;
2203 sig->pinvoke = TRUE;
2204 sig->hasthis = TRUE;
2205 for (i = 0; i < class->rank; ++i)
2206 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2207 amethod = create_array_method (class, "Address", sig);
2208 methods [method_num++] = amethod;
2209 /* void Set (idx11, [idx2, ...], element) */
2210 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2211 sig->ret = &mono_defaults.void_class->byval_arg;
2212 sig->pinvoke = TRUE;
2213 sig->hasthis = TRUE;
2214 for (i = 0; i < class->rank; ++i)
2215 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2216 sig->params [i] = &class->element_class->byval_arg;
2217 amethod = create_array_method (class, "Set", sig);
2218 methods [method_num++] = amethod;
2220 for (i = 0; i < class->interface_count; i++)
2221 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2223 count = class->method.count;
2224 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2225 for (i = 0; i < count; ++i) {
2226 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2227 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2231 if (MONO_CLASS_IS_INTERFACE (class)) {
2233 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2234 for (i = 0; i < count; ++i) {
2235 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2236 methods [i]->slot = slot++;
2240 mono_image_lock (class->image);
2242 if (!class->methods) {
2243 class->method.count = count;
2245 /* Needed because of the double-checking locking pattern */
2246 mono_memory_barrier ();
2248 class->methods = methods;
2251 mono_image_unlock (class->image);
2255 * mono_class_get_method_by_index:
2257 * Returns class->methods [index], initializing class->methods if neccesary.
2259 * LOCKING: Acquires the loader lock.
2262 mono_class_get_method_by_index (MonoClass *class, int index)
2264 /* Avoid calling setup_methods () if possible */
2265 if (class->generic_class && !class->methods) {
2266 MonoClass *gklass = class->generic_class->container_class;
2269 m = mono_class_inflate_generic_method_full (
2270 gklass->methods [index], class, mono_class_get_context (class));
2272 * If setup_methods () is called later for this class, no duplicates are created,
2273 * since inflate_generic_method guarantees that only one instance of a method
2274 * is created for each context.
2277 mono_class_setup_methods (class);
2278 g_assert (m == class->methods [index]);
2282 mono_class_setup_methods (class);
2283 if (class->exception_type) /*FIXME do proper error handling*/
2285 g_assert (index >= 0 && index < class->method.count);
2286 return class->methods [index];
2291 * mono_class_get_inflated_method:
2293 * Given an inflated class CLASS and a method METHOD which should be a method of
2294 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2297 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2299 MonoClass *gklass = class->generic_class->container_class;
2302 g_assert (method->klass == gklass);
2304 mono_class_setup_methods (gklass);
2305 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2307 for (i = 0; i < gklass->method.count; ++i) {
2308 if (gklass->methods [i] == method) {
2310 return class->methods [i];
2312 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2320 * mono_class_get_vtable_entry:
2322 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2323 * LOCKING: Acquires the loader lock.
2326 mono_class_get_vtable_entry (MonoClass *class, int offset)
2330 if (class->rank == 1) {
2332 * szarrays do not overwrite any methods of Array, so we can avoid
2333 * initializing their vtables in some cases.
2335 mono_class_setup_vtable (class->parent);
2336 if (offset < class->parent->vtable_size)
2337 return class->parent->vtable [offset];
2340 if (class->generic_class) {
2341 MonoClass *gklass = class->generic_class->container_class;
2342 mono_class_setup_vtable (gklass);
2343 m = gklass->vtable [offset];
2345 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2347 mono_class_setup_vtable (class);
2348 if (class->exception_type)
2350 m = class->vtable [offset];
2357 * mono_class_get_vtable_size:
2359 * Return the vtable size for KLASS.
2362 mono_class_get_vtable_size (MonoClass *klass)
2364 mono_class_setup_vtable (klass);
2366 return klass->vtable_size;
2370 * mono_class_setup_properties:
2372 * Initialize class->ext.property and class->ext.properties.
2374 * This method can fail the class.
2377 mono_class_setup_properties (MonoClass *class)
2379 guint startm, endm, i, j;
2380 guint32 cols [MONO_PROPERTY_SIZE];
2381 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2382 MonoProperty *properties;
2386 if (class->ext && class->ext->properties)
2389 if (class->generic_class) {
2390 MonoClass *gklass = class->generic_class->container_class;
2392 mono_class_init (gklass);
2393 mono_class_setup_properties (gklass);
2394 if (gklass->exception_type) {
2395 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2399 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2401 for (i = 0; i < gklass->ext->property.count; i++) {
2402 MonoProperty *prop = &properties [i];
2404 *prop = gklass->ext->properties [i];
2407 prop->get = mono_class_inflate_generic_method_full (
2408 prop->get, class, mono_class_get_context (class));
2410 prop->set = mono_class_inflate_generic_method_full (
2411 prop->set, class, mono_class_get_context (class));
2413 prop->parent = class;
2416 first = gklass->ext->property.first;
2417 count = gklass->ext->property.count;
2419 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2420 count = last - first;
2423 mono_class_setup_methods (class);
2424 if (class->exception_type)
2428 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2429 for (i = first; i < last; ++i) {
2430 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2431 properties [i - first].parent = class;
2432 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2433 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2435 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2436 for (j = startm; j < endm; ++j) {
2439 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2441 if (class->image->uncompressed_metadata)
2442 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2443 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2445 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2447 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2448 case METHOD_SEMANTIC_SETTER:
2449 properties [i - first].set = method;
2451 case METHOD_SEMANTIC_GETTER:
2452 properties [i - first].get = method;
2461 mono_class_alloc_ext (class);
2463 mono_image_lock (class->image);
2465 if (class->ext->properties) {
2466 /* We leak 'properties' which was allocated from the image mempool */
2467 mono_image_unlock (class->image);
2471 class->ext->property.first = first;
2472 class->ext->property.count = count;
2474 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2475 mono_memory_barrier ();
2477 /* Leave this assignment as the last op in the function */
2478 class->ext->properties = properties;
2480 mono_image_unlock (class->image);
2484 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2486 MonoMethod **om, **retval;
2489 for (om = methods, count = 0; *om; ++om, ++count)
2492 retval = g_new0 (MonoMethod*, count + 1);
2494 for (om = methods, count = 0; *om; ++om, ++count)
2495 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2500 /*This method can fail the class.*/
2502 mono_class_setup_events (MonoClass *class)
2505 guint startm, endm, i, j;
2506 guint32 cols [MONO_EVENT_SIZE];
2507 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2511 if (class->ext && class->ext->events)
2514 if (class->generic_class) {
2515 MonoClass *gklass = class->generic_class->container_class;
2516 MonoGenericContext *context = NULL;
2518 mono_class_setup_events (gklass);
2519 if (gklass->exception_type) {
2520 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2524 first = gklass->ext->event.first;
2525 count = gklass->ext->event.count;
2527 events = mono_class_new0 (class, MonoEvent, count);
2530 context = mono_class_get_context (class);
2532 for (i = 0; i < count; i++) {
2533 MonoEvent *event = &events [i];
2534 MonoEvent *gevent = &gklass->ext->events [i];
2536 event->parent = class;
2537 event->name = gevent->name;
2538 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2539 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2540 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2541 #ifndef MONO_SMALL_CONFIG
2542 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2544 event->attrs = gevent->attrs;
2547 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2548 count = last - first;
2551 mono_class_setup_methods (class);
2552 if (class->exception_type) {
2553 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2558 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2559 for (i = first; i < last; ++i) {
2560 MonoEvent *event = &events [i - first];
2562 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2563 event->parent = class;
2564 event->attrs = cols [MONO_EVENT_FLAGS];
2565 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2567 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2568 for (j = startm; j < endm; ++j) {
2571 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2573 if (class->image->uncompressed_metadata)
2574 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2575 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2577 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2579 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2580 case METHOD_SEMANTIC_ADD_ON:
2581 event->add = method;
2583 case METHOD_SEMANTIC_REMOVE_ON:
2584 event->remove = method;
2586 case METHOD_SEMANTIC_FIRE:
2587 event->raise = method;
2589 case METHOD_SEMANTIC_OTHER: {
2590 #ifndef MONO_SMALL_CONFIG
2593 if (event->other == NULL) {
2594 event->other = g_new0 (MonoMethod*, 2);
2596 while (event->other [n])
2598 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2600 event->other [n] = method;
2601 /* NULL terminated */
2602 event->other [n + 1] = NULL;
2613 mono_class_alloc_ext (class);
2615 mono_image_lock (class->image);
2617 if (class->ext->events) {
2618 mono_image_unlock (class->image);
2622 class->ext->event.first = first;
2623 class->ext->event.count = count;
2625 /* Flush any pending writes as we do double checked locking on class->ext.events */
2626 mono_memory_barrier ();
2628 /* Leave this assignment as the last op in the function */
2629 class->ext->events = events;
2631 mono_image_unlock (class->image);
2635 * Global pool of interface IDs, represented as a bitset.
2636 * LOCKING: Protected by the classes lock.
2638 static MonoBitSet *global_interface_bitset = NULL;
2641 * mono_unload_interface_ids:
2642 * @bitset: bit set of interface IDs
2644 * When an image is unloaded, the interface IDs associated with
2645 * the image are put back in the global pool of IDs so the numbers
2649 mono_unload_interface_ids (MonoBitSet *bitset)
2652 mono_bitset_sub (global_interface_bitset, bitset);
2657 mono_unload_interface_id (MonoClass *class)
2659 if (global_interface_bitset && class->interface_id) {
2661 mono_bitset_clear (global_interface_bitset, class->interface_id);
2667 * mono_get_unique_iid:
2670 * Assign a unique integer ID to the interface represented by @class.
2671 * The ID will positive and as small as possible.
2672 * LOCKING: Acquires the classes lock.
2673 * Returns: the new ID.
2676 mono_get_unique_iid (MonoClass *class)
2680 g_assert (MONO_CLASS_IS_INTERFACE (class));
2684 if (!global_interface_bitset) {
2685 global_interface_bitset = mono_bitset_new (128, 0);
2688 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2690 int old_size = mono_bitset_size (global_interface_bitset);
2691 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2692 mono_bitset_free (global_interface_bitset);
2693 global_interface_bitset = new_set;
2696 mono_bitset_set (global_interface_bitset, iid);
2697 /* set the bit also in the per-image set */
2698 if (!class->generic_class) {
2699 if (class->image->interface_bitset) {
2700 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2701 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2702 mono_bitset_free (class->image->interface_bitset);
2703 class->image->interface_bitset = new_set;
2706 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2708 mono_bitset_set (class->image->interface_bitset, iid);
2713 #ifndef MONO_SMALL_CONFIG
2714 if (mono_print_vtable) {
2716 char *type_name = mono_type_full_name (&class->byval_arg);
2717 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2718 generic_id = class->generic_class->context.class_inst->id;
2719 g_assert (generic_id != 0);
2723 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2728 g_assert (iid <= 65535);
2733 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2738 mono_class_setup_interfaces (klass, error);
2739 if (!mono_error_ok (error))
2742 for (i = 0; i < klass->interface_count; i++) {
2743 ic = klass->interfaces [i];
2746 *res = g_ptr_array_new ();
2747 g_ptr_array_add (*res, ic);
2748 mono_class_init (ic);
2749 if (ic->exception_type) {
2750 mono_error_set_type_load_class (error, ic, "Error Loading class");
2754 collect_implemented_interfaces_aux (ic, res, error);
2755 if (!mono_error_ok (error))
2761 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2763 GPtrArray *res = NULL;
2765 collect_implemented_interfaces_aux (klass, &res, error);
2766 if (!mono_error_ok (error)) {
2768 g_ptr_array_free (res, TRUE);
2775 compare_interface_ids (const void *p_key, const void *p_element) {
2776 const MonoClass *key = p_key;
2777 const MonoClass *element = *(MonoClass**) p_element;
2779 return (key->interface_id - element->interface_id);
2782 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2784 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2785 MonoClass **result = mono_binary_search (
2787 klass->interfaces_packed,
2788 klass->interface_offsets_count,
2789 sizeof (MonoClass *),
2790 compare_interface_ids);
2792 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2799 * mono_class_interface_offset_with_variance:
2801 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2802 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2804 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2806 * FIXME figure out MS disambiguation rules and fix this function.
2809 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2810 int i = mono_class_interface_offset (klass, itf);
2811 *non_exact_match = FALSE;
2815 if (!mono_class_has_variant_generic_params (itf))
2818 for (i = 0; i < klass->interface_offsets_count; i++) {
2819 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2820 *non_exact_match = TRUE;
2821 return klass->interface_offsets_packed [i];
2829 print_implemented_interfaces (MonoClass *klass) {
2832 GPtrArray *ifaces = NULL;
2834 int ancestor_level = 0;
2836 name = mono_type_get_full_name (klass);
2837 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2840 for (i = 0; i < klass->interface_offsets_count; i++)
2841 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2842 klass->interfaces_packed [i]->interface_id,
2843 klass->interface_offsets_packed [i],
2844 klass->interfaces_packed [i]->method.count,
2845 klass->interfaces_packed [i]->name_space,
2846 klass->interfaces_packed [i]->name );
2847 printf ("Interface flags: ");
2848 for (i = 0; i <= klass->max_interface_id; i++)
2849 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2850 printf ("(%d,T)", i);
2852 printf ("(%d,F)", i);
2854 printf ("Dump interface flags:");
2855 #ifdef COMPRESSED_INTERFACE_BITMAP
2857 const uint8_t* p = klass->interface_bitmap;
2858 i = klass->max_interface_id;
2860 printf (" %d x 00 %02X", p [0], p [1]);
2866 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2867 printf (" %02X", klass->interface_bitmap [i]);
2870 while (klass != NULL) {
2871 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2872 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2873 if (!mono_error_ok (&error)) {
2874 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2875 mono_error_cleanup (&error);
2876 } else if (ifaces) {
2877 for (i = 0; i < ifaces->len; i++) {
2878 MonoClass *ic = g_ptr_array_index (ifaces, i);
2879 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2880 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2882 mono_class_interface_offset (klass, ic),
2887 g_ptr_array_free (ifaces, TRUE);
2890 klass = klass->parent;
2895 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2898 args [0] = &arg0->byval_arg;
2900 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2904 array_class_get_if_rank (MonoClass *class, guint rank)
2906 return rank ? mono_array_class_get (class, rank) : class;
2910 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2912 valuetype_types [0] = eclass;
2913 if (eclass == mono_defaults.int16_class)
2914 valuetype_types [1] = mono_defaults.uint16_class;
2915 else if (eclass == mono_defaults.uint16_class)
2916 valuetype_types [1] = mono_defaults.int16_class;
2917 else if (eclass == mono_defaults.int32_class)
2918 valuetype_types [1] = mono_defaults.uint32_class;
2919 else if (eclass == mono_defaults.uint32_class)
2920 valuetype_types [1] = mono_defaults.int32_class;
2921 else if (eclass == mono_defaults.int64_class)
2922 valuetype_types [1] = mono_defaults.uint64_class;
2923 else if (eclass == mono_defaults.uint64_class)
2924 valuetype_types [1] = mono_defaults.int64_class;
2925 else if (eclass == mono_defaults.byte_class)
2926 valuetype_types [1] = mono_defaults.sbyte_class;
2927 else if (eclass == mono_defaults.sbyte_class)
2928 valuetype_types [1] = mono_defaults.byte_class;
2929 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2930 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2933 /* this won't be needed once bug #325495 is completely fixed
2934 * though we'll need something similar to know which interfaces to allow
2935 * in arrays when they'll be lazyly created
2937 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2938 * MS returns diferrent types based on which instance is called. For example:
2939 * object obj = new byte[10][];
2940 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2941 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2944 * Fixing this should kill quite some code, save some bits and improve compatibility.
2947 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2949 MonoClass *eclass = class->element_class;
2950 static MonoClass* generic_icollection_class = NULL;
2951 static MonoClass* generic_ienumerable_class = NULL;
2952 static MonoClass* generic_ienumerator_class = NULL;
2953 static MonoClass* generic_ireadonlylist_class = NULL;
2954 static MonoClass* generic_ireadonlycollection_class = NULL;
2955 MonoClass *valuetype_types[2] = { NULL, NULL };
2956 MonoClass **interfaces = NULL;
2957 int i, nifaces, interface_count, real_count, original_rank;
2959 gboolean internal_enumerator;
2960 gboolean eclass_is_valuetype;
2962 if (!mono_defaults.generic_ilist_class) {
2966 internal_enumerator = FALSE;
2967 eclass_is_valuetype = FALSE;
2968 original_rank = eclass->rank;
2969 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2970 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2972 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2974 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2975 original_rank = eclass->rank;
2977 eclass = eclass->element_class;
2978 internal_enumerator = TRUE;
2979 *is_enumerator = TRUE;
2987 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2988 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2990 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2992 if (!generic_icollection_class) {
2993 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2994 "System.Collections.Generic", "ICollection`1");
2995 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2996 "System.Collections.Generic", "IEnumerable`1");
2997 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2998 "System.Collections.Generic", "IEnumerator`1");
2999 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3000 "System.Collections.Generic", "IReadOnlyList`1");
3001 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3002 "System.Collections.Generic", "IReadOnlyCollection`1");
3005 mono_class_init (eclass);
3008 * Arrays in 2.0 need to implement a number of generic interfaces
3009 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3010 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3011 * We collect the types needed to build the
3012 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3013 * the generic interfaces needed to implement.
3015 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3016 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3018 if (eclass->valuetype) {
3019 nifaces = generic_ireadonlylist_class ? 5 : 3;
3020 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3022 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3023 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3024 if (internal_enumerator) {
3026 if (valuetype_types [1])
3030 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3031 interfaces [0] = valuetype_types [0];
3032 if (valuetype_types [1])
3033 interfaces [nifaces] = valuetype_types [1];
3035 eclass_is_valuetype = TRUE;
3038 int idepth = eclass->idepth;
3039 if (!internal_enumerator)
3041 nifaces = generic_ireadonlylist_class ? 2 : 3;
3043 // FIXME: This doesn't seem to work/required for generic params
3044 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3045 mono_class_setup_interface_offsets (eclass);
3047 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3048 /* we add object for interfaces and the supertypes for the other
3049 * types. The last of the supertypes is the element class itself which we
3050 * already created the explicit interfaces for (so we include it for IEnumerator
3051 * and exclude it for arrays).
3053 if (MONO_CLASS_IS_INTERFACE (eclass))
3056 interface_count += idepth;
3057 if (eclass->rank && eclass->element_class->valuetype) {
3058 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3059 if (valuetype_types [1])
3062 /* IList, ICollection, IEnumerable, IReadOnlyList */
3063 interface_count *= nifaces;
3064 real_count = interface_count;
3065 if (internal_enumerator) {
3066 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3067 if (valuetype_types [1])
3070 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3071 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3072 interfaces [0] = mono_defaults.object_class;
3076 for (i = 0; i < idepth; i++) {
3077 mono_class_init (eclass->supertypes [i]);
3078 interfaces [j] = eclass->supertypes [i];
3082 if (all_interfaces) {
3083 for (i = 0; i < eclass->interface_offsets_count; i++) {
3084 interfaces [j] = eclass->interfaces_packed [i];
3088 for (i = 0; i < eclass->interface_count; i++) {
3089 interfaces [j] = eclass->interfaces [i];
3093 if (valuetype_types [1]) {
3094 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3099 /* instantiate the generic interfaces */
3100 for (i = 0; i < interface_count; i += nifaces) {
3101 MonoClass *iface = interfaces [i];
3103 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3104 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3106 if (eclass->valuetype) {
3107 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3108 if (generic_ireadonlylist_class) {
3109 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3110 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3113 if (!generic_ireadonlylist_class)
3114 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3117 if (internal_enumerator) {
3119 /* instantiate IEnumerator<iface> */
3120 for (i = 0; i < interface_count; i++) {
3121 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3123 j = interface_count;
3124 if (!eclass_is_valuetype) {
3125 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3126 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3129 for (i = 0; i < eclass->idepth; i++) {
3130 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3134 for (i = 0; i < eclass->interface_offsets_count; i++) {
3135 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3139 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3141 if (valuetype_types [1])
3142 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3146 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3147 for (i = 0; i < real_count; ++i) {
3148 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3149 g_print ("%s implements %s\n", type_name, name);
3160 find_array_interface (MonoClass *klass, const char *name)
3163 for (i = 0; i < klass->interface_count; ++i) {
3164 if (strcmp (klass->interfaces [i]->name, name) == 0)
3171 * Return the number of virtual methods.
3172 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3173 * Return -1 on failure.
3174 * FIXME It would be nice if this information could be cached somewhere.
3177 count_virtual_methods (MonoClass *class)
3181 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3183 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3184 mono_class_setup_methods (class);
3185 if (class->exception_type)
3188 for (i = 0; i < class->method.count; ++i) {
3189 flags = class->methods [i]->flags;
3190 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3194 for (i = 0; i < class->method.count; ++i) {
3195 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3197 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3205 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3213 m = (l + num_ifaces) / 2;
3214 if (interfaces_full [m] == ic)
3216 if (l == num_ifaces)
3218 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3227 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3229 int i = find_interface (num_ifaces, interfaces_full, ic);
3231 return interface_offsets_full [i];
3236 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3238 int i = find_interface (num_ifaces, interfaces_full, ic);
3242 interface_offsets_full [i] = offset;
3245 for (i = 0; i < num_ifaces; ++i) {
3246 if (interfaces_full [i]) {
3248 if (interfaces_full [i]->interface_id < ic->interface_id)
3251 while (end < num_ifaces && interfaces_full [end]) end++;
3252 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3253 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3255 interfaces_full [i] = ic;
3256 interface_offsets_full [i] = offset;
3262 #ifdef COMPRESSED_INTERFACE_BITMAP
3265 * Compressed interface bitmap design.
3267 * Interface bitmaps take a large amount of memory, because their size is
3268 * linear with the maximum interface id assigned in the process (each interface
3269 * is assigned a unique id as it is loaded). The number of interface classes
3270 * is high because of the many implicit interfaces implemented by arrays (we'll
3271 * need to lazy-load them in the future).
3272 * Most classes implement a very small number of interfaces, so the bitmap is
3273 * sparse. This bitmap needs to be checked by interface casts, so access to the
3274 * needed bit must be fast and doable with few jit instructions.
3276 * The current compression format is as follows:
3277 * *) it is a sequence of one or more two-byte elements
3278 * *) the first byte in the element is the count of empty bitmap bytes
3279 * at the current bitmap position
3280 * *) the second byte in the element is an actual bitmap byte at the current
3283 * As an example, the following compressed bitmap bytes:
3284 * 0x07 0x01 0x00 0x7
3285 * correspond to the following bitmap:
3286 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3288 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3289 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3290 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3294 * mono_compress_bitmap:
3295 * @dest: destination buffer
3296 * @bitmap: bitmap buffer
3297 * @size: size of @bitmap in bytes
3299 * This is a mono internal function.
3300 * The @bitmap data is compressed into a format that is small but
3301 * still searchable in few instructions by the JIT and runtime.
3302 * The compressed data is stored in the buffer pointed to by the
3303 * @dest array. Passing a #NULL value for @dest allows to just compute
3304 * the size of the buffer.
3305 * This compression algorithm assumes the bits set in the bitmap are
3306 * few and far between, like in interface bitmaps.
3307 * Returns: the size of the compressed bitmap in bytes.
3310 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3314 const uint8_t *end = bitmap + size;
3315 while (bitmap < end) {
3316 if (*bitmap || numz == 255) {
3340 * mono_class_interface_match:
3341 * @bitmap: a compressed bitmap buffer
3342 * @id: the index to check in the bitmap
3344 * This is a mono internal function.
3345 * Checks if a bit is set in a compressed interface bitmap. @id must
3346 * be already checked for being smaller than the maximum id encoded in the
3349 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3353 mono_class_interface_match (const uint8_t *bitmap, int id)
3356 id -= bitmap [0] * 8;
3360 return bitmap [1] & (1 << id);
3369 * LOCKING: this is supposed to be called with the loader lock held.
3370 * Return -1 on failure and set exception_type
3373 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3377 int i, j, max_iid, num_ifaces;
3378 MonoClass **interfaces_full = NULL;
3379 int *interface_offsets_full = NULL;
3381 GPtrArray **ifaces_array = NULL;
3382 int interface_offsets_count;
3383 MonoClass **array_interfaces = NULL;
3384 int num_array_interfaces;
3385 int is_enumerator = FALSE;
3387 mono_class_setup_supertypes (class);
3389 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3390 * implicit interfaces have the property that they are assigned the same slot in the
3391 * vtables for compatible interfaces
3393 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3395 /* compute maximum number of slots and maximum interface id */
3397 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3398 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3399 for (j = 0; j < class->idepth; j++) {
3400 k = class->supertypes [j];
3401 num_ifaces += k->interface_count;
3402 for (i = 0; i < k->interface_count; i++) {
3403 ic = k->interfaces [i];
3406 mono_class_init (ic);
3408 if (max_iid < ic->interface_id)
3409 max_iid = ic->interface_id;
3411 ifaces = mono_class_get_implemented_interfaces (k, &error);
3412 if (!mono_error_ok (&error)) {
3413 char *name = mono_type_get_full_name (k);
3414 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3416 mono_error_cleanup (&error);
3421 num_ifaces += ifaces->len;
3422 for (i = 0; i < ifaces->len; ++i) {
3423 ic = g_ptr_array_index (ifaces, i);
3424 if (max_iid < ic->interface_id)
3425 max_iid = ic->interface_id;
3427 ifaces_array [j] = ifaces;
3431 for (i = 0; i < num_array_interfaces; ++i) {
3432 ic = array_interfaces [i];
3433 mono_class_init (ic);
3434 if (max_iid < ic->interface_id)
3435 max_iid = ic->interface_id;
3438 if (MONO_CLASS_IS_INTERFACE (class)) {
3440 if (max_iid < class->interface_id)
3441 max_iid = class->interface_id;
3443 class->max_interface_id = max_iid;
3444 /* compute vtable offset for interfaces */
3445 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3446 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3448 for (i = 0; i < num_ifaces; i++) {
3449 interface_offsets_full [i] = -1;
3452 /* skip the current class */
3453 for (j = 0; j < class->idepth - 1; j++) {
3454 k = class->supertypes [j];
3455 ifaces = ifaces_array [j];
3458 for (i = 0; i < ifaces->len; ++i) {
3460 ic = g_ptr_array_index (ifaces, i);
3462 /*Force the sharing of interface offsets between parent and subtypes.*/
3463 io = mono_class_interface_offset (k, ic);
3465 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3470 g_assert (class == class->supertypes [class->idepth - 1]);
3471 ifaces = ifaces_array [class->idepth - 1];
3473 for (i = 0; i < ifaces->len; ++i) {
3475 ic = g_ptr_array_index (ifaces, i);
3476 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3478 count = count_virtual_methods (ic);
3480 char *name = mono_type_get_full_name (ic);
3481 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3490 if (MONO_CLASS_IS_INTERFACE (class))
3491 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3493 if (num_array_interfaces) {
3494 if (is_enumerator) {
3495 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3496 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3497 g_assert (ienumerator_offset >= 0);
3498 for (i = 0; i < num_array_interfaces; ++i) {
3499 ic = array_interfaces [i];
3500 if (strcmp (ic->name, "IEnumerator`1") == 0)
3501 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3503 g_assert_not_reached ();
3504 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/
3507 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3508 int ilist_iface_idx = find_array_interface (class, "IList`1");
3509 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3510 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3511 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3512 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3513 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3514 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3515 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3516 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3517 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3518 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3519 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3520 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3521 for (i = 0; i < num_array_interfaces; ++i) {
3523 ic = array_interfaces [i];
3524 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3525 offset = ilist_offset;
3526 else if (strcmp (ic->name, "ICollection`1") == 0)
3527 offset = icollection_offset;
3528 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3529 offset = ienumerable_offset;
3530 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3531 offset = ireadonlylist_offset;
3532 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3533 offset = ireadonlycollection_offset;
3535 g_assert_not_reached ();
3536 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3537 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3542 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3543 if (interface_offsets_full [i] != -1) {
3544 interface_offsets_count ++;
3549 * We might get called multiple times:
3550 * - mono_class_init ()
3551 * - mono_class_setup_vtable ().
3552 * - mono_class_setup_interface_offsets ().
3553 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3554 * means we have to overwrite those when called from other places (#4440).
3556 if (class->interfaces_packed && !overwrite) {
3557 g_assert (class->interface_offsets_count == interface_offsets_count);
3561 class->interface_offsets_count = interface_offsets_count;
3562 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3563 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3564 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3565 #ifdef COMPRESSED_INTERFACE_BITMAP
3566 bitmap = g_malloc0 (bsize);
3568 bitmap = mono_class_alloc0 (class, bsize);
3570 for (i = 0; i < interface_offsets_count; i++) {
3571 int id = interfaces_full [i]->interface_id;
3572 bitmap [id >> 3] |= (1 << (id & 7));
3573 class->interfaces_packed [i] = interfaces_full [i];
3574 class->interface_offsets_packed [i] = interface_offsets_full [i];
3575 /*if (num_array_interfaces)
3576 g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&class->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
3578 #ifdef COMPRESSED_INTERFACE_BITMAP
3579 i = mono_compress_bitmap (NULL, bitmap, bsize);
3580 class->interface_bitmap = mono_class_alloc0 (class, i);
3581 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3584 class->interface_bitmap = bitmap;
3589 g_free (interfaces_full);
3590 g_free (interface_offsets_full);
3591 g_free (array_interfaces);
3592 for (i = 0; i < class->idepth; i++) {
3593 ifaces = ifaces_array [i];
3595 g_ptr_array_free (ifaces, TRUE);
3597 g_free (ifaces_array);
3599 //printf ("JUST DONE: ");
3600 //print_implemented_interfaces (class);
3606 * Setup interface offsets for interfaces.
3608 * - class->max_interface_id
3609 * - class->interface_offsets_count
3610 * - class->interfaces_packed
3611 * - class->interface_offsets_packed
3612 * - class->interface_bitmap
3614 * This function can fail @class.
3617 mono_class_setup_interface_offsets (MonoClass *class)
3619 mono_loader_lock ();
3621 setup_interface_offsets (class, 0, FALSE);
3623 mono_loader_unlock ();
3626 /*Checks if @klass has @parent as one of it's parents type gtd
3630 * Bar<T> : Foo<Bar<Bar<T>>>
3634 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3636 klass = mono_class_get_generic_type_definition (klass);
3637 parent = mono_class_get_generic_type_definition (parent);
3638 mono_class_setup_supertypes (klass);
3639 mono_class_setup_supertypes (parent);
3641 return klass->idepth >= parent->idepth &&
3642 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3646 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3648 MonoGenericInst *ginst;
3650 if (!class->generic_class) {
3651 mono_class_setup_vtable_full (class, in_setup);
3652 return class->exception_type == 0;
3655 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3656 if (class->generic_class->container_class->exception_type) {
3657 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3661 ginst = class->generic_class->context.class_inst;
3662 for (i = 0; i < ginst->type_argc; ++i) {
3664 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3666 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3667 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3668 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3670 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3671 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3679 * mono_class_setup_vtable:
3681 * Creates the generic vtable of CLASS.
3682 * Initializes the following fields in MonoClass:
3685 * Plus all the fields initialized by setup_interface_offsets ().
3686 * If there is an error during vtable construction, class->exception_type is set.
3688 * LOCKING: Acquires the loader lock.
3691 mono_class_setup_vtable (MonoClass *class)
3693 mono_class_setup_vtable_full (class, NULL);
3697 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3699 MonoMethod **overrides;
3700 MonoGenericContext *context;
3708 if (MONO_CLASS_IS_INTERFACE (class)) {
3709 /* This sets method->slot for all methods if this is an interface */
3710 mono_class_setup_methods (class);
3714 if (class->exception_type)
3717 if (g_list_find (in_setup, class))
3720 mono_loader_lock ();
3722 if (class->vtable) {
3723 mono_loader_unlock ();
3727 mono_stats.generic_vtable_count ++;
3728 in_setup = g_list_prepend (in_setup, class);
3730 if (class->generic_class) {
3731 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3732 mono_loader_unlock ();
3733 g_list_remove (in_setup, class);
3737 context = mono_class_get_context (class);
3738 type_token = class->generic_class->container_class->type_token;
3740 context = (MonoGenericContext *) class->generic_container;
3741 type_token = class->type_token;
3744 if (image_is_dynamic (class->image)) {
3745 /* Generic instances can have zero method overrides without causing any harm.
3746 * This is true since we don't do layout all over again for them, we simply inflate
3747 * the layout of the parent.
3749 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3751 /* The following call fails if there are missing methods in the type */
3752 /* FIXME it's probably a good idea to avoid this for generic instances. */
3753 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3757 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3759 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3763 mono_loader_unlock ();
3764 g_list_remove (in_setup, class);
3769 #define DEBUG_INTERFACE_VTABLE_CODE 0
3770 #define TRACE_INTERFACE_VTABLE_CODE 0
3771 #define VERIFY_INTERFACE_VTABLE_CODE 0
3772 #define VTABLE_SELECTOR (1)
3774 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3775 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3776 if (!(VTABLE_SELECTOR)) break; \
3780 #define DEBUG_INTERFACE_VTABLE(stmt)
3783 #if TRACE_INTERFACE_VTABLE_CODE
3784 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3785 if (!(VTABLE_SELECTOR)) break; \
3789 #define TRACE_INTERFACE_VTABLE(stmt)
3792 #if VERIFY_INTERFACE_VTABLE_CODE
3793 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3794 if (!(VTABLE_SELECTOR)) break; \
3798 #define VERIFY_INTERFACE_VTABLE(stmt)
3802 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3804 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3808 GString *res = g_string_new ("");
3810 g_string_append_c (res, '(');
3811 for (i = 0; i < sig->param_count; ++i) {
3813 g_string_append_c (res, ',');
3814 mono_type_get_desc (res, sig->params [i], include_namespace);
3816 g_string_append (res, ")=>");
3817 if (sig->ret != NULL) {
3818 mono_type_get_desc (res, sig->ret, include_namespace);
3820 g_string_append (res, "NULL");
3823 g_string_free (res, FALSE);
3827 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3828 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3829 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3830 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3838 is_wcf_hack_disabled (void)
3840 static gboolean disabled;
3841 static gboolean inited = FALSE;
3843 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3850 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
3851 MonoMethodSignature *cmsig, *imsig;
3852 if (strcmp (im->name, cm->name) == 0) {
3853 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3854 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3857 if (! slot_is_empty) {
3858 if (require_newslot) {
3859 if (! interface_is_explicitly_implemented_by_class) {
3860 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3863 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3864 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3868 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3871 cmsig = mono_method_signature (cm);
3872 imsig = mono_method_signature (im);
3873 if (!cmsig || !imsig) {
3874 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3878 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3879 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3880 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3881 TRACE_INTERFACE_VTABLE (printf ("]"));
3884 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3885 /* CAS - SecurityAction.InheritanceDemand on interface */
3886 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3887 mono_secman_inheritancedemand_method (cm, im);
3890 if (mono_security_core_clr_enabled ())
3891 mono_security_core_clr_check_override (class, cm, im);
3893 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3894 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3895 char *body_name = mono_method_full_name (cm, TRUE);
3896 char *decl_name = mono_method_full_name (im, TRUE);
3897 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
3905 MonoClass *ic = im->klass;
3906 const char *ic_name_space = ic->name_space;
3907 const char *ic_name = ic->name;
3910 if (! require_newslot) {
3911 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3914 if (cm->klass->rank == 0) {
3915 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3918 cmsig = mono_method_signature (cm);
3919 imsig = mono_method_signature (im);
3920 if (!cmsig || !imsig) {
3921 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3925 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3926 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3927 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3928 TRACE_INTERFACE_VTABLE (printf ("]"));
3931 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3932 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3935 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3936 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3939 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))) {
3940 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3944 subname = strstr (cm->name, ic_name_space);
3945 if (subname != cm->name) {
3946 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3949 subname += strlen (ic_name_space);
3950 if (subname [0] != '.') {
3951 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3955 if (strstr (subname, ic_name) != subname) {
3956 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3959 subname += strlen (ic_name);
3960 if (subname [0] != '.') {
3961 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3965 if (strcmp (subname, im->name) != 0) {
3966 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3970 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3971 /* CAS - SecurityAction.InheritanceDemand on interface */
3972 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3973 mono_secman_inheritancedemand_method (cm, im);
3976 if (mono_security_core_clr_enabled ())
3977 mono_security_core_clr_check_override (class, cm, im);
3979 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3980 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3981 char *body_name = mono_method_full_name (cm, TRUE);
3982 char *decl_name = mono_method_full_name (im, TRUE);
3983 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
3993 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3995 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3996 MonoMethod *method = key;
3997 MonoMethod *override = value;
3998 MonoClass *method_class = mono_method_get_class (method);
3999 MonoClass *override_class = mono_method_get_class (override);
4001 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4002 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4003 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4006 print_overrides (GHashTable *override_map, const char *message) {
4008 printf ("Override map \"%s\" START:\n", message);
4009 g_hash_table_foreach (override_map, foreach_override, NULL);
4010 printf ("Override map \"%s\" END.\n", message);
4012 printf ("Override map \"%s\" EMPTY.\n", message);
4016 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4017 char *full_name = mono_type_full_name (&class->byval_arg);
4021 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4023 if (print_interfaces) {
4024 print_implemented_interfaces (class);
4025 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4028 if (class->parent) {
4029 parent_size = class->parent->vtable_size;
4033 for (i = 0; i < size; ++i) {
4034 MonoMethod *cm = vtable [i];
4035 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4036 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4038 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4046 #if VERIFY_INTERFACE_VTABLE_CODE
4048 mono_method_try_get_vtable_index (MonoMethod *method)
4050 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4051 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4052 if (imethod->declaring->is_generic)
4053 return imethod->declaring->slot;
4055 return method->slot;
4059 mono_class_verify_vtable (MonoClass *class)
4062 char *full_name = mono_type_full_name (&class->byval_arg);
4064 printf ("*** Verifying VTable of class '%s' \n", full_name);
4068 if (!class->methods)
4071 for (i = 0; i < class->method.count; ++i) {
4072 MonoMethod *cm = class->methods [i];
4075 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4079 full_name = mono_method_full_name (cm, TRUE);
4081 slot = mono_method_try_get_vtable_index (cm);
4083 if (slot >= class->vtable_size) {
4084 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4088 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4089 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4090 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4091 g_free (other_name);
4094 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4101 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4103 char *method_signature;
4106 for (index = 0; index < onum; ++index) {
4107 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4108 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4110 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4111 type_name = mono_type_full_name (&class->byval_arg);
4112 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4113 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4114 g_free (method_signature);
4116 mono_class_setup_methods (class);
4117 if (class->exception_type) {
4118 char *name = mono_type_get_full_name (class);
4119 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4123 for (index = 0; index < class->method.count; ++index) {
4124 MonoMethod *cm = class->methods [index];
4125 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4127 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4128 g_free (method_signature);
4133 mono_method_get_method_definition (MonoMethod *method)
4135 while (method->is_inflated)
4136 method = ((MonoMethodInflated*)method)->declaring;
4141 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4145 for (i = 0; i < onum; ++i) {
4146 MonoMethod *decl = overrides [i * 2];
4147 MonoMethod *body = overrides [i * 2 + 1];
4149 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4150 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4154 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4155 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4156 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4158 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4162 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4163 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4164 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4166 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4170 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4171 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4175 body = mono_method_get_method_definition (body);
4176 decl = mono_method_get_method_definition (decl);
4178 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4179 char *body_name = mono_method_full_name (body, TRUE);
4180 char *decl_name = mono_method_full_name (decl, TRUE);
4181 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4191 mono_class_need_stelemref_method (MonoClass *class)
4193 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4197 * LOCKING: this is supposed to be called with the loader lock held.
4200 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4204 MonoMethod **vtable;
4205 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4206 GPtrArray *ifaces = NULL;
4207 GHashTable *override_map = NULL;
4208 gboolean security_enabled = mono_security_enabled ();
4210 gpointer class_iter;
4211 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4212 int first_non_interface_slot;
4214 GSList *virt_methods = NULL, *l;
4215 int stelemref_slot = 0;
4220 if (overrides && !verify_class_overrides (class, overrides, onum))
4223 ifaces = mono_class_get_implemented_interfaces (class, &error);
4224 if (!mono_error_ok (&error)) {
4225 char *name = mono_type_get_full_name (class);
4226 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4228 mono_error_cleanup (&error);
4230 } else if (ifaces) {
4231 for (i = 0; i < ifaces->len; i++) {
4232 MonoClass *ic = g_ptr_array_index (ifaces, i);
4233 max_vtsize += ic->method.count;
4235 g_ptr_array_free (ifaces, TRUE);
4239 if (class->parent) {
4240 mono_class_init (class->parent);
4241 mono_class_setup_vtable_full (class->parent, in_setup);
4243 if (class->parent->exception_type) {
4244 char *name = mono_type_get_full_name (class->parent);
4245 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4250 max_vtsize += class->parent->vtable_size;
4251 cur_slot = class->parent->vtable_size;
4254 max_vtsize += class->method.count;
4256 /*Array have a slot for stelemref*/
4257 if (mono_class_need_stelemref_method (class)) {
4258 stelemref_slot = cur_slot;
4263 vtable = alloca (sizeof (gpointer) * max_vtsize);
4264 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4266 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4268 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4269 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4272 max_iid = class->max_interface_id;
4273 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4275 /* Optimized version for generic instances */
4276 if (class->generic_class) {
4278 MonoClass *gklass = class->generic_class->container_class;
4281 mono_class_setup_vtable_full (gklass, in_setup);
4282 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4283 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4287 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4288 class->vtable_size = gklass->vtable_size;
4289 for (i = 0; i < gklass->vtable_size; ++i)
4290 if (gklass->vtable [i]) {
4291 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4292 if (!mono_error_ok (&error)) {
4293 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4294 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4296 mono_error_cleanup (&error);
4300 tmp [i]->slot = gklass->vtable [i]->slot;
4302 mono_memory_barrier ();
4303 class->vtable = tmp;
4305 /* Have to set method->slot for abstract virtual methods */
4306 if (class->methods && gklass->methods) {
4307 for (i = 0; i < class->method.count; ++i)
4308 if (class->methods [i]->slot == -1)
4309 class->methods [i]->slot = gklass->methods [i]->slot;
4315 if (class->parent && class->parent->vtable_size) {
4316 MonoClass *parent = class->parent;
4319 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4321 // Also inherit parent interface vtables, just as a starting point.
4322 // This is needed otherwise bug-77127.exe fails when the property methods
4323 // have different names in the iterface and the class, because for child
4324 // classes the ".override" information is not used anymore.
4325 for (i = 0; i < parent->interface_offsets_count; i++) {
4326 MonoClass *parent_interface = parent->interfaces_packed [i];
4327 int interface_offset = mono_class_interface_offset (class, parent_interface);
4328 /*FIXME this is now dead code as this condition will never hold true.
4329 Since interface offsets are inherited then the offset of an interface implemented
4330 by a parent will never be the out of it's vtable boundary.
4332 if (interface_offset >= parent->vtable_size) {
4333 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4336 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4337 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4338 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4339 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4340 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4341 parent_interface_offset + j, parent_interface_offset, j,
4342 interface_offset + j, interface_offset, j));
4349 /*Array have a slot for stelemref*/
4350 if (mono_class_need_stelemref_method (class)) {
4351 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4353 method->slot = stelemref_slot;
4355 g_assert (method->slot == stelemref_slot);
4357 vtable [stelemref_slot] = method;
4360 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4361 /* override interface methods */
4362 for (i = 0; i < onum; i++) {
4363 MonoMethod *decl = overrides [i*2];
4364 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4366 dslot = mono_method_get_vtable_slot (decl);
4368 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4372 dslot += mono_class_interface_offset (class, decl->klass);
4373 vtable [dslot] = overrides [i*2 + 1];
4374 vtable [dslot]->slot = dslot;
4376 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4378 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4380 if (mono_security_core_clr_enabled ())
4381 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4384 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4385 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4388 * Create a list of virtual methods to avoid calling
4389 * mono_class_get_virtual_methods () which is slow because of the metadata
4393 gpointer iter = NULL;
4396 virt_methods = NULL;
4397 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4398 virt_methods = g_slist_prepend (virt_methods, cm);
4400 if (class->exception_type)
4404 // Loop on all implemented interfaces...
4405 for (i = 0; i < class->interface_offsets_count; i++) {
4406 MonoClass *parent = class->parent;
4408 gboolean interface_is_explicitly_implemented_by_class;
4411 ic = class->interfaces_packed [i];
4412 ic_offset = mono_class_interface_offset (class, ic);
4414 mono_class_setup_methods (ic);
4415 if (ic->exception_type)
4418 // Check if this interface is explicitly implemented (instead of just inherited)
4419 if (parent != NULL) {
4420 int implemented_interfaces_index;
4421 interface_is_explicitly_implemented_by_class = FALSE;
4422 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4423 if (ic == class->interfaces [implemented_interfaces_index]) {
4424 interface_is_explicitly_implemented_by_class = TRUE;
4429 interface_is_explicitly_implemented_by_class = TRUE;
4432 // Loop on all interface methods...
4433 for (im_index = 0; im_index < ic->method.count; im_index++) {
4434 MonoMethod *im = ic->methods [im_index];
4435 int im_slot = ic_offset + im->slot;
4436 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4438 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4441 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4443 // If there is an explicit implementation, just use it right away,
4444 // otherwise look for a matching method
4445 if (override_im == NULL) {
4450 // First look for a suitable method among the class methods
4452 for (l = virt_methods; l; l = l->next) {
4454 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)));
4455 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4456 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4457 vtable [im_slot] = cm;
4458 /* Why do we need this? */
4463 TRACE_INTERFACE_VTABLE (printf ("\n"));
4464 if (class->exception_type) /*Might be set by check_interface_method_override*/
4468 // If the slot is still empty, look in all the inherited virtual methods...
4469 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4470 MonoClass *parent = class->parent;
4471 // Reverse order, so that last added methods are preferred
4472 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4473 MonoMethod *cm = parent->vtable [cm_index];
4475 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));
4476 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4477 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4478 vtable [im_slot] = cm;
4479 /* Why do we need this? */
4485 if (class->exception_type) /*Might be set by check_interface_method_override*/
4487 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4491 g_assert (vtable [im_slot] == override_im);
4496 // If the class is not abstract, check that all its interface slots are full.
4497 // The check is done here and not directly at the end of the loop above because
4498 // it can happen (for injected generic array interfaces) that the same slot is
4499 // processed multiple times (those interfaces have overlapping slots), and it
4500 // will not always be the first pass the one that fills the slot.
4501 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4502 for (i = 0; i < class->interface_offsets_count; i++) {
4506 ic = class->interfaces_packed [i];
4507 ic_offset = mono_class_interface_offset (class, ic);
4509 for (im_index = 0; im_index < ic->method.count; im_index++) {
4510 MonoMethod *im = ic->methods [im_index];
4511 int im_slot = ic_offset + im->slot;
4513 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4516 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4517 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4518 if (vtable [im_slot] == NULL) {
4519 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4526 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4528 for (l = virt_methods; l; l = l->next) {
4531 * If the method is REUSE_SLOT, we must check in the
4532 * base class for a method to override.
4534 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4536 for (k = class->parent; k ; k = k->parent) {
4541 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4542 MonoMethodSignature *cmsig, *m1sig;
4544 cmsig = mono_method_signature (cm);
4545 m1sig = mono_method_signature (m1);
4547 if (!cmsig || !m1sig) {
4548 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4552 if (!strcmp(cm->name, m1->name) &&
4553 mono_metadata_signature_equal (cmsig, m1sig)) {
4555 /* CAS - SecurityAction.InheritanceDemand */
4556 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4557 mono_secman_inheritancedemand_method (cm, m1);
4560 if (mono_security_core_clr_enabled ())
4561 mono_security_core_clr_check_override (class, cm, m1);
4563 slot = mono_method_get_vtable_slot (m1);
4567 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4568 char *body_name = mono_method_full_name (cm, TRUE);
4569 char *decl_name = mono_method_full_name (m1, TRUE);
4570 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4576 g_assert (cm->slot < max_vtsize);
4578 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4579 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4580 mono_method_full_name (m1, 1), m1,
4581 mono_method_full_name (cm, 1), cm));
4582 g_hash_table_insert (override_map, m1, cm);
4586 if (k->exception_type)
4596 /*Non final newslot methods must be given a non-interface vtable slot*/
4597 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4601 cm->slot = cur_slot++;
4603 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4604 vtable [cm->slot] = cm;
4607 /* override non interface methods */
4608 for (i = 0; i < onum; i++) {
4609 MonoMethod *decl = overrides [i*2];
4610 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4611 g_assert (decl->slot != -1);
4612 vtable [decl->slot] = overrides [i*2 + 1];
4613 overrides [i * 2 + 1]->slot = decl->slot;
4615 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4616 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4617 mono_method_full_name (decl, 1), decl,
4618 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4619 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4621 if (mono_security_core_clr_enabled ())
4622 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4627 * If a method occupies more than one place in the vtable, and it is
4628 * overriden, then change the other occurances too.
4633 for (i = 0; i < max_vtsize; ++i)
4635 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4637 cm = g_hash_table_lookup (override_map, vtable [i]);
4642 g_hash_table_destroy (override_map);
4643 override_map = NULL;
4646 g_slist_free (virt_methods);
4647 virt_methods = NULL;
4649 /* Ensure that all vtable slots are filled with concrete instance methods */
4650 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4651 for (i = 0; i < cur_slot; ++i) {
4652 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4653 char *type_name = mono_type_get_full_name (class);
4654 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4655 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4657 g_free (method_name);
4663 if (class->generic_class) {
4664 MonoClass *gklass = class->generic_class->container_class;
4666 mono_class_init (gklass);
4668 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4670 /* Check that the vtable_size value computed in mono_class_init () is correct */
4671 if (class->vtable_size)
4672 g_assert (cur_slot == class->vtable_size);
4673 class->vtable_size = cur_slot;
4676 /* Try to share the vtable with our parent. */
4677 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4678 mono_memory_barrier ();
4679 class->vtable = class->parent->vtable;
4681 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4682 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4683 mono_memory_barrier ();
4684 class->vtable = tmp;
4687 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4688 if (mono_print_vtable) {
4691 print_implemented_interfaces (class);
4693 for (i = 0; i <= max_iid; i++)
4694 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4697 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4698 class->vtable_size, icount);
4700 for (i = 0; i < cur_slot; ++i) {
4705 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4706 mono_method_full_name (cm, TRUE));
4712 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4713 class->name, max_iid);
4715 for (i = 0; i < class->interface_count; i++) {
4716 ic = class->interfaces [i];
4717 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4718 mono_class_interface_offset (class, ic),
4719 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4722 for (k = class->parent; k ; k = k->parent) {
4723 for (i = 0; i < k->interface_count; i++) {
4724 ic = k->interfaces [i];
4725 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4726 mono_class_interface_offset (class, ic),
4727 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4733 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4738 char *name = mono_type_get_full_name (class);
4739 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4742 g_hash_table_destroy (override_map);
4744 g_slist_free (virt_methods);
4749 * mono_method_get_vtable_slot:
4751 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4752 * LOCKING: Acquires the loader lock.
4754 * FIXME Use proper MonoError machinery here.
4757 mono_method_get_vtable_slot (MonoMethod *method)
4759 if (method->slot == -1) {
4760 mono_class_setup_vtable (method->klass);
4761 if (method->klass->exception_type)
4763 if (method->slot == -1) {
4767 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4768 g_assert (method->klass->generic_class);
4769 gklass = method->klass->generic_class->container_class;
4770 mono_class_setup_methods (method->klass);
4771 g_assert (method->klass->methods);
4772 for (i = 0; i < method->klass->method.count; ++i) {
4773 if (method->klass->methods [i] == method)
4776 g_assert (i < method->klass->method.count);
4777 g_assert (gklass->methods);
4778 method->slot = gklass->methods [i]->slot;
4780 g_assert (method->slot != -1);
4782 return method->slot;
4786 * mono_method_get_vtable_index:
4789 * Returns the index into the runtime vtable to access the method or,
4790 * in the case of a virtual generic method, the virtual generic method
4791 * thunk. Returns -1 on failure.
4793 * FIXME Use proper MonoError machinery here.
4796 mono_method_get_vtable_index (MonoMethod *method)
4798 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4799 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4800 if (imethod->declaring->is_generic)
4801 return mono_method_get_vtable_slot (imethod->declaring);
4803 return mono_method_get_vtable_slot (method);
4806 static MonoMethod *default_ghc = NULL;
4807 static MonoMethod *default_finalize = NULL;
4808 static int finalize_slot = -1;
4809 static int ghc_slot = -1;
4812 initialize_object_slots (MonoClass *class)
4817 if (class == mono_defaults.object_class) {
4818 mono_class_setup_vtable (class);
4819 for (i = 0; i < class->vtable_size; ++i) {
4820 MonoMethod *cm = class->vtable [i];
4822 if (!strcmp (cm->name, "GetHashCode"))
4824 else if (!strcmp (cm->name, "Finalize"))
4828 g_assert (ghc_slot > 0);
4829 default_ghc = class->vtable [ghc_slot];
4831 g_assert (finalize_slot > 0);
4832 default_finalize = class->vtable [finalize_slot];
4837 MonoMethod *array_method;
4839 } GenericArrayMethodInfo;
4841 static int generic_array_method_num = 0;
4842 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4845 generic_array_methods (MonoClass *class)
4847 int i, count_generic = 0;
4848 GList *list = NULL, *tmp;
4849 if (generic_array_method_num)
4850 return generic_array_method_num;
4851 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4852 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4853 for (i = 0; i < class->parent->method.count; i++) {
4854 MonoMethod *m = class->parent->methods [i];
4855 if (!strncmp (m->name, "InternalArray__", 15)) {
4857 list = g_list_prepend (list, m);
4860 list = g_list_reverse (list);
4861 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4863 for (tmp = list; tmp; tmp = tmp->next) {
4864 const char *mname, *iname;
4866 MonoMethod *m = tmp->data;
4867 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4868 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4870 generic_array_method_info [i].array_method = m;
4871 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4872 iname = "System.Collections.Generic.ICollection`1.";
4873 mname = m->name + 27;
4874 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4875 iname = "System.Collections.Generic.IEnumerable`1.";
4876 mname = m->name + 27;
4877 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4878 iname = "System.Collections.Generic.IReadOnlyList`1.";
4879 mname = m->name + strlen (ireadonlylist_prefix);
4880 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4881 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4882 mname = m->name + strlen (ireadonlycollection_prefix);
4883 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4884 iname = "System.Collections.Generic.IList`1.";
4885 mname = m->name + 15;
4887 g_assert_not_reached ();
4890 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4891 strcpy (name, iname);
4892 strcpy (name + strlen (iname), mname);
4893 generic_array_method_info [i].name = name;
4896 /*g_print ("array generic methods: %d\n", count_generic);*/
4898 generic_array_method_num = count_generic;
4900 return generic_array_method_num;
4904 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4906 MonoGenericContext tmp_context;
4909 tmp_context.class_inst = NULL;
4910 tmp_context.method_inst = iface->generic_class->context.class_inst;
4911 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4913 for (i = 0; i < generic_array_method_num; i++) {
4914 MonoMethod *m = generic_array_method_info [i].array_method;
4915 MonoMethod *inflated;
4917 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4918 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4923 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4925 int null_length = strlen ("(null)");
4926 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4927 char *s = mono_image_alloc (image, len);
4930 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4931 g_assert (result == len - 1);
4937 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4939 gpointer exception_data = NULL;
4941 switch (error->exception_type) {
4942 case MONO_EXCEPTION_TYPE_LOAD:
4943 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4946 case MONO_EXCEPTION_MISSING_METHOD:
4947 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4950 case MONO_EXCEPTION_MISSING_FIELD: {
4951 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4952 const char *class_name;
4955 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4957 class_name = error->klass->name;
4959 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4962 g_free ((void*)class_name);
4966 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4969 if (error->ref_only)
4970 msg = "Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.";
4972 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4974 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4978 case MONO_EXCEPTION_BAD_IMAGE:
4979 exception_data = error->msg;
4983 g_assert_not_reached ();
4986 mono_class_set_failure (class, error->exception_type, exception_data);
4991 * @class: the class to initialize
4993 * Compute the instance_size, class_size and other infos that cannot be
4994 * computed at mono_class_get() time. Also compute vtable_size if possible.
4995 * Returns TRUE on success or FALSE if there was a problem in loading
4996 * the type (incorrect assemblies, missing assemblies, methods, etc).
4998 * LOCKING: Acquires the loader lock.
5001 mono_class_init (MonoClass *class)
5004 MonoCachedClassInfo cached_info;
5005 gboolean has_cached_info;
5009 /* Double-checking locking pattern */
5010 if (class->inited || class->exception_type)
5011 return class->exception_type == MONO_EXCEPTION_NONE;
5013 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5015 /* We do everything inside the lock to prevent races */
5016 mono_loader_lock ();
5018 if (class->inited || class->exception_type) {
5019 mono_loader_unlock ();
5020 /* Somebody might have gotten in before us */
5021 return class->exception_type == MONO_EXCEPTION_NONE;
5024 if (class->init_pending) {
5025 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5029 class->init_pending = 1;
5031 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5032 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5037 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5038 MonoClass *element_class = class->element_class;
5039 if (!element_class->inited)
5040 mono_class_init (element_class);
5041 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5042 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5047 /* CAS - SecurityAction.InheritanceDemand */
5048 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5049 mono_secman_inheritancedemand_class (class, class->parent);
5052 mono_stats.initialized_class_count++;
5054 if (class->generic_class && !class->generic_class->is_dynamic) {
5055 MonoClass *gklass = class->generic_class->container_class;
5057 mono_stats.generic_class_count++;
5059 class->method = gklass->method;
5060 class->field = gklass->field;
5062 mono_class_init (gklass);
5063 // FIXME: Why is this needed ?
5064 if (!gklass->exception_type)
5065 mono_class_setup_methods (gklass);
5066 if (gklass->exception_type) {
5067 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5071 if (MONO_CLASS_IS_INTERFACE (class))
5072 class->interface_id = mono_get_unique_iid (class);
5075 if (class->parent && !class->parent->inited)
5076 mono_class_init (class->parent);
5078 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5080 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5081 class->nested_classes_inited = TRUE;
5084 * Computes the size used by the fields, and their locations
5086 if (has_cached_info) {
5087 class->instance_size = cached_info.instance_size;
5088 class->sizes.class_size = cached_info.class_size;
5089 class->packing_size = cached_info.packing_size;
5090 class->min_align = cached_info.min_align;
5091 class->blittable = cached_info.blittable;
5092 class->has_references = cached_info.has_references;
5093 class->has_static_refs = cached_info.has_static_refs;
5094 class->no_special_static_fields = cached_info.no_special_static_fields;
5097 if (!class->size_inited){
5098 mono_class_setup_fields (class);
5099 if (class->exception_type || mono_loader_get_last_error ())
5103 /* Initialize arrays */
5105 class->method.count = 3 + (class->rank > 1? 2: 1);
5107 if (class->interface_count) {
5108 int count_generic = generic_array_methods (class);
5109 class->method.count += class->interface_count * count_generic;
5113 mono_class_setup_supertypes (class);
5116 initialize_object_slots (class);
5119 * Initialize the rest of the data without creating a generic vtable if possible.
5120 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5121 * also avoid computing a generic vtable.
5123 if (has_cached_info) {
5125 class->vtable_size = cached_info.vtable_size;
5126 class->has_finalize = cached_info.has_finalize;
5127 class->has_finalize_inited = TRUE;
5128 class->ghcimpl = cached_info.ghcimpl;
5129 class->has_cctor = cached_info.has_cctor;
5130 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5131 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5132 * The first slot if for array with.
5134 static int szarray_vtable_size[2] = { 0 };
5136 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5139 if (!szarray_vtable_size [slot]) {
5140 mono_class_setup_vtable (class);
5141 szarray_vtable_size [slot] = class->vtable_size;
5143 class->vtable_size = szarray_vtable_size[slot];
5145 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5146 MonoClass *gklass = class->generic_class->container_class;
5148 /* Generic instance case */
5149 class->ghcimpl = gklass->ghcimpl;
5150 class->has_cctor = gklass->has_cctor;
5152 mono_class_setup_vtable (gklass);
5153 if (gklass->exception_type) {
5154 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5158 class->vtable_size = gklass->vtable_size;
5162 /* ghcimpl is not currently used
5164 if (class->parent) {
5165 MonoMethod *cmethod = class->vtable [ghc_slot];
5166 if (cmethod->is_inflated)
5167 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5168 if (cmethod == default_ghc) {
5174 /* C# doesn't allow interfaces to have cctors */
5175 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5176 MonoMethod *cmethod = NULL;
5178 if (class->type_token) {
5179 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5180 /* The find_method function ignores the 'flags' argument */
5181 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5182 class->has_cctor = 1;
5184 mono_class_setup_methods (class);
5185 if (class->exception_type)
5188 for (i = 0; i < class->method.count; ++i) {
5189 MonoMethod *method = class->methods [i];
5190 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5191 (strcmp (".cctor", method->name) == 0)) {
5192 class->has_cctor = 1;
5200 if (class->parent) {
5201 int first_iface_slot;
5202 /* This will compute class->parent->vtable_size for some classes */
5203 mono_class_init (class->parent);
5204 if (class->parent->exception_type) {
5205 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5208 if (mono_loader_get_last_error ())
5210 if (!class->parent->vtable_size) {
5211 /* FIXME: Get rid of this somehow */
5212 mono_class_setup_vtable (class->parent);
5213 if (class->parent->exception_type) {
5214 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5217 if (mono_loader_get_last_error ())
5220 first_iface_slot = class->parent->vtable_size;
5221 if (mono_class_need_stelemref_method (class))
5223 setup_interface_offsets (class, first_iface_slot, TRUE);
5225 setup_interface_offsets (class, 0, TRUE);
5228 if (mono_security_core_clr_enabled ())
5229 mono_security_core_clr_check_inheritance (class);
5231 if (mono_loader_get_last_error ()) {
5232 if (class->exception_type == MONO_EXCEPTION_NONE) {
5233 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5235 mono_loader_clear_error ();
5238 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5239 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5244 /* Because of the double-checking locking pattern */
5245 mono_memory_barrier ();
5247 class->init_pending = 0;
5249 mono_loader_unlock ();
5251 if (mono_debugger_class_init_func)
5252 mono_debugger_class_init_func (class);
5254 return class->exception_type == MONO_EXCEPTION_NONE;
5258 * mono_class_has_finalizer:
5260 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5264 mono_class_has_finalizer (MonoClass *klass)
5266 MonoClass *class = klass;
5267 gboolean has_finalize = FALSE;
5269 if (klass->has_finalize_inited)
5270 return klass->has_finalize;
5272 /* Interfaces and valuetypes are not supposed to have finalizers */
5273 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5274 MonoMethod *cmethod = NULL;
5276 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5277 } else if (class->generic_class) {
5278 MonoClass *gklass = class->generic_class->container_class;
5280 has_finalize = mono_class_has_finalizer (gklass);
5281 } else if (class->parent && class->parent->has_finalize) {
5282 has_finalize = TRUE;
5284 if (class->parent) {
5286 * Can't search in metadata for a method named Finalize, because that
5287 * ignores overrides.
5289 mono_class_setup_vtable (class);
5290 if (class->exception_type || mono_loader_get_last_error ())
5293 cmethod = class->vtable [finalize_slot];
5297 g_assert (class->vtable_size > finalize_slot);
5299 if (class->parent) {
5300 if (cmethod->is_inflated)
5301 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5302 if (cmethod != default_finalize)
5303 has_finalize = TRUE;
5309 mono_image_lock (klass->image);
5311 if (!klass->has_finalize_inited) {
5312 klass->has_finalize = has_finalize ? 1 : 0;
5314 mono_memory_barrier ();
5315 klass->has_finalize_inited = TRUE;
5318 mono_image_unlock (klass->image);
5320 return klass->has_finalize;
5324 mono_is_corlib_image (MonoImage *image)
5326 /* FIXME: allow the dynamic case for our compilers and with full trust */
5327 if (image_is_dynamic (image))
5328 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5330 return image == mono_defaults.corlib;
5334 * LOCKING: this assumes the loader lock is held
5337 mono_class_setup_mono_type (MonoClass *class)
5339 const char *name = class->name;
5340 const char *nspace = class->name_space;
5341 gboolean is_corlib = mono_is_corlib_image (class->image);
5343 class->this_arg.byref = 1;
5344 class->this_arg.data.klass = class;
5345 class->this_arg.type = MONO_TYPE_CLASS;
5346 class->byval_arg.data.klass = class;
5347 class->byval_arg.type = MONO_TYPE_CLASS;
5349 if (is_corlib && !strcmp (nspace, "System")) {
5350 if (!strcmp (name, "ValueType")) {
5352 * do not set the valuetype bit for System.ValueType.
5353 * class->valuetype = 1;
5355 class->blittable = TRUE;
5356 } else if (!strcmp (name, "Enum")) {
5358 * do not set the valuetype bit for System.Enum.
5359 * class->valuetype = 1;
5361 class->valuetype = 0;
5362 class->enumtype = 0;
5363 } else if (!strcmp (name, "Object")) {
5364 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5365 } else if (!strcmp (name, "String")) {
5366 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5367 } else if (!strcmp (name, "TypedReference")) {
5368 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5372 if (class->valuetype) {
5373 int t = MONO_TYPE_VALUETYPE;
5375 if (is_corlib && !strcmp (nspace, "System")) {
5378 if (!strcmp (name, "Boolean")) {
5379 t = MONO_TYPE_BOOLEAN;
5380 } else if (!strcmp(name, "Byte")) {
5382 class->blittable = TRUE;
5386 if (!strcmp (name, "Char")) {
5391 if (!strcmp (name, "Double")) {
5393 class->blittable = TRUE;
5397 if (!strcmp (name, "Int32")) {
5399 class->blittable = TRUE;
5400 } else if (!strcmp(name, "Int16")) {
5402 class->blittable = TRUE;
5403 } else if (!strcmp(name, "Int64")) {
5405 class->blittable = TRUE;
5406 } else if (!strcmp(name, "IntPtr")) {
5408 class->blittable = TRUE;
5412 if (!strcmp (name, "Single")) {
5414 class->blittable = TRUE;
5415 } else if (!strcmp(name, "SByte")) {
5417 class->blittable = TRUE;
5421 if (!strcmp (name, "UInt32")) {
5423 class->blittable = TRUE;
5424 } else if (!strcmp(name, "UInt16")) {
5426 class->blittable = TRUE;
5427 } else if (!strcmp(name, "UInt64")) {
5429 class->blittable = TRUE;
5430 } else if (!strcmp(name, "UIntPtr")) {
5432 class->blittable = TRUE;
5436 if (!strcmp (name, "TypedReference")) {
5437 t = MONO_TYPE_TYPEDBYREF;
5438 class->blittable = TRUE;
5442 if (!strcmp (name, "Void")) {
5450 class->this_arg.type = class->byval_arg.type = t;
5453 if (MONO_CLASS_IS_INTERFACE (class))
5454 class->interface_id = mono_get_unique_iid (class);
5460 * COM initialization is delayed until needed.
5461 * However when a [ComImport] attribute is present on a type it will trigger
5462 * the initialization. This is not a problem unless the BCL being executed
5463 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5466 init_com_from_comimport (MonoClass *class)
5468 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5469 if (mono_security_core_clr_enabled ()) {
5470 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5471 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5472 /* but it can not be made available for application (i.e. user code) since all COM calls
5473 * are considered native calls. In this case we fail with a TypeLoadException (just like
5474 * Silverlight 2 does */
5475 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5480 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5482 #endif /*DISABLE_COM*/
5485 * LOCKING: this assumes the loader lock is held
5488 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5490 gboolean system_namespace;
5491 gboolean is_corlib = mono_is_corlib_image (class->image);
5493 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5495 /* if root of the hierarchy */
5496 if (system_namespace && !strcmp (class->name, "Object")) {
5497 class->parent = NULL;
5498 class->instance_size = sizeof (MonoObject);
5501 if (!strcmp (class->name, "<Module>")) {
5502 class->parent = NULL;
5503 class->instance_size = 0;
5507 if (!MONO_CLASS_IS_INTERFACE (class)) {
5508 /* Imported COM Objects always derive from __ComObject. */
5510 if (MONO_CLASS_IS_IMPORT (class)) {
5511 init_com_from_comimport (class);
5512 if (parent == mono_defaults.object_class)
5513 parent = mono_class_get_com_object_class ();
5517 /* set the parent to something useful and safe, but mark the type as broken */
5518 parent = mono_defaults.object_class;
5519 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5522 class->parent = parent;
5524 if (parent->generic_class && !parent->name) {
5526 * If the parent is a generic instance, we may get
5527 * called before it is fully initialized, especially
5528 * before it has its name.
5533 #ifndef DISABLE_REMOTING
5534 class->marshalbyref = parent->marshalbyref;
5535 class->contextbound = parent->contextbound;
5538 class->delegate = parent->delegate;
5540 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5541 mono_class_set_is_com_object (class);
5543 if (system_namespace) {
5544 #ifndef DISABLE_REMOTING
5545 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5546 class->marshalbyref = 1;
5548 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5549 class->contextbound = 1;
5551 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5552 class->delegate = 1;
5555 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5556 (strcmp (class->parent->name_space, "System") == 0)))
5557 class->valuetype = 1;
5558 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5559 class->valuetype = class->enumtype = 1;
5561 /*class->enumtype = class->parent->enumtype; */
5563 /* initialize com types if COM interfaces are present */
5565 if (MONO_CLASS_IS_IMPORT (class))
5566 init_com_from_comimport (class);
5568 class->parent = NULL;
5574 * mono_class_setup_supertypes:
5577 * Build the data structure needed to make fast type checks work.
5578 * This currently sets two fields in @class:
5579 * - idepth: distance between @class and System.Object in the type
5581 * - supertypes: array of classes: each element has a class in the hierarchy
5582 * starting from @class up to System.Object
5584 * LOCKING: This function is atomic, in case of contention we waste memory.
5587 mono_class_setup_supertypes (MonoClass *class)
5590 MonoClass **supertypes;
5592 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5596 if (class->parent && !class->parent->supertypes)
5597 mono_class_setup_supertypes (class->parent);
5599 class->idepth = class->parent->idepth + 1;
5603 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5604 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5606 if (class->parent) {
5607 supertypes [class->idepth - 1] = class;
5608 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5610 supertypes [0] = class;
5613 mono_atomic_store_release (&class->supertypes, supertypes);
5617 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5619 MonoClass *gtd = (MonoClass*)user_data;
5620 /* Only try to fix generic instances of @gtd */
5621 if (gclass->generic_class->container_class != gtd)
5624 /* Check if the generic instance has no parent. */
5625 if (gtd->parent && !gclass->parent)
5626 mono_generic_class_setup_parent (gclass, gtd);
5632 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5634 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5635 mono_error_set_type_load_class (error, class, msg);
5639 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5641 MonoLoaderError *lerror = mono_loader_get_last_error ();
5644 set_failure_from_loader_error (class, lerror);
5645 mono_error_set_from_loader_error (error);
5649 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5650 mono_error_set_type_load_class (error, class, msg);
5655 * mono_class_create_from_typedef:
5656 * @image: image where the token is valid
5657 * @type_token: typedef token
5658 * @error: used to return any error found while creating the type
5660 * Create the MonoClass* representing the specified type token.
5661 * @type_token must be a TypeDef token.
5663 * FIXME: don't return NULL on failure, just the the caller figure it out.
5666 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5668 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5669 MonoClass *class, *parent = NULL;
5670 guint32 cols [MONO_TYPEDEF_SIZE];
5671 guint32 cols_next [MONO_TYPEDEF_SIZE];
5672 guint tidx = mono_metadata_token_index (type_token);
5673 MonoGenericContext *context = NULL;
5674 const char *name, *nspace;
5676 MonoClass **interfaces;
5677 guint32 field_last, method_last;
5678 guint32 nesting_tokeen;
5680 mono_error_init (error);
5682 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5683 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5684 g_assert (!mono_loader_get_last_error ());
5688 mono_loader_lock ();
5690 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5691 mono_loader_unlock ();
5692 g_assert (!mono_loader_get_last_error ());
5696 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5698 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5699 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5701 class = mono_image_alloc0 (image, sizeof (MonoClass));
5704 class->name_space = nspace;
5706 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5708 class->image = image;
5709 class->type_token = type_token;
5710 class->flags = cols [MONO_TYPEDEF_FLAGS];
5712 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5714 classes_size += sizeof (MonoClass);
5717 * Check whether we're a generic type definition.
5719 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5720 if (class->generic_container) {
5721 class->is_generic = 1;
5722 class->generic_container->owner.klass = class;
5723 context = &class->generic_container->context;
5726 if (class->generic_container)
5727 enable_gclass_recording ();
5729 if (cols [MONO_TYPEDEF_EXTENDS]) {
5731 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5733 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5734 /*WARNING: this must satisfy mono_metadata_type_hash*/
5735 class->this_arg.byref = 1;
5736 class->this_arg.data.klass = class;
5737 class->this_arg.type = MONO_TYPE_CLASS;
5738 class->byval_arg.data.klass = class;
5739 class->byval_arg.type = MONO_TYPE_CLASS;
5741 parent = mono_class_get_checked (image, parent_token, error);
5742 if (parent && context) /* Always inflate */
5743 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5745 if (parent == NULL) {
5746 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5747 goto parent_failure;
5750 for (tmp = parent; tmp; tmp = tmp->parent) {
5752 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5753 goto parent_failure;
5755 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5756 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5757 goto parent_failure;
5762 mono_class_setup_parent (class, parent);
5764 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5765 mono_class_setup_mono_type (class);
5767 if (class->generic_container)
5768 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5771 * This might access class->byval_arg for recursion generated by generic constraints,
5772 * so it has to come after setup_mono_type ().
5774 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5775 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5776 if (!mono_error_ok (error)) {
5777 /*FIXME implement a mono_class_set_failure_from_mono_error */
5778 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5779 mono_loader_unlock ();
5780 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5781 g_assert (!mono_loader_get_last_error ());
5786 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5790 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5794 class->cast_class = class->element_class = class;
5796 if (!class->enumtype) {
5797 if (!mono_metadata_interfaces_from_typedef_full (
5798 image, type_token, &interfaces, &icount, FALSE, context)){
5799 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5800 mono_loader_unlock ();
5801 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5805 class->interfaces = interfaces;
5806 class->interface_count = icount;
5807 class->interfaces_inited = 1;
5810 /*g_print ("Load class %s\n", name);*/
5813 * Compute the field and method lists
5815 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5816 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5818 if (tt->rows > tidx){
5819 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5820 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5821 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5823 field_last = image->tables [MONO_TABLE_FIELD].rows;
5824 method_last = image->tables [MONO_TABLE_METHOD].rows;
5827 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5828 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5829 class->field.count = field_last - class->field.first;
5831 class->field.count = 0;
5833 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5834 class->method.count = method_last - class->method.first;
5836 class->method.count = 0;
5838 /* reserve space to store vector pointer in arrays */
5839 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5840 class->instance_size += 2 * sizeof (gpointer);
5841 g_assert (class->field.count == 0);
5844 if (class->enumtype) {
5845 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5846 if (!enum_basetype) {
5847 /*set it to a default value as the whole runtime can't handle this to be null*/
5848 class->cast_class = class->element_class = mono_defaults.int32_class;
5849 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5850 mono_loader_unlock ();
5851 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5852 g_assert (!mono_loader_get_last_error ());
5855 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5859 * If we're a generic type definition, load the constraints.
5860 * We must do this after the class has been constructed to make certain recursive scenarios
5863 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5864 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5865 mono_loader_unlock ();
5866 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5867 g_assert (!mono_loader_get_last_error ());
5871 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5872 if (!strncmp (name, "Vector", 6))
5873 class->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");
5876 mono_loader_unlock ();
5878 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5879 g_assert (!mono_loader_get_last_error ());
5884 mono_class_setup_mono_type (class);
5885 mono_loader_unlock ();
5886 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5887 g_assert (!mono_loader_get_last_error ());
5891 /** is klass Nullable<T>? */
5893 mono_class_is_nullable (MonoClass *klass)
5895 return klass->generic_class != NULL &&
5896 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5900 /** if klass is T? return T */
5902 mono_class_get_nullable_param (MonoClass *klass)
5904 g_assert (mono_class_is_nullable (klass));
5905 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5909 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5913 MonoGenericClass *gclass = klass->generic_class;
5915 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5916 if (!mono_error_ok (&error)) {
5917 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5918 klass->parent = mono_defaults.object_class;
5919 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5920 mono_error_cleanup (&error);
5924 mono_class_setup_parent (klass, klass->parent);
5926 if (klass->enumtype) {
5927 klass->cast_class = gtd->cast_class;
5928 klass->element_class = gtd->element_class;
5934 * Create the `MonoClass' for an instantiation of a generic type.
5935 * We only do this if we actually need it.
5938 mono_generic_class_get_class (MonoGenericClass *gclass)
5940 MonoClass *klass, *gklass;
5942 if (gclass->cached_class)
5943 return gclass->cached_class;
5945 mono_loader_lock ();
5946 if (gclass->cached_class) {
5947 mono_loader_unlock ();
5948 return gclass->cached_class;
5951 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5953 gklass = gclass->container_class;
5955 if (record_gclass_instantiation > 0)
5956 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5958 if (gklass->nested_in) {
5959 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5960 klass->nested_in = gklass->nested_in;
5963 klass->name = gklass->name;
5964 klass->name_space = gklass->name_space;
5966 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5968 klass->image = gklass->image;
5969 klass->flags = gklass->flags;
5970 klass->type_token = gklass->type_token;
5971 klass->field.count = gklass->field.count;
5973 klass->is_inflated = 1;
5974 klass->generic_class = gclass;
5976 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5977 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5978 klass->this_arg.byref = TRUE;
5979 klass->enumtype = gklass->enumtype;
5980 klass->valuetype = gklass->valuetype;
5982 klass->cast_class = klass->element_class = klass;
5984 if (mono_class_is_nullable (klass))
5985 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5988 * We're not interested in the nested classes of a generic instance.
5989 * We use the generic type definition to look for nested classes.
5992 mono_generic_class_setup_parent (klass, gklass);
5994 if (gclass->is_dynamic) {
5997 mono_class_setup_supertypes (klass);
5999 if (klass->enumtype) {
6001 * For enums, gklass->fields might not been set, but instance_size etc. is
6002 * already set in mono_reflection_create_internal_class (). For non-enums,
6003 * these will be computed normally in mono_class_layout_fields ().
6005 klass->instance_size = gklass->instance_size;
6006 klass->sizes.class_size = gklass->sizes.class_size;
6007 mono_memory_barrier ();
6008 klass->size_inited = 1;
6012 mono_memory_barrier ();
6013 gclass->cached_class = klass;
6015 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6017 inflated_classes ++;
6018 inflated_classes_size += sizeof (MonoClass);
6020 mono_loader_unlock ();
6026 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6028 MonoClass *klass, **ptr;
6030 MonoGenericContainer *container = mono_generic_param_owner (param);
6034 image = mono_defaults.corlib;
6036 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6037 classes_size += sizeof (MonoClass);
6040 klass->name = pinfo->name;
6042 int n = mono_generic_param_num (param);
6043 klass->name = mono_image_alloc0 (image, 16);
6044 sprintf ((char*)klass->name, "%d", n);
6049 MonoMethod *omethod = container->owner.method;
6050 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6052 MonoClass *oklass = container->owner.klass;
6053 klass->name_space = oklass ? oklass->name_space : "";
6056 klass->name_space = "";
6059 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6063 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6067 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6068 klass->parent = pinfo->constraints [0];
6070 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6071 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6073 klass->parent = mono_defaults.object_class;
6076 if (count - pos > 0) {
6077 klass->interface_count = count - pos;
6078 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6079 klass->interfaces_inited = TRUE;
6080 for (i = pos; i < count; i++)
6081 klass->interfaces [i - pos] = pinfo->constraints [i];
6084 klass->image = image;
6086 klass->inited = TRUE;
6087 klass->cast_class = klass->element_class = klass;
6088 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6090 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6091 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6092 klass->this_arg.byref = TRUE;
6094 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6095 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6097 /*Init these fields to sane values*/
6098 klass->min_align = 1;
6099 klass->instance_size = sizeof (gpointer);
6100 mono_memory_barrier ();
6101 klass->size_inited = 1;
6103 mono_class_setup_supertypes (klass);
6105 if (count - pos > 0) {
6106 mono_class_setup_vtable (klass->parent);
6107 if (klass->parent->exception_type)
6108 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6110 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6116 #define FAST_CACHE_SIZE 16
6119 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6121 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6122 MonoImage *image = param->image;
6127 if (n < FAST_CACHE_SIZE) {
6129 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6131 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6133 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6134 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6139 * LOCKING: Acquires the loader lock.
6142 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6144 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6145 MonoImage *image = param->image;
6150 if (n < FAST_CACHE_SIZE) {
6152 /* No locking needed */
6153 if (!image->mvar_cache_fast)
6154 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6155 image->mvar_cache_fast [n] = klass;
6157 if (!image->var_cache_fast)
6158 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6159 image->var_cache_fast [n] = klass;
6163 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6165 mono_image_lock (image);
6166 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6168 ht = g_hash_table_new (NULL, NULL);
6169 mono_memory_barrier ();
6171 image->mvar_cache_slow = ht;
6173 image->var_cache_slow = ht;
6175 mono_image_unlock (image);
6178 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6182 * LOCKING: Acquires the loader lock.
6185 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6187 MonoGenericContainer *container = mono_generic_param_owner (param);
6188 MonoGenericParamInfo *pinfo;
6191 mono_loader_lock ();
6194 pinfo = mono_generic_param_info (param);
6195 if (pinfo->pklass) {
6196 mono_loader_unlock ();
6197 return pinfo->pklass;
6203 klass = get_anon_gparam_class (param, is_mvar);
6205 mono_loader_unlock ();
6210 if (!image && container) {
6212 MonoMethod *method = container->owner.method;
6213 image = (method && method->klass) ? method->klass->image : NULL;
6215 MonoClass *klass = container->owner.klass;
6216 // FIXME: 'klass' should not be null
6217 // But, monodis creates GenericContainers without associating a owner to it
6218 image = klass ? klass->image : NULL;
6222 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6224 mono_memory_barrier ();
6227 pinfo->pklass = klass;
6229 set_anon_gparam_class (param, is_mvar, klass);
6231 mono_loader_unlock ();
6233 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6234 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6240 mono_ptr_class_get (MonoType *type)
6243 MonoClass *el_class;
6247 el_class = mono_class_from_mono_type (type);
6248 image = el_class->image;
6250 mono_loader_lock ();
6252 if (!image->ptr_cache)
6253 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6255 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6256 mono_loader_unlock ();
6259 result = mono_image_alloc0 (image, sizeof (MonoClass));
6261 classes_size += sizeof (MonoClass);
6263 result->parent = NULL; /* no parent for PTR types */
6264 result->name_space = el_class->name_space;
6265 name = g_strdup_printf ("%s*", el_class->name);
6266 result->name = mono_image_strdup (image, name);
6269 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6271 result->image = el_class->image;
6272 result->inited = TRUE;
6273 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6274 /* Can pointers get boxed? */
6275 result->instance_size = sizeof (gpointer);
6276 result->cast_class = result->element_class = el_class;
6277 result->blittable = TRUE;
6279 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6280 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6281 result->this_arg.byref = TRUE;
6283 mono_class_setup_supertypes (result);
6285 g_hash_table_insert (image->ptr_cache, el_class, result);
6287 mono_loader_unlock ();
6289 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6295 mono_fnptr_class_get (MonoMethodSignature *sig)
6298 static GHashTable *ptr_hash = NULL;
6300 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6302 mono_loader_lock ();
6305 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6307 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6308 mono_loader_unlock ();
6311 result = g_new0 (MonoClass, 1);
6313 result->parent = NULL; /* no parent for PTR types */
6314 result->name_space = "System";
6315 result->name = "MonoFNPtrFakeClass";
6317 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6319 result->image = mono_defaults.corlib; /* need to fix... */
6320 result->inited = TRUE;
6321 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6322 /* Can pointers get boxed? */
6323 result->instance_size = sizeof (gpointer);
6324 result->cast_class = result->element_class = result;
6325 result->blittable = TRUE;
6327 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6328 result->this_arg.data.method = result->byval_arg.data.method = sig;
6329 result->this_arg.byref = TRUE;
6330 result->blittable = TRUE;
6332 mono_class_setup_supertypes (result);
6334 g_hash_table_insert (ptr_hash, sig, result);
6336 mono_loader_unlock ();
6338 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6344 mono_class_from_mono_type (MonoType *type)
6346 switch (type->type) {
6347 case MONO_TYPE_OBJECT:
6348 return type->data.klass? type->data.klass: mono_defaults.object_class;
6349 case MONO_TYPE_VOID:
6350 return type->data.klass? type->data.klass: mono_defaults.void_class;
6351 case MONO_TYPE_BOOLEAN:
6352 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6353 case MONO_TYPE_CHAR:
6354 return type->data.klass? type->data.klass: mono_defaults.char_class;
6356 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6358 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6360 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6362 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6364 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6366 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6368 return type->data.klass? type->data.klass: mono_defaults.int_class;
6370 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6372 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6374 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6376 return type->data.klass? type->data.klass: mono_defaults.single_class;
6378 return type->data.klass? type->data.klass: mono_defaults.double_class;
6379 case MONO_TYPE_STRING:
6380 return type->data.klass? type->data.klass: mono_defaults.string_class;
6381 case MONO_TYPE_TYPEDBYREF:
6382 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6383 case MONO_TYPE_ARRAY:
6384 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6386 return mono_ptr_class_get (type->data.type);
6387 case MONO_TYPE_FNPTR:
6388 return mono_fnptr_class_get (type->data.method);
6389 case MONO_TYPE_SZARRAY:
6390 return mono_array_class_get (type->data.klass, 1);
6391 case MONO_TYPE_CLASS:
6392 case MONO_TYPE_VALUETYPE:
6393 return type->data.klass;
6394 case MONO_TYPE_GENERICINST:
6395 return mono_generic_class_get_class (type->data.generic_class);
6397 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6398 case MONO_TYPE_MVAR:
6399 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6401 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6402 g_assert_not_reached ();
6409 * mono_type_retrieve_from_typespec
6410 * @image: context where the image is created
6411 * @type_spec: typespec token
6412 * @context: the generic context used to evaluate generic instantiations in
6415 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6417 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6419 *did_inflate = FALSE;
6424 if (context && (context->class_inst || context->method_inst)) {
6425 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6427 if (!mono_error_ok (error)) {
6428 g_assert (!mono_loader_get_last_error ());
6434 *did_inflate = TRUE;
6441 * mono_class_create_from_typespec
6442 * @image: context where the image is created
6443 * @type_spec: typespec token
6444 * @context: the generic context used to evaluate generic instantiations in
6447 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6450 gboolean inflated = FALSE;
6451 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6452 if (!mono_error_ok (error))
6454 ret = mono_class_from_mono_type (t);
6456 mono_metadata_free_type (t);
6461 * mono_bounded_array_class_get:
6462 * @element_class: element class
6463 * @rank: the dimension of the array class
6464 * @bounded: whenever the array has non-zero bounds
6466 * Returns: a class object describing the array with element type @element_type and
6470 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6474 MonoClass *parent = NULL;
6475 GSList *list, *rootlist = NULL;
6478 gboolean corlib_type = FALSE;
6480 g_assert (rank <= 255);
6483 /* bounded only matters for one-dimensional arrays */
6486 image = eclass->image;
6488 if (rank == 1 && !bounded) {
6490 * This case is very frequent not just during compilation because of calls
6491 * from mono_class_from_mono_type (), mono_array_new (),
6492 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6494 mono_mutex_lock (&image->szarray_cache_lock);
6495 if (!image->szarray_cache)
6496 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6497 class = g_hash_table_lookup (image->szarray_cache, eclass);
6498 mono_mutex_unlock (&image->szarray_cache_lock);
6502 mono_loader_lock ();
6504 mono_loader_lock ();
6506 if (!image->array_cache)
6507 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6509 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6510 for (; list; list = list->next) {
6512 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6513 mono_loader_unlock ();
6520 /* for the building corlib use System.Array from it */
6521 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6522 parent = mono_class_from_name (image, "System", "Array");
6525 parent = mono_defaults.array_class;
6526 if (!parent->inited)
6527 mono_class_init (parent);
6530 class = mono_image_alloc0 (image, sizeof (MonoClass));
6532 class->image = image;
6533 class->name_space = eclass->name_space;
6534 nsize = strlen (eclass->name);
6535 name = g_malloc (nsize + 2 + rank + 1);
6536 memcpy (name, eclass->name, nsize);
6539 memset (name + nsize + 1, ',', rank - 1);
6541 name [nsize + rank] = '*';
6542 name [nsize + rank + bounded] = ']';
6543 name [nsize + rank + bounded + 1] = 0;
6544 class->name = mono_image_strdup (image, name);
6547 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6549 classes_size += sizeof (MonoClass);
6551 class->type_token = 0;
6552 /* all arrays are marked serializable and sealed, bug #42779 */
6553 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6554 class->parent = parent;
6555 class->instance_size = mono_class_instance_size (class->parent);
6557 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6558 /*Arrays of those two types are invalid.*/
6559 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6560 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6561 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6562 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6563 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6565 /* element_size -1 is ok as this is not an instantitable type*/
6566 class->sizes.element_size = -1;
6568 class->sizes.element_size = mono_class_array_element_size (eclass);
6570 mono_class_setup_supertypes (class);
6572 if (eclass->generic_class)
6573 mono_class_init (eclass);
6574 if (!eclass->size_inited)
6575 mono_class_setup_fields (eclass);
6576 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6577 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6579 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6583 if (eclass->enumtype)
6584 class->cast_class = eclass->element_class;
6586 class->cast_class = eclass;
6588 switch (class->cast_class->byval_arg.type) {
6590 class->cast_class = mono_defaults.byte_class;
6593 class->cast_class = mono_defaults.int16_class;
6596 #if SIZEOF_VOID_P == 4
6600 class->cast_class = mono_defaults.int32_class;
6603 #if SIZEOF_VOID_P == 8
6607 class->cast_class = mono_defaults.int64_class;
6611 class->element_class = eclass;
6613 if ((rank > 1) || bounded) {
6614 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6615 class->byval_arg.type = MONO_TYPE_ARRAY;
6616 class->byval_arg.data.array = at;
6617 at->eklass = eclass;
6619 /* FIXME: complete.... */
6621 class->byval_arg.type = MONO_TYPE_SZARRAY;
6622 class->byval_arg.data.klass = eclass;
6624 class->this_arg = class->byval_arg;
6625 class->this_arg.byref = 1;
6630 class->generic_container = eclass->generic_container;
6632 if (rank == 1 && !bounded) {
6633 MonoClass *prev_class;
6635 mono_mutex_lock (&image->szarray_cache_lock);
6636 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6638 /* Someone got in before us */
6641 g_hash_table_insert (image->szarray_cache, eclass, class);
6642 mono_mutex_unlock (&image->szarray_cache_lock);
6644 list = g_slist_append (rootlist, class);
6645 g_hash_table_insert (image->array_cache, eclass, list);
6648 mono_loader_unlock ();
6650 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6656 * mono_array_class_get:
6657 * @element_class: element class
6658 * @rank: the dimension of the array class
6660 * Returns: a class object describing the array with element type @element_type and
6664 mono_array_class_get (MonoClass *eclass, guint32 rank)
6666 return mono_bounded_array_class_get (eclass, rank, FALSE);
6670 * mono_class_instance_size:
6673 * Returns: the size of an object instance
6676 mono_class_instance_size (MonoClass *klass)
6678 if (!klass->size_inited)
6679 mono_class_init (klass);
6681 return klass->instance_size;
6685 * mono_class_min_align:
6688 * Returns: minimm alignment requirements
6691 mono_class_min_align (MonoClass *klass)
6693 if (!klass->size_inited)
6694 mono_class_init (klass);
6696 return klass->min_align;
6700 * mono_class_value_size:
6703 * This function is used for value types, and return the
6704 * space and the alignment to store that kind of value object.
6706 * Returns: the size of a value of kind @klass
6709 mono_class_value_size (MonoClass *klass, guint32 *align)
6713 /* fixme: check disable, because we still have external revereces to
6714 * mscorlib and Dummy Objects
6716 /*g_assert (klass->valuetype);*/
6718 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6721 *align = klass->min_align;
6727 * mono_class_data_size:
6730 * Returns: the size of the static class data
6733 mono_class_data_size (MonoClass *klass)
6736 mono_class_init (klass);
6737 /* This can happen with dynamically created types */
6738 if (!klass->fields_inited)
6739 mono_class_setup_fields_locking (klass);
6741 /* in arrays, sizes.class_size is unioned with element_size
6742 * and arrays have no static fields
6746 return klass->sizes.class_size;
6750 * Auxiliary routine to mono_class_get_field
6752 * Takes a field index instead of a field token.
6754 static MonoClassField *
6755 mono_class_get_field_idx (MonoClass *class, int idx)
6757 mono_class_setup_fields_locking (class);
6758 if (class->exception_type)
6762 if (class->image->uncompressed_metadata) {
6764 * class->field.first points to the FieldPtr table, while idx points into the
6765 * Field table, so we have to do a search.
6767 /*FIXME this is broken for types with multiple fields with the same name.*/
6768 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6771 for (i = 0; i < class->field.count; ++i)
6772 if (mono_field_get_name (&class->fields [i]) == name)
6773 return &class->fields [i];
6774 g_assert_not_reached ();
6776 if (class->field.count) {
6777 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6778 return &class->fields [idx - class->field.first];
6782 class = class->parent;
6788 * mono_class_get_field:
6789 * @class: the class to lookup the field.
6790 * @field_token: the field token
6792 * Returns: A MonoClassField representing the type and offset of
6793 * the field, or a NULL value if the field does not belong to this
6797 mono_class_get_field (MonoClass *class, guint32 field_token)
6799 int idx = mono_metadata_token_index (field_token);
6801 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6803 return mono_class_get_field_idx (class, idx - 1);
6807 * mono_class_get_field_from_name:
6808 * @klass: the class to lookup the field.
6809 * @name: the field name
6811 * Search the class @klass and it's parents for a field with the name @name.
6813 * Returns: the MonoClassField pointer of the named field or NULL
6816 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6818 return mono_class_get_field_from_name_full (klass, name, NULL);
6822 * mono_class_get_field_from_name_full:
6823 * @klass: the class to lookup the field.
6824 * @name: the field name
6825 * @type: the type of the fields. This optional.
6827 * Search the class @klass and it's parents for a field with the name @name and type @type.
6829 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6830 * of its generic type definition.
6832 * Returns: the MonoClassField pointer of the named field or NULL
6835 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6839 mono_class_setup_fields_locking (klass);
6840 if (klass->exception_type)
6844 for (i = 0; i < klass->field.count; ++i) {
6845 MonoClassField *field = &klass->fields [i];
6847 if (strcmp (name, mono_field_get_name (field)) != 0)
6851 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6852 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6857 klass = klass->parent;
6863 * mono_class_get_field_token:
6864 * @field: the field we need the token of
6866 * Get the token of a field. Note that the tokesn is only valid for the image
6867 * the field was loaded from. Don't use this function for fields in dynamic types.
6869 * Returns: the token representing the field in the image it was loaded from.
6872 mono_class_get_field_token (MonoClassField *field)
6874 MonoClass *klass = field->parent;
6877 mono_class_setup_fields_locking (klass);
6882 for (i = 0; i < klass->field.count; ++i) {
6883 if (&klass->fields [i] == field) {
6884 int idx = klass->field.first + i + 1;
6886 if (klass->image->uncompressed_metadata)
6887 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6888 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6891 klass = klass->parent;
6894 g_assert_not_reached ();
6899 mono_field_get_index (MonoClassField *field)
6901 int index = field - field->parent->fields;
6903 g_assert (index >= 0 && index < field->parent->field.count);
6909 * mono_class_get_field_default_value:
6911 * Return the default value of the field as a pointer into the metadata blob.
6914 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6917 guint32 constant_cols [MONO_CONSTANT_SIZE];
6919 MonoClass *klass = field->parent;
6921 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6923 if (!klass->ext || !klass->ext->field_def_values) {
6924 MonoFieldDefaultValue *def_values;
6926 mono_class_alloc_ext (klass);
6928 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6930 mono_image_lock (klass->image);
6931 mono_memory_barrier ();
6932 if (!klass->ext->field_def_values)
6933 klass->ext->field_def_values = def_values;
6934 mono_image_unlock (klass->image);
6937 field_index = mono_field_get_index (field);
6939 if (!klass->ext->field_def_values [field_index].data) {
6940 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6944 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6946 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6947 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6948 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6951 *def_type = klass->ext->field_def_values [field_index].def_type;
6952 return klass->ext->field_def_values [field_index].data;
6956 mono_property_get_index (MonoProperty *prop)
6958 int index = prop - prop->parent->ext->properties;
6960 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6966 * mono_class_get_property_default_value:
6968 * Return the default value of the field as a pointer into the metadata blob.
6971 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6974 guint32 constant_cols [MONO_CONSTANT_SIZE];
6975 MonoClass *klass = property->parent;
6977 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6979 * We don't cache here because it is not used by C# so it's quite rare, but
6980 * we still do the lookup in klass->ext because that is where the data
6981 * is stored for dynamic assemblies.
6984 if (image_is_dynamic (klass->image)) {
6985 int prop_index = mono_property_get_index (property);
6986 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6987 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6988 return klass->ext->prop_def_values [prop_index].data;
6992 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6996 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6997 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6998 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7002 mono_class_get_event_token (MonoEvent *event)
7004 MonoClass *klass = event->parent;
7009 for (i = 0; i < klass->ext->event.count; ++i) {
7010 if (&klass->ext->events [i] == event)
7011 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7014 klass = klass->parent;
7017 g_assert_not_reached ();
7022 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7026 gpointer iter = NULL;
7027 while ((p = mono_class_get_properties (klass, &iter))) {
7028 if (! strcmp (name, p->name))
7031 klass = klass->parent;
7037 mono_class_get_property_token (MonoProperty *prop)
7039 MonoClass *klass = prop->parent;
7043 gpointer iter = NULL;
7044 while ((p = mono_class_get_properties (klass, &iter))) {
7045 if (&klass->ext->properties [i] == prop)
7046 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7050 klass = klass->parent;
7053 g_assert_not_reached ();
7058 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7060 const char *name, *nspace;
7061 if (image_is_dynamic (image))
7062 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7064 switch (type_token & 0xff000000){
7065 case MONO_TOKEN_TYPE_DEF: {
7066 guint32 cols [MONO_TYPEDEF_SIZE];
7067 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7068 guint tidx = mono_metadata_token_index (type_token);
7070 if (tidx > tt->rows)
7071 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7073 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7074 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7075 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7076 if (strlen (nspace) == 0)
7077 return g_strdup_printf ("%s", name);
7079 return g_strdup_printf ("%s.%s", nspace, name);
7082 case MONO_TOKEN_TYPE_REF: {
7084 guint32 cols [MONO_TYPEREF_SIZE];
7085 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7086 guint tidx = mono_metadata_token_index (type_token);
7089 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7091 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7092 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7093 mono_error_cleanup (&error);
7097 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7098 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7099 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7100 if (strlen (nspace) == 0)
7101 return g_strdup_printf ("%s", name);
7103 return g_strdup_printf ("%s.%s", nspace, name);
7106 case MONO_TOKEN_TYPE_SPEC:
7107 return g_strdup_printf ("Typespec 0x%08x", type_token);
7109 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7114 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7116 if (image_is_dynamic (image))
7117 return g_strdup_printf ("DynamicAssembly %s", image->name);
7119 switch (type_token & 0xff000000){
7120 case MONO_TOKEN_TYPE_DEF:
7121 if (image->assembly)
7122 return mono_stringify_assembly_name (&image->assembly->aname);
7123 else if (image->assembly_name)
7124 return g_strdup (image->assembly_name);
7125 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7126 case MONO_TOKEN_TYPE_REF: {
7128 MonoAssemblyName aname;
7129 guint32 cols [MONO_TYPEREF_SIZE];
7130 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7131 guint32 idx = mono_metadata_token_index (type_token);
7134 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7136 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7137 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7138 mono_error_cleanup (&error);
7141 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7143 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7144 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7145 case MONO_RESOLUTION_SCOPE_MODULE:
7147 return g_strdup ("");
7148 case MONO_RESOLUTION_SCOPE_MODULEREF:
7150 return g_strdup ("");
7151 case MONO_RESOLUTION_SCOPE_TYPEREF:
7153 return g_strdup ("");
7154 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7155 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7156 return mono_stringify_assembly_name (&aname);
7158 g_assert_not_reached ();
7162 case MONO_TOKEN_TYPE_SPEC:
7164 return g_strdup ("");
7166 g_assert_not_reached ();
7173 * mono_class_get_full:
7174 * @image: the image where the class resides
7175 * @type_token: the token for the class
7176 * @context: the generic context used to evaluate generic instantiations in
7177 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7179 * Returns: the MonoClass that represents @type_token in @image
7182 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7186 class = mono_class_get_checked (image, type_token, &error);
7188 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7189 class = mono_class_inflate_generic_class_checked (class, context, &error);
7192 mono_loader_set_error_from_mono_error (&error);
7193 mono_error_cleanup (&error); /*FIXME don't swallow this error */
7200 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7204 mono_error_init (error);
7205 class = mono_class_get_checked (image, type_token, error);
7207 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7208 class = mono_class_inflate_generic_class_checked (class, context, error);
7213 * mono_class_get_checked:
7214 * @image: the image where the class resides
7215 * @type_token: the token for the class
7216 * @error: error object to return any error
7218 * Returns: the MonoClass that represents @type_token in @image
7221 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7223 MonoClass *class = NULL;
7225 mono_error_init (error);
7227 if (image_is_dynamic (image)) {
7228 int table = mono_metadata_token_table (type_token);
7230 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7231 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7234 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7238 switch (type_token & 0xff000000){
7239 case MONO_TOKEN_TYPE_DEF:
7240 class = mono_class_create_from_typedef (image, type_token, error);
7242 case MONO_TOKEN_TYPE_REF:
7243 class = mono_class_from_typeref_checked (image, type_token, error);
7245 case MONO_TOKEN_TYPE_SPEC:
7246 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7249 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7253 /* Generic case, should be avoided for when a better error is possible. */
7254 if (!class && mono_error_ok (error)) {
7255 char *name = mono_class_name_from_token (image, type_token);
7256 char *assembly = mono_assembly_name_from_token (image, type_token);
7257 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7265 * mono_type_get_checked:
7266 * @image: the image where the type resides
7267 * @type_token: the token for the type
7268 * @context: the generic context used to evaluate generic instantiations in
7269 * @error: Error handling context
7271 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7273 * Returns: the MonoType that represents @type_token in @image
7276 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7278 MonoType *type = NULL;
7279 gboolean inflated = FALSE;
7281 mono_error_init (error);
7283 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7284 if (image_is_dynamic (image))
7285 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7287 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7288 MonoClass *class = mono_class_get_checked (image, type_token, error);
7291 g_assert (!mono_loader_get_last_error ());
7296 return mono_class_get_type (class);
7299 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7302 g_assert (!mono_loader_get_last_error ());
7307 MonoType *tmp = type;
7308 type = mono_class_get_type (mono_class_from_mono_type (type));
7309 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7310 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7311 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7313 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7315 if (type->type != tmp->type)
7318 mono_metadata_free_type (tmp);
7325 mono_class_get (MonoImage *image, guint32 type_token)
7327 return mono_class_get_full (image, type_token, NULL);
7331 * mono_image_init_name_cache:
7333 * Initializes the class name cache stored in image->name_cache.
7335 * LOCKING: Acquires the corresponding image lock.
7338 mono_image_init_name_cache (MonoImage *image)
7340 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7341 guint32 cols [MONO_TYPEDEF_SIZE];
7344 guint32 i, visib, nspace_index;
7345 GHashTable *name_cache2, *nspace_table;
7347 mono_image_lock (image);
7349 if (image->name_cache) {
7350 mono_image_unlock (image);
7354 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7356 if (image_is_dynamic (image)) {
7357 mono_image_unlock (image);
7361 /* Temporary hash table to avoid lookups in the nspace_table */
7362 name_cache2 = g_hash_table_new (NULL, NULL);
7364 for (i = 1; i <= t->rows; ++i) {
7365 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7366 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7368 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7369 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7371 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7373 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7374 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7376 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7377 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7378 if (!nspace_table) {
7379 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7380 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7381 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7384 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7387 /* Load type names from EXPORTEDTYPES table */
7389 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7390 guint32 cols [MONO_EXP_TYPE_SIZE];
7393 for (i = 0; i < t->rows; ++i) {
7394 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7395 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7396 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7398 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7399 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7400 if (!nspace_table) {
7401 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7402 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7403 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7406 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7410 g_hash_table_destroy (name_cache2);
7411 mono_image_unlock (image);
7414 /*FIXME Only dynamic assemblies should allow this operation.*/
7416 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7417 const char *name, guint32 index)
7419 GHashTable *nspace_table;
7420 GHashTable *name_cache;
7423 mono_image_lock (image);
7425 if (!image->name_cache)
7426 mono_image_init_name_cache (image);
7428 name_cache = image->name_cache;
7429 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7430 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7431 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7434 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7435 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7437 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7439 mono_image_unlock (image);
7448 find_nocase (gpointer key, gpointer value, gpointer user_data)
7450 char *name = (char*)key;
7451 FindUserData *data = (FindUserData*)user_data;
7453 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7454 data->value = value;
7458 * mono_class_from_name_case:
7459 * @image: The MonoImage where the type is looked up in
7460 * @name_space: the type namespace
7461 * @name: the type short name.
7462 * @deprecated: use the _checked variant
7464 * Obtains a MonoClass with a given namespace and a given name which
7465 * is located in the given MonoImage. The namespace and name
7466 * lookups are case insensitive.
7469 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7472 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7473 g_assert (!mono_error_ok (&error));
7478 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7480 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7481 guint32 cols [MONO_TYPEDEF_SIZE];
7486 mono_error_init (error);
7488 if (image_is_dynamic (image)) {
7490 FindUserData user_data;
7492 mono_image_lock (image);
7494 if (!image->name_cache)
7495 mono_image_init_name_cache (image);
7497 user_data.key = name_space;
7498 user_data.value = NULL;
7499 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7501 if (user_data.value) {
7502 GHashTable *nspace_table = (GHashTable*)user_data.value;
7504 user_data.key = name;
7505 user_data.value = NULL;
7507 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7509 if (user_data.value)
7510 token = GPOINTER_TO_UINT (user_data.value);
7513 mono_image_unlock (image);
7516 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7522 /* add a cache if needed */
7523 for (i = 1; i <= t->rows; ++i) {
7524 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7525 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7527 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7528 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7530 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7532 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7533 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7534 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7535 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7541 return_nested_in (MonoClass *class, char *nested)
7544 char *s = strchr (nested, '/');
7545 gpointer iter = NULL;
7552 while ((found = mono_class_get_nested_types (class, &iter))) {
7553 if (strcmp (found->name, nested) == 0) {
7555 return return_nested_in (found, s);
7563 search_modules (MonoImage *image, const char *name_space, const char *name)
7565 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7566 MonoImage *file_image;
7571 * The EXPORTEDTYPES table only contains public types, so have to search the
7573 * Note: image->modules contains the contents of the MODULEREF table, while
7574 * the real module list is in the FILE table.
7576 for (i = 0; i < file_table->rows; i++) {
7577 guint32 cols [MONO_FILE_SIZE];
7578 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7579 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7582 file_image = mono_image_load_file_for_image (image, i + 1);
7584 class = mono_class_from_name (file_image, name_space, name);
7594 * mono_class_from_name:
7595 * @image: The MonoImage where the type is looked up in
7596 * @name_space: the type namespace
7597 * @name: the type short name.
7599 * Obtains a MonoClass with a given namespace and a given name which
7600 * is located in the given MonoImage.
7602 * To reference nested classes, use the "/" character as a separator.
7603 * For example use "Foo/Bar" to reference the class Bar that is nested
7604 * inside Foo, like this: "class Foo { class Bar {} }".
7607 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7609 GHashTable *nspace_table;
7610 MonoImage *loaded_image;
7617 if ((nested = strchr (name, '/'))) {
7618 int pos = nested - name;
7619 int len = strlen (name);
7622 memcpy (buf, name, len + 1);
7624 nested = buf + pos + 1;
7628 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7629 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7630 gboolean res = get_class_from_name (image, name_space, name, &class);
7633 class = search_modules (image, name_space, name);
7635 return class ? return_nested_in (class, nested) : NULL;
7641 mono_image_lock (image);
7643 if (!image->name_cache)
7644 mono_image_init_name_cache (image);
7646 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7649 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7651 mono_image_unlock (image);
7653 if (!token && image_is_dynamic (image) && image->modules) {
7654 /* Search modules as well */
7655 for (i = 0; i < image->module_count; ++i) {
7656 MonoImage *module = image->modules [i];
7658 class = mono_class_from_name (module, name_space, name);
7665 class = search_modules (image, name_space, name);
7673 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7674 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7675 guint32 cols [MONO_EXP_TYPE_SIZE];
7678 idx = mono_metadata_token_index (token);
7680 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7682 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7683 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7684 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7687 class = mono_class_from_name (loaded_image, name_space, name);
7689 return return_nested_in (class, nested);
7691 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7692 guint32 assembly_idx;
7694 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7696 mono_assembly_load_reference (image, assembly_idx - 1);
7697 g_assert (image->references [assembly_idx - 1]);
7698 if (image->references [assembly_idx - 1] == (gpointer)-1)
7701 /* FIXME: Cycle detection */
7702 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7704 g_error ("not yet implemented");
7708 token = MONO_TOKEN_TYPE_DEF | token;
7710 class = mono_class_get (image, token);
7712 return return_nested_in (class, nested);
7717 * mono_class_is_subclass_of:
7718 * @klass: class to probe if it is a subclass of another one
7719 * @klassc: the class we suspect is the base class
7720 * @check_interfaces: whether we should perform interface checks
7722 * This method determines whether @klass is a subclass of @klassc.
7724 * If the @check_interfaces flag is set, then if @klassc is an interface
7725 * this method return true if the @klass implements the interface or
7726 * if @klass is an interface, if one of its base classes is @klass.
7728 * If @check_interfaces is false then, then if @klass is not an interface
7729 * then it returns true if the @klass is a subclass of @klassc.
7731 * if @klass is an interface and @klassc is System.Object, then this function
7736 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7737 gboolean check_interfaces)
7739 /*FIXME test for interfaces with variant generic arguments*/
7741 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7742 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7744 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7747 for (i = 0; i < klass->interface_count; i ++) {
7748 MonoClass *ic = klass->interfaces [i];
7753 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7758 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7761 if (klassc == mono_defaults.object_class)
7768 mono_type_is_generic_argument (MonoType *type)
7770 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7774 mono_class_has_variant_generic_params (MonoClass *klass)
7777 MonoGenericContainer *container;
7779 if (!klass->generic_class)
7782 container = klass->generic_class->container_class->generic_container;
7784 for (i = 0; i < container->type_argc; ++i)
7785 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7792 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7794 if (target == candidate)
7797 if (check_for_reference_conv &&
7798 mono_type_is_generic_argument (&target->byval_arg) &&
7799 mono_type_is_generic_argument (&candidate->byval_arg)) {
7800 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7801 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7803 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7806 if (!mono_class_is_assignable_from (target, candidate))
7812 * @container the generic container from the GTD
7813 * @klass: the class to be assigned to
7814 * @oklass: the source class
7816 * Both klass and oklass must be instances of the same generic interface.
7817 * Return true if @klass can be assigned to a @klass variable
7820 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7823 MonoType **klass_argv, **oklass_argv;
7824 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7825 MonoGenericContainer *container = klass_gtd->generic_container;
7827 if (klass == oklass)
7830 /*Viable candidates are instances of the same generic interface*/
7831 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7834 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7835 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7837 for (j = 0; j < container->type_argc; ++j) {
7838 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7839 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7841 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7845 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7846 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7848 if (param1_class != param2_class) {
7849 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7850 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7852 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7853 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7863 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7865 MonoGenericParam *gparam, *ogparam;
7866 MonoGenericParamInfo *tinfo, *cinfo;
7867 MonoClass **candidate_class;
7868 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7871 if (target == candidate)
7873 if (target->byval_arg.type != candidate->byval_arg.type)
7876 gparam = target->byval_arg.data.generic_param;
7877 ogparam = candidate->byval_arg.data.generic_param;
7878 tinfo = mono_generic_param_info (gparam);
7879 cinfo = mono_generic_param_info (ogparam);
7881 class_constraint_satisfied = FALSE;
7882 valuetype_constraint_satisfied = FALSE;
7884 /*candidate must have a super set of target's special constraints*/
7885 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7886 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7888 if (cinfo->constraints) {
7889 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7890 MonoClass *cc = *candidate_class;
7892 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7893 class_constraint_satisfied = TRUE;
7894 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7895 valuetype_constraint_satisfied = TRUE;
7898 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7899 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7901 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7903 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7905 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7906 valuetype_constraint_satisfied)) {
7911 /*candidate type constraints must be a superset of target's*/
7912 if (tinfo->constraints) {
7913 MonoClass **target_class;
7914 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7915 MonoClass *tc = *target_class;
7918 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7919 * check it's constraints since it satisfy the constraint by itself.
7921 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7924 if (!cinfo->constraints)
7927 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7928 MonoClass *cc = *candidate_class;
7930 if (mono_class_is_assignable_from (tc, cc))
7934 * This happens when we have the following:
7936 * Bar<K> where K : IFace
7937 * Foo<T, U> where T : U where U : IFace
7939 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7942 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7943 if (mono_gparam_is_assignable_from (target, cc))
7947 if (!*candidate_class)
7952 /*candidate itself must have a constraint that satisfy target*/
7953 if (cinfo->constraints) {
7954 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7955 MonoClass *cc = *candidate_class;
7956 if (mono_class_is_assignable_from (target, cc))
7964 * mono_class_is_assignable_from:
7965 * @klass: the class to be assigned to
7966 * @oklass: the source class
7968 * Return: true if an instance of object oklass can be assigned to an
7969 * instance of object @klass
7972 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7974 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7976 mono_class_init (klass);
7978 if (!oklass->inited)
7979 mono_class_init (oklass);
7981 if (klass->exception_type || oklass->exception_type)
7984 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7985 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7987 return mono_gparam_is_assignable_from (klass, oklass);
7990 if (MONO_CLASS_IS_INTERFACE (klass)) {
7991 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7992 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7993 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7997 for (i = 0; constraints [i]; ++i) {
7998 if (mono_class_is_assignable_from (klass, constraints [i]))
8006 /* interface_offsets might not be set for dynamic classes */
8007 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8009 * oklass might be a generic type parameter but they have
8010 * interface_offsets set.
8012 return mono_reflection_call_is_assignable_to (oklass, klass);
8013 if (!oklass->interface_bitmap)
8014 /* Happens with generic instances of not-yet created dynamic types */
8016 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8019 if (mono_class_has_variant_generic_params (klass)) {
8022 mono_class_setup_interfaces (oklass, &error);
8023 if (!mono_error_ok (&error)) {
8024 mono_error_cleanup (&error);
8028 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8029 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8030 MonoClass *iface = oklass->interfaces_packed [i];
8032 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8037 } else if (klass->delegate) {
8038 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8040 }else if (klass->rank) {
8041 MonoClass *eclass, *eoclass;
8043 if (oklass->rank != klass->rank)
8046 /* vectors vs. one dimensional arrays */
8047 if (oklass->byval_arg.type != klass->byval_arg.type)
8050 eclass = klass->cast_class;
8051 eoclass = oklass->cast_class;
8054 * a is b does not imply a[] is b[] when a is a valuetype, and
8055 * b is a reference type.
8058 if (eoclass->valuetype) {
8059 if ((eclass == mono_defaults.enum_class) ||
8060 (eclass == mono_defaults.enum_class->parent) ||
8061 (eclass == mono_defaults.object_class))
8065 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8066 } else if (mono_class_is_nullable (klass)) {
8067 if (mono_class_is_nullable (oklass))
8068 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8070 return mono_class_is_assignable_from (klass->cast_class, oklass);
8071 } else if (klass == mono_defaults.object_class)
8074 return mono_class_has_parent (oklass, klass);
8077 /*Check if @oklass is variant compatible with @klass.*/
8079 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8082 MonoType **klass_argv, **oklass_argv;
8083 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8084 MonoGenericContainer *container = klass_gtd->generic_container;
8086 /*Viable candidates are instances of the same generic interface*/
8087 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8090 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8091 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8093 for (j = 0; j < container->type_argc; ++j) {
8094 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8095 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8097 if (param1_class->valuetype != param2_class->valuetype)
8101 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8102 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8104 if (param1_class != param2_class) {
8105 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8106 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8108 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8109 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8117 /*Check if @candidate implements the interface @target*/
8119 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8123 gboolean is_variant = mono_class_has_variant_generic_params (target);
8125 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8126 if (mono_class_is_variant_compatible_slow (target, candidate))
8131 if (candidate == target)
8134 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8135 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8136 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8138 if (tb && tb->interfaces) {
8139 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8140 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8141 MonoClass *iface_class;
8143 /* we can't realize the type here since it can do pretty much anything. */
8146 iface_class = mono_class_from_mono_type (iface->type);
8147 if (iface_class == target)
8149 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8151 if (mono_class_implement_interface_slow (target, iface_class))
8156 /*setup_interfaces don't mono_class_init anything*/
8157 /*FIXME this doesn't handle primitive type arrays.
8158 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8159 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8161 mono_class_setup_interfaces (candidate, &error);
8162 if (!mono_error_ok (&error)) {
8163 mono_error_cleanup (&error);
8167 for (i = 0; i < candidate->interface_count; ++i) {
8168 if (candidate->interfaces [i] == target)
8171 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8174 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8178 candidate = candidate->parent;
8179 } while (candidate);
8185 * Check if @oklass can be assigned to @klass.
8186 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8189 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8191 if (candidate == target)
8193 if (target == mono_defaults.object_class)
8196 if (mono_class_has_parent (candidate, target))
8199 /*If target is not an interface there is no need to check them.*/
8200 if (MONO_CLASS_IS_INTERFACE (target))
8201 return mono_class_implement_interface_slow (target, candidate);
8203 if (target->delegate && mono_class_has_variant_generic_params (target))
8204 return mono_class_is_variant_compatible (target, candidate, FALSE);
8207 MonoClass *eclass, *eoclass;
8209 if (target->rank != candidate->rank)
8212 /* vectors vs. one dimensional arrays */
8213 if (target->byval_arg.type != candidate->byval_arg.type)
8216 eclass = target->cast_class;
8217 eoclass = candidate->cast_class;
8220 * a is b does not imply a[] is b[] when a is a valuetype, and
8221 * b is a reference type.
8224 if (eoclass->valuetype) {
8225 if ((eclass == mono_defaults.enum_class) ||
8226 (eclass == mono_defaults.enum_class->parent) ||
8227 (eclass == mono_defaults.object_class))
8231 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8233 /*FIXME properly handle nullables */
8234 /*FIXME properly handle (M)VAR */
8239 * mono_class_get_cctor:
8240 * @klass: A MonoClass pointer
8242 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8245 mono_class_get_cctor (MonoClass *klass)
8247 MonoCachedClassInfo cached_info;
8249 if (image_is_dynamic (klass->image)) {
8251 * has_cctor is not set for these classes because mono_class_init () is
8254 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8257 if (!klass->has_cctor)
8260 if (mono_class_get_cached_class_info (klass, &cached_info))
8261 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8263 if (klass->generic_class && !klass->methods)
8264 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8266 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8270 * mono_class_get_finalizer:
8271 * @klass: The MonoClass pointer
8273 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8276 mono_class_get_finalizer (MonoClass *klass)
8278 MonoCachedClassInfo cached_info;
8281 mono_class_init (klass);
8282 if (!mono_class_has_finalizer (klass))
8285 if (mono_class_get_cached_class_info (klass, &cached_info))
8286 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8288 mono_class_setup_vtable (klass);
8289 return klass->vtable [finalize_slot];
8294 * mono_class_needs_cctor_run:
8295 * @klass: the MonoClass pointer
8296 * @caller: a MonoMethod describing the caller
8298 * Determines whenever the class has a static constructor and whenever it
8299 * needs to be called when executing CALLER.
8302 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8306 method = mono_class_get_cctor (klass);
8308 return (method == caller) ? FALSE : TRUE;
8314 * mono_class_array_element_size:
8317 * Returns: the number of bytes an element of type @klass
8318 * uses when stored into an array.
8321 mono_class_array_element_size (MonoClass *klass)
8323 MonoType *type = &klass->byval_arg;
8326 switch (type->type) {
8329 case MONO_TYPE_BOOLEAN:
8333 case MONO_TYPE_CHAR:
8342 case MONO_TYPE_CLASS:
8343 case MONO_TYPE_STRING:
8344 case MONO_TYPE_OBJECT:
8345 case MONO_TYPE_SZARRAY:
8346 case MONO_TYPE_ARRAY:
8348 case MONO_TYPE_MVAR:
8349 return sizeof (gpointer);
8354 case MONO_TYPE_VALUETYPE:
8355 if (type->data.klass->enumtype) {
8356 type = mono_class_enum_basetype (type->data.klass);
8357 klass = klass->element_class;
8360 return mono_class_instance_size (klass) - sizeof (MonoObject);
8361 case MONO_TYPE_GENERICINST:
8362 type = &type->data.generic_class->container_class->byval_arg;
8365 case MONO_TYPE_VOID:
8369 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8375 * mono_array_element_size:
8376 * @ac: pointer to a #MonoArrayClass
8378 * Returns: the size of single array element.
8381 mono_array_element_size (MonoClass *ac)
8383 g_assert (ac->rank);
8384 return ac->sizes.element_size;
8388 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8389 MonoGenericContext *context)
8391 if (image_is_dynamic (image)) {
8392 MonoClass *tmp_handle_class;
8393 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8395 g_assert (tmp_handle_class);
8397 *handle_class = tmp_handle_class;
8399 if (tmp_handle_class == mono_defaults.typehandle_class)
8400 return &((MonoClass*)obj)->byval_arg;
8405 switch (token & 0xff000000) {
8406 case MONO_TOKEN_TYPE_DEF:
8407 case MONO_TOKEN_TYPE_REF:
8408 case MONO_TOKEN_TYPE_SPEC: {
8412 *handle_class = mono_defaults.typehandle_class;
8413 type = mono_type_get_checked (image, token, context, &error);
8415 mono_loader_set_error_from_mono_error (&error);
8416 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8419 mono_class_init (mono_class_from_mono_type (type));
8420 /* We return a MonoType* as handle */
8423 case MONO_TOKEN_FIELD_DEF: {
8426 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8430 *handle_class = mono_defaults.fieldhandle_class;
8431 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8433 mono_loader_set_error_from_mono_error (&error);
8434 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8437 mono_class_init (class);
8438 return mono_class_get_field (class, token);
8440 case MONO_TOKEN_METHOD_DEF:
8441 case MONO_TOKEN_METHOD_SPEC: {
8443 meth = mono_get_method_full (image, token, NULL, context);
8445 *handle_class = mono_defaults.methodhandle_class;
8448 case MONO_TOKEN_MEMBER_REF: {
8449 guint32 cols [MONO_MEMBERREF_SIZE];
8451 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8452 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8453 mono_metadata_decode_blob_size (sig, &sig);
8454 if (*sig == 0x6) { /* it's a field */
8456 MonoClassField *field;
8457 field = mono_field_from_token (image, token, &klass, context);
8459 *handle_class = mono_defaults.fieldhandle_class;
8463 meth = mono_get_method_full (image, token, NULL, context);
8465 *handle_class = mono_defaults.methodhandle_class;
8470 g_warning ("Unknown token 0x%08x in ldtoken", token);
8477 * This function might need to call runtime functions so it can't be part
8478 * of the metadata library.
8480 static MonoLookupDynamicToken lookup_dynamic = NULL;
8483 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8485 lookup_dynamic = func;
8489 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8491 MonoClass *handle_class;
8493 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8497 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8499 return lookup_dynamic (image, token, valid_token, handle_class, context);
8502 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8505 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8507 get_cached_class_info = func;
8511 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8513 if (!get_cached_class_info)
8516 return get_cached_class_info (klass, res);
8520 mono_install_get_class_from_name (MonoGetClassFromName func)
8522 get_class_from_name = func;
8526 mono_class_get_image (MonoClass *klass)
8528 return klass->image;
8532 * mono_class_get_element_class:
8533 * @klass: the MonoClass to act on
8535 * Returns: the element class of an array or an enumeration.
8538 mono_class_get_element_class (MonoClass *klass)
8540 return klass->element_class;
8544 * mono_class_is_valuetype:
8545 * @klass: the MonoClass to act on
8547 * Returns: true if the MonoClass represents a ValueType.
8550 mono_class_is_valuetype (MonoClass *klass)
8552 return klass->valuetype;
8556 * mono_class_is_enum:
8557 * @klass: the MonoClass to act on
8559 * Returns: true if the MonoClass represents an enumeration.
8562 mono_class_is_enum (MonoClass *klass)
8564 return klass->enumtype;
8568 * mono_class_enum_basetype:
8569 * @klass: the MonoClass to act on
8571 * Returns: the underlying type representation for an enumeration.
8574 mono_class_enum_basetype (MonoClass *klass)
8576 if (klass->element_class == klass)
8577 /* SRE or broken types */
8580 return &klass->element_class->byval_arg;
8584 * mono_class_get_parent
8585 * @klass: the MonoClass to act on
8587 * Returns: the parent class for this class.
8590 mono_class_get_parent (MonoClass *klass)
8592 return klass->parent;
8596 * mono_class_get_nesting_type;
8597 * @klass: the MonoClass to act on
8599 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8602 mono_class_get_nesting_type (MonoClass *klass)
8604 return klass->nested_in;
8608 * mono_class_get_rank:
8609 * @klass: the MonoClass to act on
8611 * Returns: the rank for the array (the number of dimensions).
8614 mono_class_get_rank (MonoClass *klass)
8620 * mono_class_get_flags:
8621 * @klass: the MonoClass to act on
8623 * The type flags from the TypeDef table from the metadata.
8624 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8627 * Returns: the flags from the TypeDef table.
8630 mono_class_get_flags (MonoClass *klass)
8632 return klass->flags;
8636 * mono_class_get_name
8637 * @klass: the MonoClass to act on
8639 * Returns: the name of the class.
8642 mono_class_get_name (MonoClass *klass)
8648 * mono_class_get_namespace:
8649 * @klass: the MonoClass to act on
8651 * Returns: the namespace of the class.
8654 mono_class_get_namespace (MonoClass *klass)
8656 return klass->name_space;
8660 * mono_class_get_type:
8661 * @klass: the MonoClass to act on
8663 * This method returns the internal Type representation for the class.
8665 * Returns: the MonoType from the class.
8668 mono_class_get_type (MonoClass *klass)
8670 return &klass->byval_arg;
8674 * mono_class_get_type_token
8675 * @klass: the MonoClass to act on
8677 * This method returns type token for the class.
8679 * Returns: the type token for the class.
8682 mono_class_get_type_token (MonoClass *klass)
8684 return klass->type_token;
8688 * mono_class_get_byref_type:
8689 * @klass: the MonoClass to act on
8694 mono_class_get_byref_type (MonoClass *klass)
8696 return &klass->this_arg;
8700 * mono_class_num_fields:
8701 * @klass: the MonoClass to act on
8703 * Returns: the number of static and instance fields in the class.
8706 mono_class_num_fields (MonoClass *klass)
8708 return klass->field.count;
8712 * mono_class_num_methods:
8713 * @klass: the MonoClass to act on
8715 * Returns: the number of methods in the class.
8718 mono_class_num_methods (MonoClass *klass)
8720 return klass->method.count;
8724 * mono_class_num_properties
8725 * @klass: the MonoClass to act on
8727 * Returns: the number of properties in the class.
8730 mono_class_num_properties (MonoClass *klass)
8732 mono_class_setup_properties (klass);
8734 return klass->ext->property.count;
8738 * mono_class_num_events:
8739 * @klass: the MonoClass to act on
8741 * Returns: the number of events in the class.
8744 mono_class_num_events (MonoClass *klass)
8746 mono_class_setup_events (klass);
8748 return klass->ext->event.count;
8752 * mono_class_get_fields:
8753 * @klass: the MonoClass to act on
8755 * This routine is an iterator routine for retrieving the fields in a class.
8757 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8758 * iterate over all of the elements. When no more values are
8759 * available, the return value is NULL.
8761 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8764 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8766 MonoClassField* field;
8770 mono_class_setup_fields_locking (klass);
8771 if (klass->exception_type)
8773 /* start from the first */
8774 if (klass->field.count) {
8775 return *iter = &klass->fields [0];
8783 if (field < &klass->fields [klass->field.count]) {
8784 return *iter = field;
8790 * mono_class_get_methods
8791 * @klass: the MonoClass to act on
8793 * This routine is an iterator routine for retrieving the fields in a class.
8795 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8796 * iterate over all of the elements. When no more values are
8797 * available, the return value is NULL.
8799 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8802 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8804 MonoMethod** method;
8808 mono_class_setup_methods (klass);
8811 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8812 * FIXME we should better report this error to the caller
8814 if (!klass->methods)
8816 /* start from the first */
8817 if (klass->method.count) {
8818 *iter = &klass->methods [0];
8819 return klass->methods [0];
8827 if (method < &klass->methods [klass->method.count]) {
8835 * mono_class_get_virtual_methods:
8837 * Iterate over the virtual methods of KLASS.
8839 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8842 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8844 MonoMethod** method;
8847 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8849 mono_class_setup_methods (klass);
8851 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8852 * FIXME we should better report this error to the caller
8854 if (!klass->methods)
8856 /* start from the first */
8857 method = &klass->methods [0];
8862 while (method < &klass->methods [klass->method.count]) {
8863 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8867 if (method < &klass->methods [klass->method.count]) {
8874 /* Search directly in metadata to avoid calling setup_methods () */
8875 MonoMethod *res = NULL;
8881 start_index = GPOINTER_TO_UINT (*iter);
8884 for (i = start_index; i < klass->method.count; ++i) {
8887 /* class->method.first points into the methodptr table */
8888 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8890 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8894 if (i < klass->method.count) {
8895 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8896 /* Add 1 here so the if (*iter) check fails */
8897 *iter = GUINT_TO_POINTER (i + 1);
8906 * mono_class_get_properties:
8907 * @klass: the MonoClass to act on
8909 * This routine is an iterator routine for retrieving the properties in a class.
8911 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8912 * iterate over all of the elements. When no more values are
8913 * available, the return value is NULL.
8915 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8918 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8920 MonoProperty* property;
8924 mono_class_setup_properties (klass);
8925 /* start from the first */
8926 if (klass->ext->property.count) {
8927 return *iter = &klass->ext->properties [0];
8935 if (property < &klass->ext->properties [klass->ext->property.count]) {
8936 return *iter = property;
8942 * mono_class_get_events:
8943 * @klass: the MonoClass to act on
8945 * This routine is an iterator routine for retrieving the properties in a class.
8947 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8948 * iterate over all of the elements. When no more values are
8949 * available, the return value is NULL.
8951 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8954 mono_class_get_events (MonoClass* klass, gpointer *iter)
8960 mono_class_setup_events (klass);
8961 /* start from the first */
8962 if (klass->ext->event.count) {
8963 return *iter = &klass->ext->events [0];
8971 if (event < &klass->ext->events [klass->ext->event.count]) {
8972 return *iter = event;
8978 * mono_class_get_interfaces
8979 * @klass: the MonoClass to act on
8981 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8983 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8984 * iterate over all of the elements. When no more values are
8985 * available, the return value is NULL.
8987 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8990 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8998 mono_class_init (klass);
8999 if (!klass->interfaces_inited) {
9000 mono_class_setup_interfaces (klass, &error);
9001 if (!mono_error_ok (&error)) {
9002 mono_error_cleanup (&error);
9006 /* start from the first */
9007 if (klass->interface_count) {
9008 *iter = &klass->interfaces [0];
9009 return klass->interfaces [0];
9017 if (iface < &klass->interfaces [klass->interface_count]) {
9025 setup_nested_types (MonoClass *klass)
9028 GList *classes, *nested_classes, *l;
9031 if (klass->nested_classes_inited)
9034 if (!klass->type_token)
9035 klass->nested_classes_inited = TRUE;
9037 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9041 guint32 cols [MONO_NESTED_CLASS_SIZE];
9042 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9043 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9044 if (!mono_error_ok (&error)) {
9045 /*FIXME don't swallow the error message*/
9046 mono_error_cleanup (&error);
9048 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9052 classes = g_list_prepend (classes, nclass);
9054 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9057 mono_class_alloc_ext (klass);
9059 nested_classes = NULL;
9060 for (l = classes; l; l = l->next)
9061 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9062 g_list_free (classes);
9064 mono_image_lock (klass->image);
9066 mono_memory_barrier ();
9067 if (!klass->nested_classes_inited) {
9068 klass->ext->nested_classes = nested_classes;
9069 mono_memory_barrier ();
9070 klass->nested_classes_inited = TRUE;
9073 mono_image_unlock (klass->image);
9077 * mono_class_get_nested_types
9078 * @klass: the MonoClass to act on
9080 * This routine is an iterator routine for retrieving the nested types of a class.
9081 * This works only if @klass is non-generic, or a generic type definition.
9083 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9084 * iterate over all of the elements. When no more values are
9085 * available, the return value is NULL.
9087 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9090 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9096 if (!klass->nested_classes_inited)
9097 setup_nested_types (klass);
9100 /* start from the first */
9101 if (klass->ext && klass->ext->nested_classes) {
9102 *iter = klass->ext->nested_classes;
9103 return klass->ext->nested_classes->data;
9105 /* no nested types */
9120 * mono_class_is_delegate
9121 * @klass: the MonoClass to act on
9123 * Returns: true if the MonoClass represents a System.Delegate.
9126 mono_class_is_delegate (MonoClass *klass)
9128 return klass->delegate;
9132 * mono_class_implements_interface
9133 * @klass: The MonoClass to act on
9134 * @interface: The interface to check if @klass implements.
9136 * Returns: true if @klass implements @interface.
9139 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9141 return mono_class_is_assignable_from (iface, klass);
9145 * mono_field_get_name:
9146 * @field: the MonoClassField to act on
9148 * Returns: the name of the field.
9151 mono_field_get_name (MonoClassField *field)
9157 * mono_field_get_type:
9158 * @field: the MonoClassField to act on
9160 * Returns: MonoType of the field.
9163 mono_field_get_type (MonoClassField *field)
9166 MonoType *type = mono_field_get_type_checked (field, &error);
9167 if (!mono_error_ok (&error)) {
9168 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9169 mono_error_cleanup (&error);
9176 * mono_field_get_type_checked:
9177 * @field: the MonoClassField to act on
9178 * @error: used to return any erro found while retrieving @field type
9180 * Returns: MonoType of the field.
9183 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9185 mono_error_init (error);
9187 mono_field_resolve_type (field, error);
9192 * mono_field_get_parent:
9193 * @field: the MonoClassField to act on
9195 * Returns: MonoClass where the field was defined.
9198 mono_field_get_parent (MonoClassField *field)
9200 return field->parent;
9204 * mono_field_get_flags;
9205 * @field: the MonoClassField to act on
9207 * The metadata flags for a field are encoded using the
9208 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9210 * Returns: the flags for the field.
9213 mono_field_get_flags (MonoClassField *field)
9216 return mono_field_resolve_flags (field);
9217 return field->type->attrs;
9221 * mono_field_get_offset;
9222 * @field: the MonoClassField to act on
9224 * Returns: the field offset.
9227 mono_field_get_offset (MonoClassField *field)
9229 return field->offset;
9233 mono_field_get_rva (MonoClassField *field)
9237 MonoClass *klass = field->parent;
9238 MonoFieldDefaultValue *field_def_values;
9240 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9242 if (!klass->ext || !klass->ext->field_def_values) {
9243 mono_class_alloc_ext (klass);
9245 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9247 mono_image_lock (klass->image);
9248 if (!klass->ext->field_def_values)
9249 klass->ext->field_def_values = field_def_values;
9250 mono_image_unlock (klass->image);
9253 field_index = mono_field_get_index (field);
9255 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9256 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9258 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9259 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9262 return klass->ext->field_def_values [field_index].data;
9266 * mono_field_get_data;
9267 * @field: the MonoClassField to act on
9269 * Returns: pointer to the metadata constant value or to the field
9270 * data if it has an RVA flag.
9273 mono_field_get_data (MonoClassField *field)
9275 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9276 MonoTypeEnum def_type;
9278 return mono_class_get_field_default_value (field, &def_type);
9279 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9280 return mono_field_get_rva (field);
9287 * mono_property_get_name:
9288 * @prop: the MonoProperty to act on
9290 * Returns: the name of the property
9293 mono_property_get_name (MonoProperty *prop)
9299 * mono_property_get_set_method
9300 * @prop: the MonoProperty to act on.
9302 * Returns: the setter method of the property (A MonoMethod)
9305 mono_property_get_set_method (MonoProperty *prop)
9311 * mono_property_get_get_method
9312 * @prop: the MonoProperty to act on.
9314 * Returns: the setter method of the property (A MonoMethod)
9317 mono_property_get_get_method (MonoProperty *prop)
9323 * mono_property_get_parent:
9324 * @prop: the MonoProperty to act on.
9326 * Returns: the MonoClass where the property was defined.
9329 mono_property_get_parent (MonoProperty *prop)
9331 return prop->parent;
9335 * mono_property_get_flags:
9336 * @prop: the MonoProperty to act on.
9338 * The metadata flags for a property are encoded using the
9339 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9341 * Returns: the flags for the property.
9344 mono_property_get_flags (MonoProperty *prop)
9350 * mono_event_get_name:
9351 * @event: the MonoEvent to act on
9353 * Returns: the name of the event.
9356 mono_event_get_name (MonoEvent *event)
9362 * mono_event_get_add_method:
9363 * @event: The MonoEvent to act on.
9365 * Returns: the @add' method for the event (a MonoMethod).
9368 mono_event_get_add_method (MonoEvent *event)
9374 * mono_event_get_remove_method:
9375 * @event: The MonoEvent to act on.
9377 * Returns: the @remove method for the event (a MonoMethod).
9380 mono_event_get_remove_method (MonoEvent *event)
9382 return event->remove;
9386 * mono_event_get_raise_method:
9387 * @event: The MonoEvent to act on.
9389 * Returns: the @raise method for the event (a MonoMethod).
9392 mono_event_get_raise_method (MonoEvent *event)
9394 return event->raise;
9398 * mono_event_get_parent:
9399 * @event: the MonoEvent to act on.
9401 * Returns: the MonoClass where the event is defined.
9404 mono_event_get_parent (MonoEvent *event)
9406 return event->parent;
9410 * mono_event_get_flags
9411 * @event: the MonoEvent to act on.
9413 * The metadata flags for an event are encoded using the
9414 * EVENT_* constants. See the tabledefs.h file for details.
9416 * Returns: the flags for the event.
9419 mono_event_get_flags (MonoEvent *event)
9421 return event->attrs;
9425 * mono_class_get_method_from_name:
9426 * @klass: where to look for the method
9427 * @name: name of the method
9428 * @param_count: number of parameters. -1 for any number.
9430 * Obtains a MonoMethod with a given name and number of parameters.
9431 * It only works if there are no multiple signatures for any given method name.
9434 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9436 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9440 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9442 MonoMethod *res = NULL;
9445 /* Search directly in the metadata to avoid calling setup_methods () */
9446 for (i = 0; i < klass->method.count; ++i) {
9447 guint32 cols [MONO_METHOD_SIZE];
9449 MonoMethodSignature *sig;
9451 /* class->method.first points into the methodptr table */
9452 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9454 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9455 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9456 if (param_count == -1) {
9460 sig = mono_method_signature (method);
9461 if (sig && sig->param_count == param_count) {
9472 * mono_class_get_method_from_name_flags:
9473 * @klass: where to look for the method
9474 * @name_space: name of the method
9475 * @param_count: number of parameters. -1 for any number.
9476 * @flags: flags which must be set in the method
9478 * Obtains a MonoMethod with a given name and number of parameters.
9479 * It only works if there are no multiple signatures for any given method name.
9482 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9484 MonoMethod *res = NULL;
9487 mono_class_init (klass);
9489 if (klass->generic_class && !klass->methods) {
9490 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9492 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9496 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9497 mono_class_setup_methods (klass);
9499 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9500 See mono/tests/array_load_exception.il
9501 FIXME we should better report this error to the caller
9503 if (!klass->methods)
9505 for (i = 0; i < klass->method.count; ++i) {
9506 MonoMethod *method = klass->methods [i];
9508 if (method->name[0] == name [0] &&
9509 !strcmp (name, method->name) &&
9510 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9511 ((method->flags & flags) == flags)) {
9518 res = find_method_in_metadata (klass, name, param_count, flags);
9525 * mono_class_set_failure:
9526 * @klass: class in which the failure was detected
9527 * @ex_type: the kind of exception/error to be thrown (later)
9528 * @ex_data: exception data (specific to each type of exception/error)
9530 * Keep a detected failure informations in the class for later processing.
9531 * Note that only the first failure is kept.
9533 * LOCKING: Acquires the loader lock.
9536 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9538 if (klass->exception_type)
9541 mono_loader_lock ();
9542 klass->exception_type = ex_type;
9544 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9545 mono_loader_unlock ();
9551 * mono_class_get_exception_data:
9553 * Return the exception_data property of KLASS.
9555 * LOCKING: Acquires the loader lock.
9558 mono_class_get_exception_data (MonoClass *klass)
9560 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9564 * mono_classes_init:
9566 * Initialize the resources used by this module.
9569 mono_classes_init (void)
9571 mono_mutex_init (&classes_mutex);
9573 mono_counters_register ("Inflated methods size",
9574 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9575 mono_counters_register ("Inflated classes",
9576 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9577 mono_counters_register ("Inflated classes size",
9578 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9579 mono_counters_register ("MonoClass size",
9580 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9581 mono_counters_register ("MonoClassExt size",
9582 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9586 * mono_classes_cleanup:
9588 * Free the resources used by this module.
9591 mono_classes_cleanup (void)
9593 if (global_interface_bitset)
9594 mono_bitset_free (global_interface_bitset);
9595 global_interface_bitset = NULL;
9596 mono_mutex_destroy (&classes_mutex);
9600 * mono_class_get_exception_for_failure:
9601 * @klass: class in which the failure was detected
9603 * Return a constructed MonoException than the caller can then throw
9604 * using mono_raise_exception - or NULL if no failure is present (or
9605 * doesn't result in an exception).
9608 mono_class_get_exception_for_failure (MonoClass *klass)
9610 gpointer exception_data = mono_class_get_exception_data (klass);
9612 switch (klass->exception_type) {
9613 #ifndef DISABLE_SECURITY
9614 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9615 MonoDomain *domain = mono_domain_get ();
9616 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9617 MonoMethod *method = exception_data;
9618 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9619 MonoObject *exc = NULL;
9623 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9624 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9625 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9627 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9628 return (MonoException*) exc;
9631 case MONO_EXCEPTION_TYPE_LOAD: {
9634 char *str = mono_type_get_full_name (klass);
9635 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9636 name = mono_string_new (mono_domain_get (), str);
9638 ex = mono_get_exception_type_load (name, astr);
9642 case MONO_EXCEPTION_MISSING_METHOD: {
9643 char *class_name = exception_data;
9644 char *assembly_name = class_name + strlen (class_name) + 1;
9646 return mono_get_exception_missing_method (class_name, assembly_name);
9648 case MONO_EXCEPTION_MISSING_FIELD: {
9649 char *class_name = exception_data;
9650 char *member_name = class_name + strlen (class_name) + 1;
9652 return mono_get_exception_missing_field (class_name, member_name);
9654 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9655 char *msg_format = exception_data;
9656 char *assembly_name = msg_format + strlen (msg_format) + 1;
9657 char *msg = g_strdup_printf (msg_format, assembly_name);
9660 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9666 case MONO_EXCEPTION_BAD_IMAGE: {
9667 return mono_get_exception_bad_image_format (exception_data);
9670 MonoLoaderError *error;
9673 error = mono_loader_get_last_error ();
9675 ex = mono_loader_error_prepare_exception (error);
9679 /* TODO - handle other class related failures */
9686 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9688 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9689 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9691 if (outer_klass == inner_klass)
9693 inner_klass = inner_klass->nested_in;
9694 } while (inner_klass);
9699 mono_class_get_generic_type_definition (MonoClass *klass)
9701 return klass->generic_class ? klass->generic_class->container_class : klass;
9705 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9707 * Generic instantiations are ignored for all super types of @klass.
9709 * Visibility checks ignoring generic instantiations.
9712 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9715 klass = mono_class_get_generic_type_definition (klass);
9716 parent = mono_class_get_generic_type_definition (parent);
9717 mono_class_setup_supertypes (klass);
9719 for (i = 0; i < klass->idepth; ++i) {
9720 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9726 * Subtype can only access parent members with family protection if the site object
9727 * is subclass of Subtype. For example:
9728 * class A { protected int x; }
9730 * void valid_access () {
9734 * void invalid_access () {
9741 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9743 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9746 if (context_klass == NULL)
9748 /*if access_klass is not member_klass context_klass must be type compat*/
9749 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9755 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9758 if (accessing == accessed)
9760 if (!accessed || !accessing)
9763 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9764 * anywhere so untrusted friends are not safe to access platform's code internals */
9765 if (mono_security_core_clr_enabled ()) {
9766 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9770 mono_assembly_load_friends (accessed);
9771 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9772 MonoAssemblyName *friend = tmp->data;
9773 /* Be conservative with checks */
9776 if (strcmp (accessing->aname.name, friend->name))
9778 if (friend->public_key_token [0]) {
9779 if (!accessing->aname.public_key_token [0])
9781 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9790 * If klass is a generic type or if it is derived from a generic type, return the
9791 * MonoClass of the generic definition
9792 * Returns NULL if not found
9795 get_generic_definition_class (MonoClass *klass)
9798 if (klass->generic_class && klass->generic_class->container_class)
9799 return klass->generic_class->container_class;
9800 klass = klass->parent;
9806 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9809 for (i = 0; i < ginst->type_argc; ++i) {
9810 MonoType *type = ginst->type_argv[i];
9811 switch (type->type) {
9812 case MONO_TYPE_SZARRAY:
9813 if (!can_access_type (access_klass, type->data.klass))
9816 case MONO_TYPE_ARRAY:
9817 if (!can_access_type (access_klass, type->data.array->eklass))
9821 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9824 case MONO_TYPE_CLASS:
9825 case MONO_TYPE_VALUETYPE:
9826 case MONO_TYPE_GENERICINST:
9827 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9835 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9839 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9842 if (access_klass->element_class && !access_klass->enumtype)
9843 access_klass = access_klass->element_class;
9845 if (member_klass->element_class && !member_klass->enumtype)
9846 member_klass = member_klass->element_class;
9848 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9850 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9853 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9856 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9859 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9862 /*Non nested type with nested visibility. We just fail it.*/
9863 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9866 switch (access_level) {
9867 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9868 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9870 case TYPE_ATTRIBUTE_PUBLIC:
9873 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9876 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9877 return is_nesting_type (member_klass, access_klass);
9879 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9880 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9882 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9883 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9885 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9886 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9887 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9889 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9890 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9891 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9896 /* FIXME: check visibility of type, too */
9898 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9900 MonoClass *member_generic_def;
9901 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9904 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9905 access_klass->generic_container) &&
9906 (member_generic_def = get_generic_definition_class (member_klass))) {
9907 MonoClass *access_container;
9909 if (access_klass->generic_container)
9910 access_container = access_klass;
9912 access_container = access_klass->generic_class->container_class;
9914 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9918 /* Partition I 8.5.3.2 */
9919 /* the access level values are the same for fields and methods */
9920 switch (access_level) {
9921 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9922 /* same compilation unit */
9923 return access_klass->image == member_klass->image;
9924 case FIELD_ATTRIBUTE_PRIVATE:
9925 return access_klass == member_klass;
9926 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9927 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9928 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9931 case FIELD_ATTRIBUTE_ASSEMBLY:
9932 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9933 case FIELD_ATTRIBUTE_FAMILY:
9934 if (is_valid_family_access (access_klass, member_klass, context_klass))
9937 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9938 if (is_valid_family_access (access_klass, member_klass, context_klass))
9940 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9941 case FIELD_ATTRIBUTE_PUBLIC:
9948 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9950 /* FIXME: check all overlapping fields */
9951 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9953 MonoClass *nested = method->klass->nested_in;
9955 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9958 nested = nested->nested_in;
9965 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9967 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9969 MonoClass *nested = method->klass->nested_in;
9971 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9974 nested = nested->nested_in;
9979 * with generics calls to explicit interface implementations can be expressed
9980 * directly: the method is private, but we must allow it. This may be opening
9981 * a hole or the generics code should handle this differently.
9982 * Maybe just ensure the interface type is public.
9984 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9990 * mono_method_can_access_method_full:
9991 * @method: The caller method
9992 * @called: The called method
9993 * @context_klass: The static type on stack of the owner @called object used
9995 * This function must be used with instance calls, as they have more strict family accessibility.
9996 * It can be used with static methods, but context_klass should be NULL.
9998 * Returns: TRUE if caller have proper visibility and acessibility to @called
10001 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10003 MonoClass *access_class = method->klass;
10004 MonoClass *member_class = called->klass;
10005 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10007 MonoClass *nested = access_class->nested_in;
10009 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10012 nested = nested->nested_in;
10019 can = can_access_type (access_class, member_class);
10021 MonoClass *nested = access_class->nested_in;
10023 can = can_access_type (nested, member_class);
10026 nested = nested->nested_in;
10033 if (called->is_inflated) {
10034 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10035 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10044 * mono_method_can_access_field_full:
10045 * @method: The caller method
10046 * @field: The accessed field
10047 * @context_klass: The static type on stack of the owner @field object used
10049 * This function must be used with instance fields, as they have more strict family accessibility.
10050 * It can be used with static fields, but context_klass should be NULL.
10052 * Returns: TRUE if caller have proper visibility and acessibility to @field
10055 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10057 MonoClass *access_class = method->klass;
10058 MonoClass *member_class = field->parent;
10059 /* FIXME: check all overlapping fields */
10060 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10062 MonoClass *nested = access_class->nested_in;
10064 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10067 nested = nested->nested_in;
10074 can = can_access_type (access_class, member_class);
10076 MonoClass *nested = access_class->nested_in;
10078 can = can_access_type (nested, member_class);
10081 nested = nested->nested_in;
10091 * mono_class_can_access_class:
10092 * @source_class: The source class
10093 * @target_class: The accessed class
10095 * This function returns is @target_class is visible to @source_class
10097 * Returns: TRUE if source have proper visibility and acessibility to target
10100 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10102 return can_access_type (source_class, target_class);
10106 * mono_type_is_valid_enum_basetype:
10107 * @type: The MonoType to check
10109 * Returns: TRUE if the type can be used as the basetype of an enum
10111 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10112 switch (type->type) {
10115 case MONO_TYPE_BOOLEAN:
10118 case MONO_TYPE_CHAR:
10131 * mono_class_is_valid_enum:
10132 * @klass: An enum class to be validated
10134 * This method verify the required properties an enum should have.
10136 * Returns: TRUE if the informed enum class is valid
10138 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10139 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10140 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10142 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10143 MonoClassField * field;
10144 gpointer iter = NULL;
10145 gboolean found_base_field = FALSE;
10147 g_assert (klass->enumtype);
10148 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10149 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10153 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10156 while ((field = mono_class_get_fields (klass, &iter))) {
10157 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10158 if (found_base_field)
10160 found_base_field = TRUE;
10161 if (!mono_type_is_valid_enum_basetype (field->type))
10166 if (!found_base_field)
10169 if (klass->method.count > 0)
10176 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10178 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10182 * mono_class_setup_interface_id:
10184 * Initializes MonoClass::interface_id if required.
10186 * LOCKING: Acquires the loader lock.
10189 mono_class_setup_interface_id (MonoClass *class)
10191 mono_loader_lock ();
10192 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10193 class->interface_id = mono_get_unique_iid (class);
10194 mono_loader_unlock ();
10198 * mono_class_alloc_ext:
10200 * Allocate klass->ext if not already done.
10203 mono_class_alloc_ext (MonoClass *klass)
10210 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10211 mono_image_lock (klass->image);
10212 mono_memory_barrier ();
10215 class_ext_size += sizeof (MonoClassExt);
10216 mono_image_unlock (klass->image);
10220 * mono_class_setup_interfaces:
10222 * Initialize class->interfaces/interfaces_count.
10223 * LOCKING: Acquires the loader lock.
10224 * This function can fail the type.
10227 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10229 int i, interface_count;
10230 MonoClass **interfaces;
10232 mono_error_init (error);
10234 if (klass->interfaces_inited)
10237 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10238 MonoType *args [1];
10240 /* generic IList, ICollection, IEnumerable */
10241 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10242 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10244 args [0] = &klass->element_class->byval_arg;
10245 interfaces [0] = mono_class_bind_generic_parameters (
10246 mono_defaults.generic_ilist_class, 1, args, FALSE);
10247 if (interface_count > 1)
10248 interfaces [1] = mono_class_bind_generic_parameters (
10249 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10250 } else if (klass->generic_class) {
10251 MonoClass *gklass = klass->generic_class->container_class;
10253 mono_class_setup_interfaces (gklass, error);
10254 if (!mono_error_ok (error)) {
10255 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10259 interface_count = gklass->interface_count;
10260 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10261 for (i = 0; i < interface_count; i++) {
10262 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10263 if (!mono_error_ok (error)) {
10264 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10269 interface_count = 0;
10273 mono_image_lock (klass->image);
10275 if (!klass->interfaces_inited) {
10276 klass->interface_count = interface_count;
10277 klass->interfaces = interfaces;
10279 mono_memory_barrier ();
10281 klass->interfaces_inited = TRUE;
10284 mono_image_unlock (klass->image);
10288 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10290 MonoClass *class = field->parent;
10291 MonoImage *image = class->image;
10292 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10293 int field_idx = field - class->fields;
10295 mono_error_init (error);
10298 MonoClassField *gfield = >d->fields [field_idx];
10299 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10300 if (!mono_error_ok (error)) {
10301 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10302 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10306 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10307 if (!mono_error_ok (error)) {
10308 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10309 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10314 guint32 cols [MONO_FIELD_SIZE];
10315 MonoGenericContainer *container = NULL;
10316 int idx = class->field.first + field_idx;
10318 /*FIXME, in theory we do not lazy load SRE fields*/
10319 g_assert (!image_is_dynamic (image));
10321 if (class->generic_container) {
10322 container = class->generic_container;
10324 container = gtd->generic_container;
10325 g_assert (container);
10328 /* class->field.first and idx points into the fieldptr table */
10329 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10331 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10332 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10333 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10337 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10339 mono_metadata_decode_value (sig, &sig);
10340 /* FIELD signature == 0x06 */
10341 g_assert (*sig == 0x06);
10342 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10344 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10349 mono_field_resolve_flags (MonoClassField *field)
10351 MonoClass *class = field->parent;
10352 MonoImage *image = class->image;
10353 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10354 int field_idx = field - class->fields;
10358 MonoClassField *gfield = >d->fields [field_idx];
10359 return mono_field_get_flags (gfield);
10361 int idx = class->field.first + field_idx;
10363 /*FIXME, in theory we do not lazy load SRE fields*/
10364 g_assert (!image_is_dynamic (image));
10366 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10371 * mono_class_setup_basic_field_info:
10372 * @class: The class to initialize
10374 * Initializes the class->fields array of fields.
10375 * Aquires the loader lock.
10378 mono_class_setup_basic_field_info_locking (MonoClass *class)
10380 mono_loader_lock ();
10381 mono_class_setup_basic_field_info (class);
10382 mono_loader_unlock ();
10386 * mono_class_get_fields_lazy:
10387 * @klass: the MonoClass to act on
10389 * This routine is an iterator routine for retrieving the fields in a class.
10390 * Only minimal information about fields are loaded. Accessors must be used
10391 * for all MonoClassField returned.
10393 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10394 * iterate over all of the elements. When no more values are
10395 * available, the return value is NULL.
10397 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10400 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10402 MonoClassField* field;
10406 mono_class_setup_basic_field_info_locking (klass);
10407 if (!klass->fields)
10409 /* start from the first */
10410 if (klass->field.count) {
10411 return *iter = &klass->fields [0];
10419 if (field < &klass->fields [klass->field.count]) {
10420 return *iter = field;
10426 mono_class_full_name (MonoClass *klass)
10428 return mono_type_full_name (&klass->byval_arg);