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 We use gclass recording to allow recursive system f types to be referenced by a parent.
78 Given the following type hierarchy:
80 class TextBox : TextBoxBase<TextBox> {}
81 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
82 class TextInput<T> : Input<T> where T: TextInput<T> {}
85 The runtime tries to load TextBoxBase<>.
86 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
87 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
88 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
90 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
91 at this point, iow, both are registered in the type map and both and a NULL parent. This means
92 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
94 To fix that what we do is to record all generic instantes created while resolving the parent of
95 any generic type definition and, after resolved, correct the parent field if needed.
98 static int record_gclass_instantiation
;
99 static GSList
*gclass_recorded_list
;
100 typedef gboolean (*gclass_record_func
) (MonoClass
*, void*);
105 mono_locks_acquire (&classes_mutex
, ClassesLock
);
109 classes_unlock (void)
111 mono_locks_release (&classes_mutex
, ClassesLock
);
115 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
118 enable_gclass_recording (void)
120 ++record_gclass_instantiation
;
124 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
127 disable_gclass_recording (gclass_record_func func
, void *user_data
)
129 GSList
**head
= &gclass_recorded_list
;
131 g_assert (record_gclass_instantiation
> 0);
132 --record_gclass_instantiation
;
135 GSList
*node
= *head
;
136 if (func ((MonoClass
*)node
->data
, user_data
)) {
138 g_slist_free_1 (node
);
144 /* We automatically discard all recorded gclasses when disabled. */
145 if (!record_gclass_instantiation
&& gclass_recorded_list
) {
146 g_slist_free (gclass_recorded_list
);
147 gclass_recorded_list
= NULL
;
152 * mono_class_from_typeref:
153 * @image: a MonoImage
154 * @type_token: a TypeRef token
156 * Creates the MonoClass* structure representing the type defined by
157 * the typeref token valid inside @image.
158 * Returns: the MonoClass* representing the typeref token, NULL ifcould
162 mono_class_from_typeref (MonoImage
*image
, guint32 type_token
)
165 MonoClass
*class = mono_class_from_typeref_checked (image
, type_token
, &error
);
166 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
171 mono_class_from_typeref_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
173 guint32 cols
[MONO_TYPEREF_SIZE
];
174 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
176 const char *name
, *nspace
;
177 MonoClass
*res
= NULL
;
180 mono_error_init (error
);
182 if (!mono_verifier_verify_typeref_row (image
, (type_token
& 0xffffff) - 1, error
))
185 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
187 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
188 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
190 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
191 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
192 case MONO_RESOLUTION_SCOPE_MODULE
:
194 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
195 This is not the observed behavior of existing implementations.
196 The defacto behavior is that it's just a typedef in disguise.
198 /* a typedef in disguise */
199 res
= mono_class_from_name (image
, nspace
, name
); /*FIXME proper error handling*/
202 case MONO_RESOLUTION_SCOPE_MODULEREF
:
203 module
= mono_image_load_module (image
, idx
);
205 res
= mono_class_from_name (module
, nspace
, name
); /*FIXME proper error handling*/
208 case MONO_RESOLUTION_SCOPE_TYPEREF
: {
209 MonoClass
*enclosing
;
212 if (idx
== mono_metadata_token_index (type_token
)) {
213 mono_error_set_bad_image (error
, image
, "Image with self-referencing typeref token %08x.", type_token
);
217 enclosing
= mono_class_from_typeref_checked (image
, MONO_TOKEN_TYPE_REF
| idx
, error
);
218 if (!mono_error_ok (error
))
221 if (enclosing
->nested_classes_inited
&& enclosing
->ext
) {
222 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
223 for (tmp
= enclosing
->ext
->nested_classes
; tmp
; tmp
= tmp
->next
) {
225 if (strcmp (res
->name
, name
) == 0)
229 /* Don't call mono_class_init as we might've been called by it recursively */
230 int i
= mono_metadata_nesting_typedef (enclosing
->image
, enclosing
->type_token
, 1);
232 guint32 class_nested
= mono_metadata_decode_row_col (&enclosing
->image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, MONO_NESTED_CLASS_NESTED
);
233 guint32 string_offset
= mono_metadata_decode_row_col (&enclosing
->image
->tables
[MONO_TABLE_TYPEDEF
], class_nested
- 1, MONO_TYPEDEF_NAME
);
234 const char *nname
= mono_metadata_string_heap (enclosing
->image
, string_offset
);
236 if (strcmp (nname
, name
) == 0)
237 return mono_class_create_from_typedef (enclosing
->image
, MONO_TOKEN_TYPE_DEF
| class_nested
, error
);
239 i
= mono_metadata_nesting_typedef (enclosing
->image
, enclosing
->type_token
, i
+ 1);
242 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx
, nspace
, name
, image
->name
);
245 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
249 if (idx
> image
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
) {
250 mono_error_set_bad_image (error
, image
, "Image with invalid assemblyref token %08x.", idx
);
254 if (!image
->references
|| !image
->references
[idx
- 1])
255 mono_assembly_load_reference (image
, idx
- 1);
256 g_assert (image
->references
[idx
- 1]);
258 /* If the assembly did not load, register this as a type load exception */
259 if (image
->references
[idx
- 1] == REFERENCE_MISSING
){
260 MonoAssemblyName aname
;
263 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
264 human_name
= mono_stringify_assembly_name (&aname
);
265 mono_error_set_assembly_load_simple (error
, human_name
, image
->assembly
? image
->assembly
->ref_only
: FALSE
);
269 res
= mono_class_from_name (image
->references
[idx
- 1]->image
, nspace
, name
);
272 /* Generic case, should be avoided for when a better error is possible. */
273 if (!res
&& mono_error_ok (error
)) {
274 char *name
= mono_class_name_from_token (image
, type_token
);
275 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
276 mono_error_set_type_load_name (error
, name
, assembly
, "Could not resolve type with token %08x", type_token
);
283 mono_image_memdup (MonoImage
*image
, void *data
, guint size
)
285 void *res
= mono_image_alloc (image
, size
);
286 memcpy (res
, data
, size
);
290 /* Copy everything mono_metadata_free_array free. */
292 mono_dup_array_type (MonoImage
*image
, MonoArrayType
*a
)
295 a
= mono_image_memdup (image
, a
, sizeof (MonoArrayType
));
297 a
->sizes
= mono_image_memdup (image
, a
->sizes
, a
->numsizes
* sizeof (int));
299 a
->lobounds
= mono_image_memdup (image
, a
->lobounds
, a
->numlobounds
* sizeof (int));
301 a
= g_memdup (a
, sizeof (MonoArrayType
));
303 a
->sizes
= g_memdup (a
->sizes
, a
->numsizes
* sizeof (int));
305 a
->lobounds
= g_memdup (a
->lobounds
, a
->numlobounds
* sizeof (int));
310 /* Copy everything mono_metadata_free_method_signature free. */
312 mono_metadata_signature_deep_dup (MonoImage
*image
, MonoMethodSignature
*sig
)
316 sig
= mono_metadata_signature_dup_full (image
, sig
);
318 sig
->ret
= mono_metadata_type_dup (image
, sig
->ret
);
319 for (i
= 0; i
< sig
->param_count
; ++i
)
320 sig
->params
[i
] = mono_metadata_type_dup (image
, sig
->params
[i
]);
326 _mono_type_get_assembly_name (MonoClass
*klass
, GString
*str
)
328 MonoAssembly
*ta
= klass
->image
->assembly
;
331 name
= mono_stringify_assembly_name (&ta
->aname
);
332 g_string_append_printf (str
, ", %s", name
);
337 mono_type_name_check_byref (MonoType
*type
, GString
*str
)
340 g_string_append_c (str
, '&');
344 mono_type_get_name_recurse (MonoType
*type
, GString
*str
, gboolean is_recursed
,
345 MonoTypeNameFormat format
)
349 switch (type
->type
) {
350 case MONO_TYPE_ARRAY
: {
351 int i
, rank
= type
->data
.array
->rank
;
352 MonoTypeNameFormat nested_format
;
354 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
355 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
357 mono_type_get_name_recurse (
358 &type
->data
.array
->eklass
->byval_arg
, str
, FALSE
, nested_format
);
359 g_string_append_c (str
, '[');
361 g_string_append_c (str
, '*');
362 for (i
= 1; i
< rank
; i
++)
363 g_string_append_c (str
, ',');
364 g_string_append_c (str
, ']');
366 mono_type_name_check_byref (type
, str
);
368 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
369 _mono_type_get_assembly_name (type
->data
.array
->eklass
, str
);
372 case MONO_TYPE_SZARRAY
: {
373 MonoTypeNameFormat nested_format
;
375 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
376 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
378 mono_type_get_name_recurse (
379 &type
->data
.klass
->byval_arg
, str
, FALSE
, nested_format
);
380 g_string_append (str
, "[]");
382 mono_type_name_check_byref (type
, str
);
384 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
385 _mono_type_get_assembly_name (type
->data
.klass
, str
);
388 case MONO_TYPE_PTR
: {
389 MonoTypeNameFormat nested_format
;
391 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
392 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
394 mono_type_get_name_recurse (
395 type
->data
.type
, str
, FALSE
, nested_format
);
396 g_string_append_c (str
, '*');
398 mono_type_name_check_byref (type
, str
);
400 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
401 _mono_type_get_assembly_name (mono_class_from_mono_type (type
->data
.type
), str
);
406 if (!mono_generic_param_info (type
->data
.generic_param
))
407 g_string_append_printf (str
, "%s%d", type
->type
== MONO_TYPE_VAR
? "!" : "!!", type
->data
.generic_param
->num
);
409 g_string_append (str
, mono_generic_param_info (type
->data
.generic_param
)->name
);
411 mono_type_name_check_byref (type
, str
);
415 klass
= mono_class_from_mono_type (type
);
416 if (klass
->nested_in
) {
417 mono_type_get_name_recurse (
418 &klass
->nested_in
->byval_arg
, str
, TRUE
, format
);
419 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
420 g_string_append_c (str
, '.');
422 g_string_append_c (str
, '+');
423 } else if (*klass
->name_space
) {
424 g_string_append (str
, klass
->name_space
);
425 g_string_append_c (str
, '.');
427 if (format
== MONO_TYPE_NAME_FORMAT_IL
) {
428 char *s
= strchr (klass
->name
, '`');
429 int len
= s
? s
- klass
->name
: strlen (klass
->name
);
431 g_string_append_len (str
, klass
->name
, len
);
433 g_string_append (str
, klass
->name
);
436 if (klass
->generic_class
) {
437 MonoGenericClass
*gclass
= klass
->generic_class
;
438 MonoGenericInst
*inst
= gclass
->context
.class_inst
;
439 MonoTypeNameFormat nested_format
;
442 nested_format
= format
== MONO_TYPE_NAME_FORMAT_FULL_NAME
?
443 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
: format
;
445 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
446 g_string_append_c (str
, '<');
448 g_string_append_c (str
, '[');
449 for (i
= 0; i
< inst
->type_argc
; i
++) {
450 MonoType
*t
= inst
->type_argv
[i
];
453 g_string_append_c (str
, ',');
454 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
455 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
456 g_string_append_c (str
, '[');
457 mono_type_get_name_recurse (inst
->type_argv
[i
], str
, FALSE
, nested_format
);
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
, ']');
462 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
463 g_string_append_c (str
, '>');
465 g_string_append_c (str
, ']');
466 } else if (klass
->generic_container
&&
467 (format
!= MONO_TYPE_NAME_FORMAT_FULL_NAME
) &&
468 (format
!= MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)) {
471 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
472 g_string_append_c (str
, '<');
474 g_string_append_c (str
, '[');
475 for (i
= 0; i
< klass
->generic_container
->type_argc
; i
++) {
477 g_string_append_c (str
, ',');
478 g_string_append (str
, mono_generic_container_get_param_info (klass
->generic_container
, i
)->name
);
480 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
481 g_string_append_c (str
, '>');
483 g_string_append_c (str
, ']');
486 mono_type_name_check_byref (type
, str
);
488 if ((format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
489 (type
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
490 _mono_type_get_assembly_name (klass
, str
);
496 * mono_type_get_name_full:
498 * @format: the format for the return string.
501 * Returns: the string representation in a number of formats:
503 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
504 * returned in the formatrequired by System.Reflection, this is the
505 * inverse of mono_reflection_parse_type ().
507 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
508 * be used by the IL assembler.
510 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
512 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
515 mono_type_get_name_full (MonoType
*type
, MonoTypeNameFormat format
)
519 result
= g_string_new ("");
521 mono_type_get_name_recurse (type
, result
, FALSE
, format
);
523 return g_string_free (result
, FALSE
);
527 * mono_type_get_full_name:
530 * Returns: the string representation for type as required by System.Reflection.
531 * The inverse of mono_reflection_parse_type ().
534 mono_type_get_full_name (MonoClass
*class)
536 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION
);
540 * mono_type_get_name:
543 * Returns: the string representation for type as it would be represented in IL code.
546 mono_type_get_name (MonoType
*type
)
548 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_IL
);
552 * mono_type_get_underlying_type:
555 * Returns: the MonoType for the underlying integer type if @type
556 * is an enum and byref is false, otherwise the type itself.
559 mono_type_get_underlying_type (MonoType
*type
)
561 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
&& !type
->byref
)
562 return mono_class_enum_basetype (type
->data
.klass
);
563 if (type
->type
== MONO_TYPE_GENERICINST
&& type
->data
.generic_class
->container_class
->enumtype
&& !type
->byref
)
564 return mono_class_enum_basetype (type
->data
.generic_class
->container_class
);
569 * mono_class_is_open_constructed_type:
572 * Returns TRUE if type represents a generics open constructed type.
573 * IOW, not all type parameters required for the instantiation have
574 * been provided or it's a generic type definition.
576 * An open constructed type means it's a non realizable type. Not to
577 * be mixed up with an abstract type - we can't cast or dispatch to
578 * an open type, for example.
581 mono_class_is_open_constructed_type (MonoType
*t
)
587 case MONO_TYPE_SZARRAY
:
588 return mono_class_is_open_constructed_type (&t
->data
.klass
->byval_arg
);
589 case MONO_TYPE_ARRAY
:
590 return mono_class_is_open_constructed_type (&t
->data
.array
->eklass
->byval_arg
);
592 return mono_class_is_open_constructed_type (t
->data
.type
);
593 case MONO_TYPE_GENERICINST
:
594 return t
->data
.generic_class
->context
.class_inst
->is_open
;
595 case MONO_TYPE_CLASS
:
596 case MONO_TYPE_VALUETYPE
:
597 return t
->data
.klass
->generic_container
!= NULL
;
604 This is a simple function to catch the most common bad instances of generic types.
605 Specially those that might lead to further failures in the runtime.
608 is_valid_generic_argument (MonoType
*type
)
610 switch (type
->type
) {
612 //case MONO_TYPE_TYPEDBYREF:
619 inflate_generic_type (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
621 mono_error_init (error
);
623 switch (type
->type
) {
624 case MONO_TYPE_MVAR
: {
626 int num
= mono_type_get_generic_param_num (type
);
627 MonoGenericInst
*inst
= context
->method_inst
;
628 if (!inst
|| !inst
->type_argv
)
630 if (num
>= inst
->type_argc
) {
631 MonoGenericParamInfo
*info
= mono_generic_param_info (type
->data
.generic_param
);
632 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
633 num
, info
? info
->name
: "", inst
->type_argc
);
637 if (!is_valid_generic_argument (inst
->type_argv
[num
])) {
638 MonoGenericParamInfo
*info
= mono_generic_param_info (type
->data
.generic_param
);
639 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded with type 0x%x",
640 num
, info
? info
->name
: "", inst
->type_argv
[num
]->type
);
644 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
645 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
646 * ->byref and ->attrs from @type are propagated to the returned type.
648 nt
= mono_metadata_type_dup (image
, inst
->type_argv
[num
]);
649 nt
->byref
= type
->byref
;
650 nt
->attrs
= type
->attrs
;
653 case MONO_TYPE_VAR
: {
655 int num
= mono_type_get_generic_param_num (type
);
656 MonoGenericInst
*inst
= context
->class_inst
;
659 if (num
>= inst
->type_argc
) {
660 MonoGenericParamInfo
*info
= mono_generic_param_info (type
->data
.generic_param
);
661 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
662 num
, info
? info
->name
: "", inst
->type_argc
);
665 if (!is_valid_generic_argument (inst
->type_argv
[num
])) {
666 MonoGenericParamInfo
*info
= mono_generic_param_info (type
->data
.generic_param
);
667 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded with type 0x%x",
668 num
, info
? info
->name
: "", inst
->type_argv
[num
]->type
);
671 nt
= mono_metadata_type_dup (image
, inst
->type_argv
[num
]);
672 nt
->byref
= type
->byref
;
673 nt
->attrs
= type
->attrs
;
676 case MONO_TYPE_SZARRAY
: {
677 MonoClass
*eclass
= type
->data
.klass
;
678 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, &eclass
->byval_arg
, context
, error
);
679 if (!inflated
|| !mono_error_ok (error
))
681 nt
= mono_metadata_type_dup (image
, type
);
682 nt
->data
.klass
= mono_class_from_mono_type (inflated
);
683 mono_metadata_free_type (inflated
);
686 case MONO_TYPE_ARRAY
: {
687 MonoClass
*eclass
= type
->data
.array
->eklass
;
688 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, &eclass
->byval_arg
, context
, error
);
689 if (!inflated
|| !mono_error_ok (error
))
691 nt
= mono_metadata_type_dup (image
, type
);
692 nt
->data
.array
->eklass
= mono_class_from_mono_type (inflated
);
693 mono_metadata_free_type (inflated
);
696 case MONO_TYPE_GENERICINST
: {
697 MonoGenericClass
*gclass
= type
->data
.generic_class
;
698 MonoGenericInst
*inst
;
700 if (!gclass
->context
.class_inst
->is_open
)
703 inst
= mono_metadata_inflate_generic_inst (gclass
->context
.class_inst
, context
, error
);
704 if (!mono_error_ok (error
))
706 if (inst
!= gclass
->context
.class_inst
)
707 gclass
= mono_metadata_lookup_generic_class (gclass
->container_class
, inst
, gclass
->is_dynamic
);
709 if (gclass
== type
->data
.generic_class
)
712 nt
= mono_metadata_type_dup (image
, type
);
713 nt
->data
.generic_class
= gclass
;
716 case MONO_TYPE_CLASS
:
717 case MONO_TYPE_VALUETYPE
: {
718 MonoClass
*klass
= type
->data
.klass
;
719 MonoGenericContainer
*container
= klass
->generic_container
;
720 MonoGenericInst
*inst
;
721 MonoGenericClass
*gclass
= NULL
;
727 /* We can't use context->class_inst directly, since it can have more elements */
728 inst
= mono_metadata_inflate_generic_inst (container
->context
.class_inst
, context
, error
);
729 if (!mono_error_ok (error
))
731 if (inst
== container
->context
.class_inst
)
734 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, image_is_dynamic (klass
->image
));
736 nt
= mono_metadata_type_dup (image
, type
);
737 nt
->type
= MONO_TYPE_GENERICINST
;
738 nt
->data
.generic_class
= gclass
;
748 mono_generic_class_get_context (MonoGenericClass
*gclass
)
750 return &gclass
->context
;
754 mono_class_get_context (MonoClass
*class)
756 return class->generic_class
? mono_generic_class_get_context (class->generic_class
) : NULL
;
760 * mono_class_get_generic_container:
762 * Return the generic container of KLASS which should be a generic type definition.
764 MonoGenericContainer
*
765 mono_class_get_generic_container (MonoClass
*klass
)
767 g_assert (klass
->is_generic
);
769 return klass
->generic_container
;
773 * mono_class_get_generic_class:
775 * Return the MonoGenericClass of KLASS, which should be a generic instance.
778 mono_class_get_generic_class (MonoClass
*klass
)
780 g_assert (klass
->is_inflated
);
782 return klass
->generic_class
;
786 * mono_class_inflate_generic_type_with_mempool:
787 * @mempool: a mempool
789 * @context: a generics context
790 * @error: error context
792 * The same as mono_class_inflate_generic_type, but allocates the MonoType
793 * from mempool if it is non-NULL. If it is NULL, the MonoType is
794 * allocated on the heap and is owned by the caller.
795 * The returned type can potentially be the same as TYPE, so it should not be
796 * modified by the caller, and it should be freed using mono_metadata_free_type ().
799 mono_class_inflate_generic_type_with_mempool (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
801 MonoType
*inflated
= NULL
;
802 mono_error_init (error
);
805 inflated
= inflate_generic_type (image
, type
, context
, error
);
806 if (!mono_error_ok (error
))
810 MonoType
*shared
= mono_metadata_get_shared_type (type
);
815 return mono_metadata_type_dup (image
, type
);
819 mono_stats
.inflated_type_count
++;
824 * mono_class_inflate_generic_type:
826 * @context: a generics context
828 * If @type is a generic type and @context is not NULL, instantiate it using the
829 * generics context @context.
831 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
832 * on the heap and is owned by the caller. Returns NULL on error.
834 * @deprecated Please use mono_class_inflate_generic_type_checked instead
837 mono_class_inflate_generic_type (MonoType
*type
, MonoGenericContext
*context
)
841 result
= mono_class_inflate_generic_type_checked (type
, context
, &error
);
843 if (!mono_error_ok (&error
)) {
844 mono_error_cleanup (&error
);
851 * mono_class_inflate_generic_type:
853 * @context: a generics context
854 * @error: error context to use
856 * If @type is a generic type and @context is not NULL, instantiate it using the
857 * generics context @context.
859 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
860 * on the heap and is owned by the caller.
863 mono_class_inflate_generic_type_checked (MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
865 return mono_class_inflate_generic_type_with_mempool (NULL
, type
, context
, error
);
869 * mono_class_inflate_generic_type_no_copy:
871 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
875 mono_class_inflate_generic_type_no_copy (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
877 MonoType
*inflated
= NULL
;
879 mono_error_init (error
);
881 inflated
= inflate_generic_type (image
, type
, context
, error
);
882 if (!mono_error_ok (error
))
889 mono_stats
.inflated_type_count
++;
894 mono_class_inflate_generic_class_checked (MonoClass
*gklass
, MonoGenericContext
*context
, MonoError
*error
)
899 inflated
= mono_class_inflate_generic_type_checked (&gklass
->byval_arg
, context
, error
);
900 if (!mono_error_ok (error
))
903 res
= mono_class_from_mono_type (inflated
);
904 mono_metadata_free_type (inflated
);
909 * mono_class_inflate_generic_class:
911 * Inflate the class GKLASS with CONTEXT.
914 mono_class_inflate_generic_class (MonoClass
*gklass
, MonoGenericContext
*context
)
919 res
= mono_class_inflate_generic_class_checked (gklass
, context
, &error
);
920 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
927 static MonoGenericContext
928 inflate_generic_context (MonoGenericContext
*context
, MonoGenericContext
*inflate_with
, MonoError
*error
)
930 MonoGenericInst
*class_inst
= NULL
;
931 MonoGenericInst
*method_inst
= NULL
;
932 MonoGenericContext res
= { NULL
, NULL
};
934 mono_error_init (error
);
936 if (context
->class_inst
) {
937 class_inst
= mono_metadata_inflate_generic_inst (context
->class_inst
, inflate_with
, error
);
938 if (!mono_error_ok (error
))
942 if (context
->method_inst
) {
943 method_inst
= mono_metadata_inflate_generic_inst (context
->method_inst
, inflate_with
, error
);
944 if (!mono_error_ok (error
))
948 res
.class_inst
= class_inst
;
949 res
.method_inst
= method_inst
;
955 * mono_class_inflate_generic_method:
956 * @method: a generic method
957 * @context: a generics context
959 * Instantiate the generic method @method using the generics context @context.
961 * Returns: the new instantiated method
964 mono_class_inflate_generic_method (MonoMethod
*method
, MonoGenericContext
*context
)
966 return mono_class_inflate_generic_method_full (method
, NULL
, context
);
970 mono_class_inflate_generic_method_checked (MonoMethod
*method
, MonoGenericContext
*context
, MonoError
*error
)
972 return mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
976 * mono_class_inflate_generic_method_full:
978 * Instantiate method @method with the generic context @context.
979 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
980 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
983 mono_class_inflate_generic_method_full (MonoMethod
*method
, MonoClass
*klass_hint
, MonoGenericContext
*context
)
986 MonoMethod
*res
= mono_class_inflate_generic_method_full_checked (method
, klass_hint
, context
, &error
);
987 if (!mono_error_ok (&error
))
988 /*FIXME do proper error handling - on this case, kill this function. */
989 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error
));
995 * mono_class_inflate_generic_method_full_checked:
996 * Same as mono_class_inflate_generic_method_full but return failure using @error.
999 mono_class_inflate_generic_method_full_checked (MonoMethod
*method
, MonoClass
*klass_hint
, MonoGenericContext
*context
, MonoError
*error
)
1002 MonoMethodInflated
*iresult
, *cached
;
1003 MonoMethodSignature
*sig
;
1004 MonoGenericContext tmp_context
;
1005 gboolean is_mb_open
= FALSE
;
1007 mono_error_init (error
);
1009 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1010 while (method
->is_inflated
) {
1011 MonoGenericContext
*method_context
= mono_method_get_context (method
);
1012 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1014 tmp_context
= inflate_generic_context (method_context
, context
, error
);
1015 if (!mono_error_ok (error
))
1017 context
= &tmp_context
;
1019 if (mono_metadata_generic_context_equal (method_context
, context
))
1022 method
= imethod
->declaring
;
1026 * A method only needs to be inflated if the context has argument for which it is
1029 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1030 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1033 if (!((method
->is_generic
&& context
->method_inst
) ||
1034 (method
->klass
->generic_container
&& context
->class_inst
)))
1038 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1039 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1040 * This is opposite to the way non-SRE MethodInfos behave.
1042 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1044 * void Example<T> () {
1048 * In Example, the method token must be encoded as: "void Example<!!0>()"
1050 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1051 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1053 * On the other hand, inflating a non-SRE generic method with its own arguments should
1054 * return itself. For example:
1056 * MethodInfo m = ... //m is a generic method definition
1057 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1060 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1061 * what happens with regular methods.
1063 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1064 * everything should behave like a regular type or method.
1067 is_mb_open
= method
->is_generic
&&
1068 image_is_dynamic (method
->klass
->image
) && !method
->klass
->wastypebuilder
&& /* that is a MethodBuilder from an unfinished TypeBuilder */
1069 context
->method_inst
== mono_method_get_generic_container (method
)->context
.method_inst
; /* and it's been instantiated with its own arguments. */
1071 iresult
= g_new0 (MonoMethodInflated
, 1);
1072 iresult
->context
= *context
;
1073 iresult
->declaring
= method
;
1074 iresult
->method
.method
.is_mb_open
= is_mb_open
;
1076 if (!context
->method_inst
&& method
->is_generic
)
1077 iresult
->context
.method_inst
= mono_method_get_generic_container (method
)->context
.method_inst
;
1079 if (!context
->class_inst
) {
1080 g_assert (!iresult
->declaring
->klass
->generic_class
);
1081 if (iresult
->declaring
->klass
->generic_container
)
1082 iresult
->context
.class_inst
= iresult
->declaring
->klass
->generic_container
->context
.class_inst
;
1083 else if (iresult
->declaring
->klass
->generic_class
)
1084 iresult
->context
.class_inst
= iresult
->declaring
->klass
->generic_class
->context
.class_inst
;
1087 cached
= mono_method_inflated_lookup (iresult
, FALSE
);
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 return (MonoMethod
*)mono_method_inflated_lookup (iresult
, TRUE
);
1167 * mono_get_inflated_method:
1169 * Obsolete. We keep it around since it's mentioned in the public API.
1172 mono_get_inflated_method (MonoMethod
*method
)
1178 * mono_method_get_context_general:
1180 * @uninflated: handle uninflated methods?
1182 * Returns the generic context of a method or NULL if it doesn't have
1183 * one. For an inflated method that's the context stored in the
1184 * method. Otherwise it's in the method's generic container or in the
1185 * generic container of the method's class.
1188 mono_method_get_context_general (MonoMethod
*method
, gboolean uninflated
)
1190 if (method
->is_inflated
) {
1191 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1192 return &imethod
->context
;
1196 if (method
->is_generic
)
1197 return &(mono_method_get_generic_container (method
)->context
);
1198 if (method
->klass
->generic_container
)
1199 return &method
->klass
->generic_container
->context
;
1204 * mono_method_get_context:
1207 * Returns the generic context for method if it's inflated, otherwise
1211 mono_method_get_context (MonoMethod
*method
)
1213 return mono_method_get_context_general (method
, FALSE
);
1217 * mono_method_get_generic_container:
1219 * Returns the generic container of METHOD, which should be a generic method definition.
1220 * Returns NULL if METHOD is not a generic method definition.
1221 * LOCKING: Acquires the loader lock.
1223 MonoGenericContainer
*
1224 mono_method_get_generic_container (MonoMethod
*method
)
1226 MonoGenericContainer
*container
;
1228 if (!method
->is_generic
)
1231 container
= mono_image_property_lookup (method
->klass
->image
, method
, MONO_METHOD_PROP_GENERIC_CONTAINER
);
1232 g_assert (container
);
1238 * mono_method_set_generic_container:
1240 * Sets the generic container of METHOD to CONTAINER.
1241 * LOCKING: Acquires the image lock.
1244 mono_method_set_generic_container (MonoMethod
*method
, MonoGenericContainer
* container
)
1246 g_assert (method
->is_generic
);
1248 mono_image_property_insert (method
->klass
->image
, method
, MONO_METHOD_PROP_GENERIC_CONTAINER
, container
);
1252 * mono_class_find_enum_basetype:
1253 * @class: The enum class
1255 * Determine the basetype of an enum by iterating through its fields. We do this
1256 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1259 mono_class_find_enum_basetype (MonoClass
*class, MonoError
*error
)
1261 MonoGenericContainer
*container
= NULL
;
1262 MonoImage
*m
= class->image
;
1263 const int top
= class->field
.count
;
1266 g_assert (class->enumtype
);
1268 mono_error_init (error
);
1270 if (class->generic_container
)
1271 container
= class->generic_container
;
1272 else if (class->generic_class
) {
1273 MonoClass
*gklass
= class->generic_class
->container_class
;
1275 container
= gklass
->generic_container
;
1276 g_assert (container
);
1280 * Fetch all the field information.
1282 for (i
= 0; i
< top
; i
++){
1284 guint32 cols
[MONO_FIELD_SIZE
];
1285 int idx
= class->field
.first
+ i
;
1288 /* class->field.first and idx points into the fieldptr table */
1289 mono_metadata_decode_table_row (m
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
1291 if (cols
[MONO_FIELD_FLAGS
] & FIELD_ATTRIBUTE_STATIC
) //no need to decode static fields
1294 if (!mono_verifier_verify_field_signature (class->image
, cols
[MONO_FIELD_SIGNATURE
], NULL
)) {
1295 mono_error_set_bad_image (error
, class->image
, "Invalid field signature %x", cols
[MONO_FIELD_SIGNATURE
]);
1299 sig
= mono_metadata_blob_heap (m
, cols
[MONO_FIELD_SIGNATURE
]);
1300 mono_metadata_decode_value (sig
, &sig
);
1301 /* FIELD signature == 0x06 */
1303 mono_error_set_bad_image (error
, class->image
, "Invalid field signature %x, expected 0x6 but got %x", cols
[MONO_FIELD_SIGNATURE
], *sig
);
1307 ftype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_FIELD
, cols
[MONO_FIELD_FLAGS
], sig
+ 1, &sig
);
1309 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1310 mono_error_set_from_loader_error (error
);
1312 mono_error_set_bad_image (error
, class->image
, "Could not parse type for field signature %x", cols
[MONO_FIELD_SIGNATURE
]);
1315 if (class->generic_class
) {
1316 //FIXME do we leak here?
1317 ftype
= mono_class_inflate_generic_type_checked (ftype
, mono_class_get_context (class), error
);
1318 if (!mono_error_ok (error
))
1320 ftype
->attrs
= cols
[MONO_FIELD_FLAGS
];
1325 mono_error_set_type_load_class (error
, class, "Could not find base type");
1328 g_assert (!mono_loader_get_last_error ());
1333 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1336 mono_type_has_exceptions (MonoType
*type
)
1338 switch (type
->type
) {
1339 case MONO_TYPE_CLASS
:
1340 case MONO_TYPE_VALUETYPE
:
1341 case MONO_TYPE_SZARRAY
:
1342 return type
->data
.klass
->exception_type
;
1343 case MONO_TYPE_ARRAY
:
1344 return type
->data
.array
->eklass
->exception_type
;
1345 case MONO_TYPE_GENERICINST
:
1346 return mono_generic_class_get_class (type
->data
.generic_class
)->exception_type
;
1354 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1358 mono_class_alloc (MonoClass
*class, int size
)
1360 if (class->generic_class
)
1361 return mono_image_set_alloc (class->generic_class
->owner
, size
);
1363 return mono_image_alloc (class->image
, size
);
1367 mono_class_alloc0 (MonoClass
*class, int size
)
1371 res
= mono_class_alloc (class, size
);
1372 memset (res
, 0, size
);
1376 #define mono_class_new0(class,struct_type, n_structs) \
1377 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1380 * mono_class_setup_basic_field_info:
1381 * @class: The class to initialize
1383 * Initializes the class->fields.
1384 * LOCKING: Assumes the loader lock is held.
1387 mono_class_setup_basic_field_info (MonoClass
*class)
1389 MonoClassField
*field
;
1397 gtd
= class->generic_class
? mono_class_get_generic_type_definition (class) : NULL
;
1398 image
= class->image
;
1399 top
= class->field
.count
;
1401 if (class->generic_class
&& image_is_dynamic (class->generic_class
->container_class
->image
) && !class->generic_class
->container_class
->wastypebuilder
) {
1403 * This happens when a generic instance of an unfinished generic typebuilder
1404 * is used as an element type for creating an array type. We can't initialize
1405 * the fields of this class using the fields of gklass, since gklass is not
1406 * finished yet, fields could be added to it later.
1412 mono_class_setup_basic_field_info (gtd
);
1414 top
= gtd
->field
.count
;
1415 class->field
.first
= gtd
->field
.first
;
1416 class->field
.count
= gtd
->field
.count
;
1419 class->fields
= mono_class_alloc0 (class, sizeof (MonoClassField
) * top
);
1422 * Fetch all the field information.
1424 for (i
= 0; i
< top
; i
++){
1425 field
= &class->fields
[i
];
1426 field
->parent
= class;
1429 field
->name
= mono_field_get_name (>d
->fields
[i
]);
1431 int idx
= class->field
.first
+ i
;
1432 /* class->field.first and idx points into the fieldptr table */
1433 guint32 name_idx
= mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_NAME
);
1434 /* The name is needed for fieldrefs */
1435 field
->name
= mono_metadata_string_heap (image
, name_idx
);
1441 * mono_class_setup_fields:
1442 * @class: The class to initialize
1444 * Initializes the class->fields.
1445 * LOCKING: Assumes the loader lock is held.
1448 mono_class_setup_fields (MonoClass
*class)
1451 MonoImage
*m
= class->image
;
1453 guint32 layout
= class->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
;
1454 int i
, blittable
= TRUE
;
1455 guint32 real_size
= 0;
1456 guint32 packing_size
= 0;
1457 gboolean explicit_size
;
1458 MonoClassField
*field
;
1459 MonoGenericContainer
*container
= NULL
;
1460 MonoClass
*gtd
= class->generic_class
? mono_class_get_generic_type_definition (class) : NULL
;
1463 * FIXME: We have a race condition here. It's possible that this function returns
1464 * to its caller with `instance_size` set to `0` instead of the actual size. This
1465 * is not a problem when the function is called recursively on the same class,
1466 * because the size will be initialized by the outer invocation. What follows is a
1467 * description of how it can occur in other cases, too. There it is a problem,
1468 * because it can lead to the GC being asked to allocate an object of size `0`,
1469 * which SGen chokes on. The race condition is triggered infrequently by
1470 * `tests/sgen-suspend.cs`.
1472 * This function is called for a class whenever one of its subclasses is inited.
1473 * For example, it's called for every subclass of Object. What it does is this:
1475 * if (class->setup_fields_called)
1478 * class->instance_size = 0;
1480 * class->setup_fields_called = 1;
1481 * ... critical point
1482 * class->instance_size = actual_instance_size;
1484 * The last two steps are sometimes reversed, but that only changes the way in which
1485 * the race condition works.
1487 * Assume thread A goes through this function and makes it to the critical point.
1488 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1489 * immediately, but `instance_size` is incorrect.
1491 * The other case looks like this:
1493 * if (class->setup_fields_called)
1495 * ... critical point X
1496 * class->instance_size = 0;
1497 * ... critical point Y
1498 * class->instance_size = actual_instance_size;
1500 * class->setup_fields_called = 1;
1502 * Assume thread A goes through the function and makes it to critical point X. Now
1503 * thread B runs through the whole of the function, returning, assuming
1504 * `instance_size` is set. At that point thread A gets to run and makes it to
1505 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1508 if (class->setup_fields_called
)
1511 if (class->generic_class
&& image_is_dynamic (class->generic_class
->container_class
->image
) && !class->generic_class
->container_class
->wastypebuilder
) {
1513 * This happens when a generic instance of an unfinished generic typebuilder
1514 * is used as an element type for creating an array type. We can't initialize
1515 * the fields of this class using the fields of gklass, since gklass is not
1516 * finished yet, fields could be added to it later.
1521 mono_class_setup_basic_field_info (class);
1522 top
= class->field
.count
;
1525 mono_class_setup_fields (gtd
);
1526 if (gtd
->exception_type
) {
1527 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1532 class->instance_size
= 0;
1534 class->sizes
.class_size
= 0;
1536 if (class->parent
) {
1537 /* For generic instances, class->parent might not have been initialized */
1538 mono_class_init (class->parent
);
1539 if (!class->parent
->size_inited
) {
1540 mono_class_setup_fields (class->parent
);
1541 if (class->parent
->exception_type
) {
1542 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1546 class->instance_size
+= class->parent
->instance_size
;
1547 class->min_align
= class->parent
->min_align
;
1548 /* we use |= since it may have been set already */
1549 class->has_references
|= class->parent
->has_references
;
1550 blittable
= class->parent
->blittable
;
1552 class->instance_size
= sizeof (MonoObject
);
1553 class->min_align
= 1;
1556 /* We can't really enable 16 bytes alignment until the GC supports it.
1557 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1558 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1559 Bug #506144 is an example of this issue.
1561 if (class->simd_type)
1562 class->min_align = 16;
1564 /* Get the real size */
1565 explicit_size
= mono_metadata_packing_from_typedef (class->image
, class->type_token
, &packing_size
, &real_size
);
1567 if (explicit_size
) {
1568 if ((packing_size
& 0xffffff00) != 0) {
1569 char *err_msg
= g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name
, packing_size
);
1570 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
1573 class->packing_size
= packing_size
;
1574 real_size
+= class->instance_size
;
1578 if (explicit_size
&& real_size
) {
1579 class->instance_size
= MAX (real_size
, class->instance_size
);
1581 class->blittable
= blittable
;
1582 mono_memory_barrier ();
1583 class->size_inited
= 1;
1584 class->fields_inited
= 1;
1585 class->setup_fields_called
= 1;
1589 if (layout
== TYPE_ATTRIBUTE_AUTO_LAYOUT
)
1592 /* Prevent infinite loops if the class references itself */
1593 class->setup_fields_called
= 1;
1595 if (class->generic_container
) {
1596 container
= class->generic_container
;
1598 container
= gtd
->generic_container
;
1599 g_assert (container
);
1603 * Fetch all the field information.
1605 for (i
= 0; i
< top
; i
++){
1606 int idx
= class->field
.first
+ i
;
1607 field
= &class->fields
[i
];
1609 field
->parent
= class;
1612 mono_field_resolve_type (field
, &error
);
1613 if (!mono_error_ok (&error
)) {
1614 /*mono_field_resolve_type already failed class*/
1615 mono_error_cleanup (&error
);
1619 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field
->name
);
1620 g_assert (field
->type
);
1623 if (mono_field_is_deleted (field
))
1626 MonoClassField
*gfield
= >d
->fields
[i
];
1627 field
->offset
= gfield
->offset
;
1629 if (layout
== TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) {
1631 mono_metadata_field_info (m
, idx
, &offset
, NULL
, NULL
);
1632 field
->offset
= offset
;
1634 if (field
->offset
== (guint32
)-1 && !(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1635 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Missing field layout info for %s", field
->name
));
1638 if (field
->offset
< -1) { /*-1 is used to encode special static fields */
1639 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Invalid negative field offset %d for %s", field
->offset
, field
->name
));
1642 if (class->generic_container
) {
1643 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Generic class cannot have explicit layout."));
1649 /* Only do these checks if we still think this type is blittable */
1650 if (blittable
&& !(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1651 if (field
->type
->byref
|| MONO_TYPE_IS_REFERENCE (field
->type
)) {
1654 MonoClass
*field_class
= mono_class_from_mono_type (field
->type
);
1656 mono_class_setup_fields (field_class
);
1657 if (field_class
->exception_type
) {
1658 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1662 if (!field_class
|| !field_class
->blittable
)
1667 if (class->enumtype
&& !(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1668 class->cast_class
= class->element_class
= mono_class_from_mono_type (field
->type
);
1669 blittable
= class->element_class
->blittable
;
1672 if (mono_type_has_exceptions (field
->type
)) {
1673 char *class_name
= mono_type_get_full_name (class);
1674 char *type_name
= mono_type_full_name (field
->type
);
1676 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1677 g_warning ("Invalid type %s for instance field %s:%s", type_name
, class_name
, field
->name
);
1678 g_free (class_name
);
1682 /* The def_value of fields is compute lazily during vtable creation */
1685 if (class == mono_defaults
.string_class
)
1688 class->blittable
= blittable
;
1690 if (class->enumtype
&& !mono_class_enum_basetype (class)) {
1691 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1694 if (explicit_size
&& real_size
) {
1695 class->instance_size
= MAX (real_size
, class->instance_size
);
1698 if (class->exception_type
)
1700 mono_class_layout_fields (class);
1702 /*valuetypes can't be neither bigger than 1Mb or empty. */
1703 if (class->valuetype
&& (class->instance_size
<= 0 || class->instance_size
> (0x100000 + sizeof (MonoObject
))))
1704 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1706 mono_memory_barrier ();
1707 class->fields_inited
= 1;
1711 * mono_class_setup_fields_locking:
1712 * @class: The class to initialize
1714 * Initializes the class->fields array of fields.
1715 * Aquires the loader lock.
1718 mono_class_setup_fields_locking (MonoClass
*class)
1720 /* This can be checked without locks */
1721 if (class->fields_inited
)
1723 mono_loader_lock ();
1724 mono_class_setup_fields (class);
1725 mono_loader_unlock ();
1729 * mono_class_has_references:
1731 * Returns whenever @klass->has_references is set, initializing it if needed.
1732 * Aquires the loader lock.
1735 mono_class_has_references (MonoClass
*klass
)
1737 if (klass
->init_pending
) {
1738 /* Be conservative */
1741 mono_class_init (klass
);
1743 return klass
->has_references
;
1748 * mono_type_get_basic_type_from_generic:
1751 * Returns a closed type corresponding to the possibly open type
1755 mono_type_get_basic_type_from_generic (MonoType
*type
)
1757 /* When we do generic sharing we let type variables stand for reference types. */
1758 if (!type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
))
1759 return &mono_defaults
.object_class
->byval_arg
;
1764 * mono_class_layout_fields:
1767 * Compute the placement of fields inside an object or struct, according to
1768 * the layout rules and set the following fields in @class:
1769 * - has_references (if the class contains instance references firled or structs that contain references)
1770 * - has_static_refs (same, but for static fields)
1771 * - instance_size (size of the object in memory)
1772 * - class_size (size needed for the static fields)
1773 * - size_inited (flag set when the instance_size is set)
1775 * LOCKING: this is supposed to be called with the loader lock held.
1778 mono_class_layout_fields (MonoClass
*class)
1781 const int top
= class->field
.count
;
1782 guint32 layout
= class->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
;
1783 guint32 pass
, passes
, real_size
;
1784 gboolean gc_aware_layout
= FALSE
;
1785 gboolean has_static_fields
= FALSE
;
1786 MonoClassField
*field
;
1789 * When we do generic sharing we need to have layout
1790 * information for open generic classes (either with a generic
1791 * context containing type variables or with a generic
1792 * container), so we don't return in that case anymore.
1796 * Enable GC aware auto layout: in this mode, reference
1797 * fields are grouped together inside objects, increasing collector
1799 * Requires that all classes whose layout is known to native code be annotated
1800 * with [StructLayout (LayoutKind.Sequential)]
1801 * Value types have gc_aware_layout disabled by default, as per
1802 * what the default is for other runtimes.
1804 /* corlib is missing [StructLayout] directives in many places */
1805 if (layout
== TYPE_ATTRIBUTE_AUTO_LAYOUT
) {
1806 if (!class->valuetype
)
1807 gc_aware_layout
= TRUE
;
1810 /* Compute klass->has_references */
1812 * Process non-static fields first, since static fields might recursively
1813 * refer to the class itself.
1815 for (i
= 0; i
< top
; i
++) {
1818 field
= &class->fields
[i
];
1820 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1821 ftype
= mono_type_get_underlying_type (field
->type
);
1822 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1823 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
)))))
1824 class->has_references
= TRUE
;
1828 for (i
= 0; i
< top
; i
++) {
1831 field
= &class->fields
[i
];
1833 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
1834 ftype
= mono_type_get_underlying_type (field
->type
);
1835 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1836 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
)))))
1837 class->has_static_refs
= TRUE
;
1841 for (i
= 0; i
< top
; i
++) {
1844 field
= &class->fields
[i
];
1846 ftype
= mono_type_get_underlying_type (field
->type
);
1847 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1848 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
))))) {
1849 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1850 class->has_static_refs
= TRUE
;
1852 class->has_references
= TRUE
;
1857 * Compute field layout and total size (not considering static fields)
1861 case TYPE_ATTRIBUTE_AUTO_LAYOUT
:
1862 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT
:
1864 if (gc_aware_layout
)
1869 if (layout
!= TYPE_ATTRIBUTE_AUTO_LAYOUT
)
1872 if (class->parent
) {
1873 mono_class_setup_fields (class->parent
);
1874 if (class->parent
->exception_type
) {
1875 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1878 real_size
= class->parent
->instance_size
;
1880 real_size
= sizeof (MonoObject
);
1883 for (pass
= 0; pass
< passes
; ++pass
) {
1884 for (i
= 0; i
< top
; i
++){
1889 field
= &class->fields
[i
];
1891 if (mono_field_is_deleted (field
))
1893 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1896 ftype
= mono_type_get_underlying_type (field
->type
);
1897 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1898 if (gc_aware_layout
) {
1899 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
))))) {
1908 if ((top
== 1) && (class->instance_size
== sizeof (MonoObject
)) &&
1909 (strcmp (mono_field_get_name (field
), "$PRIVATE$") == 0)) {
1910 /* This field is a hack inserted by MCS to empty structures */
1914 size
= mono_type_size (field
->type
, &align
);
1916 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1917 align
= class->packing_size
? MIN (class->packing_size
, align
): align
;
1918 /* if the field has managed references, we need to force-align it
1921 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
)))))
1922 align
= MAX (align
, sizeof (gpointer
));
1924 class->min_align
= MAX (align
, class->min_align
);
1925 field
->offset
= real_size
;
1927 field
->offset
+= align
- 1;
1928 field
->offset
&= ~(align
- 1);
1930 /*TypeBuilders produce all sort of weird things*/
1931 g_assert (image_is_dynamic (class->image
) || field
->offset
> 0);
1932 real_size
= field
->offset
+ size
;
1935 class->instance_size
= MAX (real_size
, class->instance_size
);
1937 if (class->instance_size
& (class->min_align
- 1)) {
1938 class->instance_size
+= class->min_align
- 1;
1939 class->instance_size
&= ~(class->min_align
- 1);
1943 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
: {
1947 for (i
= 0; i
< top
; i
++) {
1952 field
= &class->fields
[i
];
1955 * There must be info about all the fields in a type if it
1956 * uses explicit layout.
1958 if (mono_field_is_deleted (field
))
1960 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1963 size
= mono_type_size (field
->type
, &align
);
1964 align
= class->packing_size
? MIN (class->packing_size
, align
): align
;
1965 class->min_align
= MAX (align
, class->min_align
);
1968 * When we get here, field->offset is already set by the
1969 * loader (for either runtime fields or fields loaded from metadata).
1970 * The offset is from the start of the object: this works for both
1971 * classes and valuetypes.
1973 field
->offset
+= sizeof (MonoObject
);
1974 ftype
= mono_type_get_underlying_type (field
->type
);
1975 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1976 if (MONO_TYPE_IS_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
))))) {
1977 if (field
->offset
% sizeof (gpointer
)) {
1978 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1985 real_size
= MAX (real_size
, size
+ field
->offset
);
1988 if (class->has_references
) {
1989 ref_bitmap
= g_new0 (guint8
, real_size
/ sizeof (gpointer
));
1991 /* Check for overlapping reference and non-reference fields */
1992 for (i
= 0; i
< top
; i
++) {
1995 field
= &class->fields
[i
];
1997 if (mono_field_is_deleted (field
))
1999 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
2001 ftype
= mono_type_get_underlying_type (field
->type
);
2002 if (MONO_TYPE_IS_REFERENCE (ftype
))
2003 ref_bitmap
[field
->offset
/ sizeof (gpointer
)] = 1;
2005 for (i
= 0; i
< top
; i
++) {
2006 field
= &class->fields
[i
];
2008 if (mono_field_is_deleted (field
))
2010 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
2013 // FIXME: Too much code does this
2015 if (!MONO_TYPE_IS_REFERENCE (field
->type
) && ref_bitmap
[field
->offset
/ sizeof (gpointer
)]) {
2016 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
);
2017 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;
2157 gboolean jagged_ctor
= FALSE
;
2159 count
= 3 + (class->rank
> 1? 2: 1);
2161 mono_class_setup_interfaces (class, &error
);
2162 g_assert (mono_error_ok (&error
)); /*FIXME can this fail for array types?*/
2164 if (class->rank
== 1 && class->element_class
->rank
) {
2166 class->method
.count
++;
2169 if (class->interface_count
) {
2170 count_generic
= generic_array_methods (class);
2171 first_generic
= count
;
2172 count
+= class->interface_count
* count_generic
;
2175 methods
= mono_class_alloc0 (class, sizeof (MonoMethod
*) * count
);
2177 sig
= mono_metadata_signature_alloc (class->image
, class->rank
);
2178 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
2179 sig
->pinvoke
= TRUE
;
2180 sig
->hasthis
= TRUE
;
2181 for (i
= 0; i
< class->rank
; ++i
)
2182 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2184 amethod
= create_array_method (class, ".ctor", sig
);
2185 methods
[method_num
++] = amethod
;
2186 if (class->rank
> 1) {
2187 sig
= mono_metadata_signature_alloc (class->image
, class->rank
* 2);
2188 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
2189 sig
->pinvoke
= TRUE
;
2190 sig
->hasthis
= TRUE
;
2191 for (i
= 0; i
< class->rank
* 2; ++i
)
2192 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2194 amethod
= create_array_method (class, ".ctor", sig
);
2195 methods
[method_num
++] = amethod
;
2199 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2200 sig
= mono_metadata_signature_alloc (class->image
, class->rank
+ 1);
2201 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
2202 sig
->pinvoke
= TRUE
;
2203 sig
->hasthis
= TRUE
;
2204 for (i
= 0; i
< class->rank
+ 1; ++i
)
2205 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2206 amethod
= create_array_method (class, ".ctor", sig
);
2207 methods
[method_num
++] = amethod
;
2210 /* element Get (idx11, [idx2, ...]) */
2211 sig
= mono_metadata_signature_alloc (class->image
, class->rank
);
2212 sig
->ret
= &class->element_class
->byval_arg
;
2213 sig
->pinvoke
= TRUE
;
2214 sig
->hasthis
= TRUE
;
2215 for (i
= 0; i
< class->rank
; ++i
)
2216 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2217 amethod
= create_array_method (class, "Get", sig
);
2218 methods
[method_num
++] = amethod
;
2219 /* element& Address (idx11, [idx2, ...]) */
2220 sig
= mono_metadata_signature_alloc (class->image
, class->rank
);
2221 sig
->ret
= &class->element_class
->this_arg
;
2222 sig
->pinvoke
= TRUE
;
2223 sig
->hasthis
= TRUE
;
2224 for (i
= 0; i
< class->rank
; ++i
)
2225 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2226 amethod
= create_array_method (class, "Address", sig
);
2227 methods
[method_num
++] = amethod
;
2228 /* void Set (idx11, [idx2, ...], element) */
2229 sig
= mono_metadata_signature_alloc (class->image
, class->rank
+ 1);
2230 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
2231 sig
->pinvoke
= TRUE
;
2232 sig
->hasthis
= TRUE
;
2233 for (i
= 0; i
< class->rank
; ++i
)
2234 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2235 sig
->params
[i
] = &class->element_class
->byval_arg
;
2236 amethod
= create_array_method (class, "Set", sig
);
2237 methods
[method_num
++] = amethod
;
2239 for (i
= 0; i
< class->interface_count
; i
++)
2240 setup_generic_array_ifaces (class, class->interfaces
[i
], methods
, first_generic
+ i
* count_generic
);
2244 count
= class->method
.count
;
2245 methods
= mono_class_alloc (class, sizeof (MonoMethod
*) * count
);
2246 for (i
= 0; i
< count
; ++i
) {
2247 int idx
= mono_metadata_translate_token_index (class->image
, MONO_TABLE_METHOD
, class->method
.first
+ i
+ 1);
2248 methods
[i
] = mono_get_method_checked (class->image
, MONO_TOKEN_METHOD_DEF
| idx
, class, NULL
, &error
);
2250 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Could not load method %d due to %s", i
, mono_error_get_message (&error
)));
2251 mono_error_cleanup (&error
);
2256 if (MONO_CLASS_IS_INTERFACE (class)) {
2258 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2259 for (i
= 0; i
< count
; ++i
) {
2260 if (methods
[i
]->flags
& METHOD_ATTRIBUTE_VIRTUAL
)
2261 methods
[i
]->slot
= slot
++;
2265 mono_image_lock (class->image
);
2267 if (!class->methods
) {
2268 class->method
.count
= count
;
2270 /* Needed because of the double-checking locking pattern */
2271 mono_memory_barrier ();
2273 class->methods
= methods
;
2276 mono_image_unlock (class->image
);
2280 * mono_class_get_method_by_index:
2282 * Returns class->methods [index], initializing class->methods if neccesary.
2284 * LOCKING: Acquires the loader lock.
2287 mono_class_get_method_by_index (MonoClass
*class, int index
)
2290 /* Avoid calling setup_methods () if possible */
2291 if (class->generic_class
&& !class->methods
) {
2292 MonoClass
*gklass
= class->generic_class
->container_class
;
2295 m
= mono_class_inflate_generic_method_full_checked (
2296 gklass
->methods
[index
], class, mono_class_get_context (class), &error
);
2297 g_assert (mono_error_ok (&error
)); /* FIXME don't swallow the error */
2299 * If setup_methods () is called later for this class, no duplicates are created,
2300 * since inflate_generic_method guarantees that only one instance of a method
2301 * is created for each context.
2304 mono_class_setup_methods (class);
2305 g_assert (m == class->methods [index]);
2309 mono_class_setup_methods (class);
2310 if (class->exception_type
) /*FIXME do proper error handling*/
2312 g_assert (index
>= 0 && index
< class->method
.count
);
2313 return class->methods
[index
];
2318 * mono_class_get_inflated_method:
2320 * Given an inflated class CLASS and a method METHOD which should be a method of
2321 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2324 mono_class_get_inflated_method (MonoClass
*class, MonoMethod
*method
)
2326 MonoClass
*gklass
= class->generic_class
->container_class
;
2329 g_assert (method
->klass
== gklass
);
2331 mono_class_setup_methods (gklass
);
2332 g_assert (!gklass
->exception_type
); /*FIXME do proper error handling*/
2334 for (i
= 0; i
< gklass
->method
.count
; ++i
) {
2335 if (gklass
->methods
[i
] == method
) {
2336 if (class->methods
) {
2337 return class->methods
[i
];
2340 MonoMethod
*result
= mono_class_inflate_generic_method_full_checked (gklass
->methods
[i
], class, mono_class_get_context (class), &error
);
2341 g_assert (mono_error_ok (&error
)); /* FIXME don't swallow this error */
2351 * mono_class_get_vtable_entry:
2353 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2354 * LOCKING: Acquires the loader lock.
2357 mono_class_get_vtable_entry (MonoClass
*class, int offset
)
2361 if (class->rank
== 1) {
2363 * szarrays do not overwrite any methods of Array, so we can avoid
2364 * initializing their vtables in some cases.
2366 mono_class_setup_vtable (class->parent
);
2367 if (offset
< class->parent
->vtable_size
)
2368 return class->parent
->vtable
[offset
];
2371 if (class->generic_class
) {
2373 MonoClass
*gklass
= class->generic_class
->container_class
;
2374 mono_class_setup_vtable (gklass
);
2375 m
= gklass
->vtable
[offset
];
2377 m
= mono_class_inflate_generic_method_full_checked (m
, class, mono_class_get_context (class), &error
);
2378 g_assert (mono_error_ok (&error
)); /* FIXME don't swallow this error */
2380 mono_class_setup_vtable (class);
2381 if (class->exception_type
)
2383 m
= class->vtable
[offset
];
2390 * mono_class_get_vtable_size:
2392 * Return the vtable size for KLASS.
2395 mono_class_get_vtable_size (MonoClass
*klass
)
2397 mono_class_setup_vtable (klass
);
2399 return klass
->vtable_size
;
2403 * mono_class_setup_properties:
2405 * Initialize class->ext.property and class->ext.properties.
2407 * This method can fail the class.
2410 mono_class_setup_properties (MonoClass
*class)
2412 guint startm
, endm
, i
, j
;
2413 guint32 cols
[MONO_PROPERTY_SIZE
];
2414 MonoTableInfo
*msemt
= &class->image
->tables
[MONO_TABLE_METHODSEMANTICS
];
2415 MonoProperty
*properties
;
2419 if (class->ext
&& class->ext
->properties
)
2422 if (class->generic_class
) {
2423 MonoClass
*gklass
= class->generic_class
->container_class
;
2425 mono_class_init (gklass
);
2426 mono_class_setup_properties (gklass
);
2427 if (gklass
->exception_type
) {
2428 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Generic type definition failed to load"));
2432 properties
= mono_class_new0 (class, MonoProperty
, gklass
->ext
->property
.count
+ 1);
2434 for (i
= 0; i
< gklass
->ext
->property
.count
; i
++) {
2436 MonoProperty
*prop
= &properties
[i
];
2438 *prop
= gklass
->ext
->properties
[i
];
2441 prop
->get
= mono_class_inflate_generic_method_full_checked (
2442 prop
->get
, class, mono_class_get_context (class), &error
);
2444 prop
->set
= mono_class_inflate_generic_method_full_checked (
2445 prop
->set
, class, mono_class_get_context (class), &error
);
2447 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
2448 prop
->parent
= class;
2451 first
= gklass
->ext
->property
.first
;
2452 count
= gklass
->ext
->property
.count
;
2454 first
= mono_metadata_properties_from_typedef (class->image
, mono_metadata_token_index (class->type_token
) - 1, &last
);
2455 count
= last
- first
;
2458 mono_class_setup_methods (class);
2459 if (class->exception_type
)
2463 properties
= mono_class_alloc0 (class, sizeof (MonoProperty
) * count
);
2464 for (i
= first
; i
< last
; ++i
) {
2465 mono_metadata_decode_table_row (class->image
, MONO_TABLE_PROPERTY
, i
, cols
, MONO_PROPERTY_SIZE
);
2466 properties
[i
- first
].parent
= class;
2467 properties
[i
- first
].attrs
= cols
[MONO_PROPERTY_FLAGS
];
2468 properties
[i
- first
].name
= mono_metadata_string_heap (class->image
, cols
[MONO_PROPERTY_NAME
]);
2470 startm
= mono_metadata_methods_from_property (class->image
, i
, &endm
);
2471 for (j
= startm
; j
< endm
; ++j
) {
2474 mono_metadata_decode_row (msemt
, j
, cols
, MONO_METHOD_SEMA_SIZE
);
2476 if (class->image
->uncompressed_metadata
) {
2478 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2479 method
= mono_get_method_checked (class->image
, MONO_TOKEN_METHOD_DEF
| cols
[MONO_METHOD_SEMA_METHOD
], class, NULL
, &error
);
2480 mono_error_cleanup (&error
); /* FIXME don't swallow this error */
2482 method
= class->methods
[cols
[MONO_METHOD_SEMA_METHOD
] - 1 - class->method
.first
];
2485 switch (cols
[MONO_METHOD_SEMA_SEMANTICS
]) {
2486 case METHOD_SEMANTIC_SETTER
:
2487 properties
[i
- first
].set
= method
;
2489 case METHOD_SEMANTIC_GETTER
:
2490 properties
[i
- first
].get
= method
;
2499 mono_class_alloc_ext (class);
2501 mono_image_lock (class->image
);
2503 if (class->ext
->properties
) {
2504 /* We leak 'properties' which was allocated from the image mempool */
2505 mono_image_unlock (class->image
);
2509 class->ext
->property
.first
= first
;
2510 class->ext
->property
.count
= count
;
2512 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2513 mono_memory_barrier ();
2515 /* Leave this assignment as the last op in the function */
2516 class->ext
->properties
= properties
;
2518 mono_image_unlock (class->image
);
2522 inflate_method_listz (MonoMethod
**methods
, MonoClass
*class, MonoGenericContext
*context
)
2524 MonoMethod
**om
, **retval
;
2527 for (om
= methods
, count
= 0; *om
; ++om
, ++count
)
2530 retval
= g_new0 (MonoMethod
*, count
+ 1);
2532 for (om
= methods
, count
= 0; *om
; ++om
, ++count
) {
2534 retval
[count
] = mono_class_inflate_generic_method_full_checked (*om
, class, context
, &error
);
2535 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
2541 /*This method can fail the class.*/
2543 mono_class_setup_events (MonoClass
*class)
2546 guint startm
, endm
, i
, j
;
2547 guint32 cols
[MONO_EVENT_SIZE
];
2548 MonoTableInfo
*msemt
= &class->image
->tables
[MONO_TABLE_METHODSEMANTICS
];
2552 if (class->ext
&& class->ext
->events
)
2555 if (class->generic_class
) {
2556 MonoClass
*gklass
= class->generic_class
->container_class
;
2557 MonoGenericContext
*context
= NULL
;
2559 mono_class_setup_events (gklass
);
2560 if (gklass
->exception_type
) {
2561 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Generic type definition failed to load"));
2565 first
= gklass
->ext
->event
.first
;
2566 count
= gklass
->ext
->event
.count
;
2568 events
= mono_class_new0 (class, MonoEvent
, count
);
2571 context
= mono_class_get_context (class);
2573 for (i
= 0; i
< count
; i
++) {
2575 MonoEvent
*event
= &events
[i
];
2576 MonoEvent
*gevent
= &gklass
->ext
->events
[i
];
2578 mono_error_init (&error
); //since we do conditional calls, we must ensure the default value is ok
2580 event
->parent
= class;
2581 event
->name
= gevent
->name
;
2582 event
->add
= gevent
->add
? mono_class_inflate_generic_method_full_checked (gevent
->add
, class, context
, &error
) : NULL
;
2583 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
2584 event
->remove
= gevent
->remove
? mono_class_inflate_generic_method_full_checked (gevent
->remove
, class, context
, &error
) : NULL
;
2585 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
2586 event
->raise
= gevent
->raise
? mono_class_inflate_generic_method_full_checked (gevent
->raise
, class, context
, &error
) : NULL
;
2587 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
2589 #ifndef MONO_SMALL_CONFIG
2590 event
->other
= gevent
->other
? inflate_method_listz (gevent
->other
, class, context
) : NULL
;
2592 event
->attrs
= gevent
->attrs
;
2595 first
= mono_metadata_events_from_typedef (class->image
, mono_metadata_token_index (class->type_token
) - 1, &last
);
2596 count
= last
- first
;
2599 mono_class_setup_methods (class);
2600 if (class->exception_type
) {
2601 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Generic type definition failed to load"));
2606 events
= mono_class_alloc0 (class, sizeof (MonoEvent
) * count
);
2607 for (i
= first
; i
< last
; ++i
) {
2608 MonoEvent
*event
= &events
[i
- first
];
2610 mono_metadata_decode_table_row (class->image
, MONO_TABLE_EVENT
, i
, cols
, MONO_EVENT_SIZE
);
2611 event
->parent
= class;
2612 event
->attrs
= cols
[MONO_EVENT_FLAGS
];
2613 event
->name
= mono_metadata_string_heap (class->image
, cols
[MONO_EVENT_NAME
]);
2615 startm
= mono_metadata_methods_from_event (class->image
, i
, &endm
);
2616 for (j
= startm
; j
< endm
; ++j
) {
2619 mono_metadata_decode_row (msemt
, j
, cols
, MONO_METHOD_SEMA_SIZE
);
2621 if (class->image
->uncompressed_metadata
) {
2623 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2624 method
= mono_get_method_checked (class->image
, MONO_TOKEN_METHOD_DEF
| cols
[MONO_METHOD_SEMA_METHOD
], class, NULL
, &error
);
2625 mono_error_cleanup (&error
); /* FIXME don't swallow this error */
2627 method
= class->methods
[cols
[MONO_METHOD_SEMA_METHOD
] - 1 - class->method
.first
];
2630 switch (cols
[MONO_METHOD_SEMA_SEMANTICS
]) {
2631 case METHOD_SEMANTIC_ADD_ON
:
2632 event
->add
= method
;
2634 case METHOD_SEMANTIC_REMOVE_ON
:
2635 event
->remove
= method
;
2637 case METHOD_SEMANTIC_FIRE
:
2638 event
->raise
= method
;
2640 case METHOD_SEMANTIC_OTHER
: {
2641 #ifndef MONO_SMALL_CONFIG
2644 if (event
->other
== NULL
) {
2645 event
->other
= g_new0 (MonoMethod
*, 2);
2647 while (event
->other
[n
])
2649 event
->other
= g_realloc (event
->other
, (n
+ 2) * sizeof (MonoMethod
*));
2651 event
->other
[n
] = method
;
2652 /* NULL terminated */
2653 event
->other
[n
+ 1] = NULL
;
2664 mono_class_alloc_ext (class);
2666 mono_image_lock (class->image
);
2668 if (class->ext
->events
) {
2669 mono_image_unlock (class->image
);
2673 class->ext
->event
.first
= first
;
2674 class->ext
->event
.count
= count
;
2676 /* Flush any pending writes as we do double checked locking on class->ext.events */
2677 mono_memory_barrier ();
2679 /* Leave this assignment as the last op in the function */
2680 class->ext
->events
= events
;
2682 mono_image_unlock (class->image
);
2686 * Global pool of interface IDs, represented as a bitset.
2687 * LOCKING: Protected by the classes lock.
2689 static MonoBitSet
*global_interface_bitset
= NULL
;
2692 * mono_unload_interface_ids:
2693 * @bitset: bit set of interface IDs
2695 * When an image is unloaded, the interface IDs associated with
2696 * the image are put back in the global pool of IDs so the numbers
2700 mono_unload_interface_ids (MonoBitSet
*bitset
)
2703 mono_bitset_sub (global_interface_bitset
, bitset
);
2708 mono_unload_interface_id (MonoClass
*class)
2710 if (global_interface_bitset
&& class->interface_id
) {
2712 mono_bitset_clear (global_interface_bitset
, class->interface_id
);
2718 * mono_get_unique_iid:
2721 * Assign a unique integer ID to the interface represented by @class.
2722 * The ID will positive and as small as possible.
2723 * LOCKING: Acquires the classes lock.
2724 * Returns: the new ID.
2727 mono_get_unique_iid (MonoClass
*class)
2731 g_assert (MONO_CLASS_IS_INTERFACE (class));
2735 if (!global_interface_bitset
) {
2736 global_interface_bitset
= mono_bitset_new (128, 0);
2739 iid
= mono_bitset_find_first_unset (global_interface_bitset
, -1);
2741 int old_size
= mono_bitset_size (global_interface_bitset
);
2742 MonoBitSet
*new_set
= mono_bitset_clone (global_interface_bitset
, old_size
* 2);
2743 mono_bitset_free (global_interface_bitset
);
2744 global_interface_bitset
= new_set
;
2747 mono_bitset_set (global_interface_bitset
, iid
);
2748 /* set the bit also in the per-image set */
2749 if (!class->generic_class
) {
2750 if (class->image
->interface_bitset
) {
2751 if (iid
>= mono_bitset_size (class->image
->interface_bitset
)) {
2752 MonoBitSet
*new_set
= mono_bitset_clone (class->image
->interface_bitset
, iid
+ 1);
2753 mono_bitset_free (class->image
->interface_bitset
);
2754 class->image
->interface_bitset
= new_set
;
2757 class->image
->interface_bitset
= mono_bitset_new (iid
+ 1, 0);
2759 mono_bitset_set (class->image
->interface_bitset
, iid
);
2764 #ifndef MONO_SMALL_CONFIG
2765 if (mono_print_vtable
) {
2767 char *type_name
= mono_type_full_name (&class->byval_arg
);
2768 if (class->generic_class
&& !class->generic_class
->context
.class_inst
->is_open
) {
2769 generic_id
= class->generic_class
->context
.class_inst
->id
;
2770 g_assert (generic_id
!= 0);
2774 printf ("Interface: assigned id %d to %s|%s|%d\n", iid
, class->image
->name
, type_name
, generic_id
);
2779 g_assert (iid
<= 65535);
2784 collect_implemented_interfaces_aux (MonoClass
*klass
, GPtrArray
**res
, MonoError
*error
)
2789 mono_class_setup_interfaces (klass
, error
);
2790 if (!mono_error_ok (error
))
2793 for (i
= 0; i
< klass
->interface_count
; i
++) {
2794 ic
= klass
->interfaces
[i
];
2797 *res
= g_ptr_array_new ();
2798 g_ptr_array_add (*res
, ic
);
2799 mono_class_init (ic
);
2800 if (ic
->exception_type
) {
2801 mono_error_set_type_load_class (error
, ic
, "Error Loading class");
2805 collect_implemented_interfaces_aux (ic
, res
, error
);
2806 if (!mono_error_ok (error
))
2812 mono_class_get_implemented_interfaces (MonoClass
*klass
, MonoError
*error
)
2814 GPtrArray
*res
= NULL
;
2816 collect_implemented_interfaces_aux (klass
, &res
, error
);
2817 if (!mono_error_ok (error
)) {
2819 g_ptr_array_free (res
, TRUE
);
2826 compare_interface_ids (const void *p_key
, const void *p_element
) {
2827 const MonoClass
*key
= p_key
;
2828 const MonoClass
*element
= *(MonoClass
**) p_element
;
2830 return (key
->interface_id
- element
->interface_id
);
2833 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2835 mono_class_interface_offset (MonoClass
*klass
, MonoClass
*itf
) {
2836 MonoClass
**result
= mono_binary_search (
2838 klass
->interfaces_packed
,
2839 klass
->interface_offsets_count
,
2840 sizeof (MonoClass
*),
2841 compare_interface_ids
);
2843 return klass
->interface_offsets_packed
[result
- (klass
->interfaces_packed
)];
2850 * mono_class_interface_offset_with_variance:
2852 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2853 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2855 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2857 * FIXME figure out MS disambiguation rules and fix this function.
2860 mono_class_interface_offset_with_variance (MonoClass
*klass
, MonoClass
*itf
, gboolean
*non_exact_match
) {
2861 int i
= mono_class_interface_offset (klass
, itf
);
2862 *non_exact_match
= FALSE
;
2866 if (!mono_class_has_variant_generic_params (itf
))
2869 for (i
= 0; i
< klass
->interface_offsets_count
; i
++) {
2870 if (mono_class_is_variant_compatible (itf
, klass
->interfaces_packed
[i
], FALSE
)) {
2871 *non_exact_match
= TRUE
;
2872 return klass
->interface_offsets_packed
[i
];
2880 print_implemented_interfaces (MonoClass
*klass
) {
2883 GPtrArray
*ifaces
= NULL
;
2885 int ancestor_level
= 0;
2887 name
= mono_type_get_full_name (klass
);
2888 printf ("Packed interface table for class %s has size %d\n", name
, klass
->interface_offsets_count
);
2891 for (i
= 0; i
< klass
->interface_offsets_count
; i
++)
2892 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i
,
2893 klass
->interfaces_packed
[i
]->interface_id
,
2894 klass
->interface_offsets_packed
[i
],
2895 klass
->interfaces_packed
[i
]->method
.count
,
2896 klass
->interfaces_packed
[i
]->name_space
,
2897 klass
->interfaces_packed
[i
]->name
);
2898 printf ("Interface flags: ");
2899 for (i
= 0; i
<= klass
->max_interface_id
; i
++)
2900 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass
, i
))
2901 printf ("(%d,T)", i
);
2903 printf ("(%d,F)", i
);
2905 printf ("Dump interface flags:");
2906 #ifdef COMPRESSED_INTERFACE_BITMAP
2908 const uint8_t* p
= klass
->interface_bitmap
;
2909 i
= klass
->max_interface_id
;
2911 printf (" %d x 00 %02X", p
[0], p
[1]);
2917 for (i
= 0; i
< ((((klass
->max_interface_id
+ 1) >> 3)) + (((klass
->max_interface_id
+ 1) & 7)? 1 :0)); i
++)
2918 printf (" %02X", klass
->interface_bitmap
[i
]);
2921 while (klass
!= NULL
) {
2922 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level
, klass
->name
);
2923 ifaces
= mono_class_get_implemented_interfaces (klass
, &error
);
2924 if (!mono_error_ok (&error
)) {
2925 printf (" Type failed due to %s\n", mono_error_get_message (&error
));
2926 mono_error_cleanup (&error
);
2927 } else if (ifaces
) {
2928 for (i
= 0; i
< ifaces
->len
; i
++) {
2929 MonoClass
*ic
= g_ptr_array_index (ifaces
, i
);
2930 printf (" [UIID %d] interface %s\n", ic
->interface_id
, ic
->name
);
2931 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i
,
2933 mono_class_interface_offset (klass
, ic
),
2938 g_ptr_array_free (ifaces
, TRUE
);
2941 klass
= klass
->parent
;
2946 inflate_class_one_arg (MonoClass
*gtype
, MonoClass
*arg0
)
2949 args
[0] = &arg0
->byval_arg
;
2951 return mono_class_bind_generic_parameters (gtype
, 1, args
, FALSE
);
2955 array_class_get_if_rank (MonoClass
*class, guint rank
)
2957 return rank
? mono_array_class_get (class, rank
) : class;
2961 fill_valuetype_array_derived_types (MonoClass
**valuetype_types
, MonoClass
*eclass
, int rank
)
2963 valuetype_types
[0] = eclass
;
2964 if (eclass
== mono_defaults
.int16_class
)
2965 valuetype_types
[1] = mono_defaults
.uint16_class
;
2966 else if (eclass
== mono_defaults
.uint16_class
)
2967 valuetype_types
[1] = mono_defaults
.int16_class
;
2968 else if (eclass
== mono_defaults
.int32_class
)
2969 valuetype_types
[1] = mono_defaults
.uint32_class
;
2970 else if (eclass
== mono_defaults
.uint32_class
)
2971 valuetype_types
[1] = mono_defaults
.int32_class
;
2972 else if (eclass
== mono_defaults
.int64_class
)
2973 valuetype_types
[1] = mono_defaults
.uint64_class
;
2974 else if (eclass
== mono_defaults
.uint64_class
)
2975 valuetype_types
[1] = mono_defaults
.int64_class
;
2976 else if (eclass
== mono_defaults
.byte_class
)
2977 valuetype_types
[1] = mono_defaults
.sbyte_class
;
2978 else if (eclass
== mono_defaults
.sbyte_class
)
2979 valuetype_types
[1] = mono_defaults
.byte_class
;
2980 else if (eclass
->enumtype
&& mono_class_enum_basetype (eclass
))
2981 valuetype_types
[1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass
));
2984 /* this won't be needed once bug #325495 is completely fixed
2985 * though we'll need something similar to know which interfaces to allow
2986 * in arrays when they'll be lazyly created
2988 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2989 * MS returns diferrent types based on which instance is called. For example:
2990 * object obj = new byte[10][];
2991 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2992 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2995 * Fixing this should kill quite some code, save some bits and improve compatibility.
2998 get_implicit_generic_array_interfaces (MonoClass
*class, int *num
, int *is_enumerator
)
3000 MonoClass
*eclass
= class->element_class
;
3001 static MonoClass
* generic_icollection_class
= NULL
;
3002 static MonoClass
* generic_ienumerable_class
= NULL
;
3003 static MonoClass
* generic_ienumerator_class
= NULL
;
3004 static MonoClass
* generic_ireadonlylist_class
= NULL
;
3005 static MonoClass
* generic_ireadonlycollection_class
= NULL
;
3006 MonoClass
*valuetype_types
[2] = { NULL
, NULL
};
3007 MonoClass
**interfaces
= NULL
;
3008 int i
, nifaces
, interface_count
, real_count
, original_rank
;
3010 gboolean internal_enumerator
;
3011 gboolean eclass_is_valuetype
;
3013 if (!mono_defaults
.generic_ilist_class
) {
3017 internal_enumerator
= FALSE
;
3018 eclass_is_valuetype
= FALSE
;
3019 original_rank
= eclass
->rank
;
3020 if (class->byval_arg
.type
!= MONO_TYPE_SZARRAY
) {
3021 if (class->generic_class
&& class->nested_in
== mono_defaults
.array_class
&& strcmp (class->name
, "InternalEnumerator`1") == 0) {
3023 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3025 eclass
= mono_class_from_mono_type (class->generic_class
->context
.class_inst
->type_argv
[0]);
3026 original_rank
= eclass
->rank
;
3028 eclass
= eclass
->element_class
;
3029 internal_enumerator
= TRUE
;
3030 *is_enumerator
= TRUE
;
3038 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3039 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3041 all_interfaces
= eclass
->rank
&& eclass
->element_class
->rank
? FALSE
: TRUE
;
3043 if (!generic_icollection_class
) {
3044 generic_icollection_class
= mono_class_from_name (mono_defaults
.corlib
,
3045 "System.Collections.Generic", "ICollection`1");
3046 generic_ienumerable_class
= mono_class_from_name (mono_defaults
.corlib
,
3047 "System.Collections.Generic", "IEnumerable`1");
3048 generic_ienumerator_class
= mono_class_from_name (mono_defaults
.corlib
,
3049 "System.Collections.Generic", "IEnumerator`1");
3050 generic_ireadonlylist_class
= mono_class_from_name (mono_defaults
.corlib
,
3051 "System.Collections.Generic", "IReadOnlyList`1");
3052 generic_ireadonlycollection_class
= mono_class_from_name (mono_defaults
.corlib
,
3053 "System.Collections.Generic", "IReadOnlyCollection`1");
3056 mono_class_init (eclass
);
3059 * Arrays in 2.0 need to implement a number of generic interfaces
3060 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3061 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3062 * We collect the types needed to build the
3063 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3064 * the generic interfaces needed to implement.
3066 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3067 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3069 if (eclass
->valuetype
) {
3070 nifaces
= generic_ireadonlylist_class
? 5 : 3;
3071 fill_valuetype_array_derived_types (valuetype_types
, eclass
, original_rank
);
3073 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3074 real_count
= interface_count
= valuetype_types
[1] ? (nifaces
* 2) : nifaces
;
3075 if (internal_enumerator
) {
3077 if (valuetype_types
[1])
3081 interfaces
= g_malloc0 (sizeof (MonoClass
*) * real_count
);
3082 interfaces
[0] = valuetype_types
[0];
3083 if (valuetype_types
[1])
3084 interfaces
[nifaces
] = valuetype_types
[1];
3086 eclass_is_valuetype
= TRUE
;
3089 int idepth
= eclass
->idepth
;
3090 if (!internal_enumerator
)
3092 nifaces
= generic_ireadonlylist_class
? 2 : 3;
3094 // FIXME: This doesn't seem to work/required for generic params
3095 if (!(eclass
->this_arg
.type
== MONO_TYPE_VAR
|| eclass
->this_arg
.type
== MONO_TYPE_MVAR
|| (image_is_dynamic (eclass
->image
) && !eclass
->wastypebuilder
)))
3096 mono_class_setup_interface_offsets (eclass
);
3098 interface_count
= all_interfaces
? eclass
->interface_offsets_count
: eclass
->interface_count
;
3099 /* we add object for interfaces and the supertypes for the other
3100 * types. The last of the supertypes is the element class itself which we
3101 * already created the explicit interfaces for (so we include it for IEnumerator
3102 * and exclude it for arrays).
3104 if (MONO_CLASS_IS_INTERFACE (eclass
))
3107 interface_count
+= idepth
;
3108 if (eclass
->rank
&& eclass
->element_class
->valuetype
) {
3109 fill_valuetype_array_derived_types (valuetype_types
, eclass
->element_class
, original_rank
);
3110 if (valuetype_types
[1])
3113 /* IList, ICollection, IEnumerable, IReadOnlyList */
3114 interface_count
*= nifaces
;
3115 real_count
= interface_count
;
3116 if (internal_enumerator
) {
3117 real_count
+= (MONO_CLASS_IS_INTERFACE (eclass
) ? 1 : idepth
) + eclass
->interface_offsets_count
;
3118 if (valuetype_types
[1])
3121 interfaces
= g_malloc0 (sizeof (MonoClass
*) * real_count
);
3122 if (MONO_CLASS_IS_INTERFACE (eclass
)) {
3123 interfaces
[0] = mono_defaults
.object_class
;
3127 for (i
= 0; i
< idepth
; i
++) {
3128 mono_class_init (eclass
->supertypes
[i
]);
3129 interfaces
[j
] = eclass
->supertypes
[i
];
3133 if (all_interfaces
) {
3134 for (i
= 0; i
< eclass
->interface_offsets_count
; i
++) {
3135 interfaces
[j
] = eclass
->interfaces_packed
[i
];
3139 for (i
= 0; i
< eclass
->interface_count
; i
++) {
3140 interfaces
[j
] = eclass
->interfaces
[i
];
3144 if (valuetype_types
[1]) {
3145 interfaces
[j
] = array_class_get_if_rank (valuetype_types
[1], original_rank
);
3150 /* instantiate the generic interfaces */
3151 for (i
= 0; i
< interface_count
; i
+= nifaces
) {
3152 MonoClass
*iface
= interfaces
[i
];
3154 interfaces
[i
+ 0] = inflate_class_one_arg (mono_defaults
.generic_ilist_class
, iface
);
3155 interfaces
[i
+ 1] = inflate_class_one_arg (generic_icollection_class
, iface
);
3157 if (eclass
->valuetype
) {
3158 interfaces
[i
+ 2] = inflate_class_one_arg (generic_ienumerable_class
, iface
);
3159 if (generic_ireadonlylist_class
) {
3160 interfaces
[i
+ 3] = inflate_class_one_arg (generic_ireadonlylist_class
, iface
);
3161 interfaces
[i
+ 4] = inflate_class_one_arg (generic_ireadonlycollection_class
, iface
);
3164 if (!generic_ireadonlylist_class
)
3165 interfaces
[i
+ 2] = inflate_class_one_arg (generic_ienumerable_class
, iface
);
3168 if (internal_enumerator
) {
3170 /* instantiate IEnumerator<iface> */
3171 for (i
= 0; i
< interface_count
; i
++) {
3172 interfaces
[i
] = inflate_class_one_arg (generic_ienumerator_class
, interfaces
[i
]);
3174 j
= interface_count
;
3175 if (!eclass_is_valuetype
) {
3176 if (MONO_CLASS_IS_INTERFACE (eclass
)) {
3177 interfaces
[j
] = inflate_class_one_arg (generic_ienumerator_class
, mono_defaults
.object_class
);
3180 for (i
= 0; i
< eclass
->idepth
; i
++) {
3181 interfaces
[j
] = inflate_class_one_arg (generic_ienumerator_class
, eclass
->supertypes
[i
]);
3185 for (i
= 0; i
< eclass
->interface_offsets_count
; i
++) {
3186 interfaces
[j
] = inflate_class_one_arg (generic_ienumerator_class
, eclass
->interfaces_packed
[i
]);
3190 interfaces
[j
++] = inflate_class_one_arg (generic_ienumerator_class
, array_class_get_if_rank (valuetype_types
[0], original_rank
));
3192 if (valuetype_types
[1])
3193 interfaces
[j
] = inflate_class_one_arg (generic_ienumerator_class
, array_class_get_if_rank (valuetype_types
[1], original_rank
));
3197 char *type_name
= mono_type_get_name_full (&class->byval_arg
, 0);
3198 for (i
= 0; i
< real_count
; ++i
) {
3199 char *name
= mono_type_get_name_full (&interfaces
[i
]->byval_arg
, 0);
3200 g_print ("%s implements %s\n", type_name
, name
);
3211 find_array_interface (MonoClass
*klass
, const char *name
)
3214 for (i
= 0; i
< klass
->interface_count
; ++i
) {
3215 if (strcmp (klass
->interfaces
[i
]->name
, name
) == 0)
3222 * Return the number of virtual methods.
3223 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3224 * Return -1 on failure.
3225 * FIXME It would be nice if this information could be cached somewhere.
3228 count_virtual_methods (MonoClass
*class)
3232 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3234 if (class->methods
|| !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3235 mono_class_setup_methods (class);
3236 if (class->exception_type
)
3239 for (i
= 0; i
< class->method
.count
; ++i
) {
3240 flags
= class->methods
[i
]->flags
;
3241 if (flags
& METHOD_ATTRIBUTE_VIRTUAL
)
3245 for (i
= 0; i
< class->method
.count
; ++i
) {
3246 flags
= mono_metadata_decode_table_row_col (class->image
, MONO_TABLE_METHOD
, class->method
.first
+ i
, MONO_METHOD_FLAGS
);
3248 if (flags
& METHOD_ATTRIBUTE_VIRTUAL
)
3256 find_interface (int num_ifaces
, MonoClass
**interfaces_full
, MonoClass
*ic
)
3264 m
= (l
+ num_ifaces
) / 2;
3265 if (interfaces_full
[m
] == ic
)
3267 if (l
== num_ifaces
)
3269 if (!interfaces_full
[m
] || interfaces_full
[m
]->interface_id
> ic
->interface_id
) {
3278 find_interface_offset (int num_ifaces
, MonoClass
**interfaces_full
, int *interface_offsets_full
, MonoClass
*ic
)
3280 int i
= find_interface (num_ifaces
, interfaces_full
, ic
);
3282 return interface_offsets_full
[i
];
3287 set_interface_and_offset (int num_ifaces
, MonoClass
**interfaces_full
, int *interface_offsets_full
, MonoClass
*ic
, int offset
, mono_bool force_set
)
3289 int i
= find_interface (num_ifaces
, interfaces_full
, ic
);
3293 interface_offsets_full
[i
] = offset
;
3296 for (i
= 0; i
< num_ifaces
; ++i
) {
3297 if (interfaces_full
[i
]) {
3299 if (interfaces_full
[i
]->interface_id
< ic
->interface_id
)
3302 while (end
< num_ifaces
&& interfaces_full
[end
]) end
++;
3303 memmove (interfaces_full
+ i
+ 1, interfaces_full
+ i
, sizeof (MonoClass
*) * (end
- i
));
3304 memmove (interface_offsets_full
+ i
+ 1, interface_offsets_full
+ i
, sizeof (int) * (end
- i
));
3306 interfaces_full
[i
] = ic
;
3307 interface_offsets_full
[i
] = offset
;
3313 #ifdef COMPRESSED_INTERFACE_BITMAP
3316 * Compressed interface bitmap design.
3318 * Interface bitmaps take a large amount of memory, because their size is
3319 * linear with the maximum interface id assigned in the process (each interface
3320 * is assigned a unique id as it is loaded). The number of interface classes
3321 * is high because of the many implicit interfaces implemented by arrays (we'll
3322 * need to lazy-load them in the future).
3323 * Most classes implement a very small number of interfaces, so the bitmap is
3324 * sparse. This bitmap needs to be checked by interface casts, so access to the
3325 * needed bit must be fast and doable with few jit instructions.
3327 * The current compression format is as follows:
3328 * *) it is a sequence of one or more two-byte elements
3329 * *) the first byte in the element is the count of empty bitmap bytes
3330 * at the current bitmap position
3331 * *) the second byte in the element is an actual bitmap byte at the current
3334 * As an example, the following compressed bitmap bytes:
3335 * 0x07 0x01 0x00 0x7
3336 * correspond to the following bitmap:
3337 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3339 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3340 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3341 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3345 * mono_compress_bitmap:
3346 * @dest: destination buffer
3347 * @bitmap: bitmap buffer
3348 * @size: size of @bitmap in bytes
3350 * This is a mono internal function.
3351 * The @bitmap data is compressed into a format that is small but
3352 * still searchable in few instructions by the JIT and runtime.
3353 * The compressed data is stored in the buffer pointed to by the
3354 * @dest array. Passing a #NULL value for @dest allows to just compute
3355 * the size of the buffer.
3356 * This compression algorithm assumes the bits set in the bitmap are
3357 * few and far between, like in interface bitmaps.
3358 * Returns: the size of the compressed bitmap in bytes.
3361 mono_compress_bitmap (uint8_t *dest
, const uint8_t *bitmap
, int size
)
3365 const uint8_t *end
= bitmap
+ size
;
3366 while (bitmap
< end
) {
3367 if (*bitmap
|| numz
== 255) {
3391 * mono_class_interface_match:
3392 * @bitmap: a compressed bitmap buffer
3393 * @id: the index to check in the bitmap
3395 * This is a mono internal function.
3396 * Checks if a bit is set in a compressed interface bitmap. @id must
3397 * be already checked for being smaller than the maximum id encoded in the
3400 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3404 mono_class_interface_match (const uint8_t *bitmap
, int id
)
3407 id
-= bitmap
[0] * 8;
3411 return bitmap
[1] & (1 << id
);
3420 * LOCKING: this is supposed to be called with the loader lock held.
3421 * Return -1 on failure and set exception_type
3424 setup_interface_offsets (MonoClass
*class, int cur_slot
, gboolean overwrite
)
3428 int i
, j
, max_iid
, num_ifaces
;
3429 MonoClass
**interfaces_full
= NULL
;
3430 int *interface_offsets_full
= NULL
;
3432 GPtrArray
**ifaces_array
= NULL
;
3433 int interface_offsets_count
;
3434 MonoClass
**array_interfaces
= NULL
;
3435 int num_array_interfaces
;
3436 int is_enumerator
= FALSE
;
3438 mono_class_setup_supertypes (class);
3440 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3441 * implicit interfaces have the property that they are assigned the same slot in the
3442 * vtables for compatible interfaces
3444 array_interfaces
= get_implicit_generic_array_interfaces (class, &num_array_interfaces
, &is_enumerator
);
3446 /* compute maximum number of slots and maximum interface id */
3448 num_ifaces
= num_array_interfaces
; /* this can include duplicated ones */
3449 ifaces_array
= g_new0 (GPtrArray
*, class->idepth
);
3450 for (j
= 0; j
< class->idepth
; j
++) {
3451 k
= class->supertypes
[j
];
3452 num_ifaces
+= k
->interface_count
;
3453 for (i
= 0; i
< k
->interface_count
; i
++) {
3454 ic
= k
->interfaces
[i
];
3457 mono_class_init (ic
);
3459 if (max_iid
< ic
->interface_id
)
3460 max_iid
= ic
->interface_id
;
3462 ifaces
= mono_class_get_implemented_interfaces (k
, &error
);
3463 if (!mono_error_ok (&error
)) {
3464 char *name
= mono_type_get_full_name (k
);
3465 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
)));
3467 mono_error_cleanup (&error
);
3472 num_ifaces
+= ifaces
->len
;
3473 for (i
= 0; i
< ifaces
->len
; ++i
) {
3474 ic
= g_ptr_array_index (ifaces
, i
);
3475 if (max_iid
< ic
->interface_id
)
3476 max_iid
= ic
->interface_id
;
3478 ifaces_array
[j
] = ifaces
;
3482 for (i
= 0; i
< num_array_interfaces
; ++i
) {
3483 ic
= array_interfaces
[i
];
3484 mono_class_init (ic
);
3485 if (max_iid
< ic
->interface_id
)
3486 max_iid
= ic
->interface_id
;
3489 if (MONO_CLASS_IS_INTERFACE (class)) {
3491 if (max_iid
< class->interface_id
)
3492 max_iid
= class->interface_id
;
3494 class->max_interface_id
= max_iid
;
3495 /* compute vtable offset for interfaces */
3496 interfaces_full
= g_malloc0 (sizeof (MonoClass
*) * num_ifaces
);
3497 interface_offsets_full
= g_malloc (sizeof (int) * num_ifaces
);
3499 for (i
= 0; i
< num_ifaces
; i
++) {
3500 interface_offsets_full
[i
] = -1;
3503 /* skip the current class */
3504 for (j
= 0; j
< class->idepth
- 1; j
++) {
3505 k
= class->supertypes
[j
];
3506 ifaces
= ifaces_array
[j
];
3509 for (i
= 0; i
< ifaces
->len
; ++i
) {
3511 ic
= g_ptr_array_index (ifaces
, i
);
3513 /*Force the sharing of interface offsets between parent and subtypes.*/
3514 io
= mono_class_interface_offset (k
, ic
);
3516 set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ic
, io
, TRUE
);
3521 g_assert (class == class->supertypes
[class->idepth
- 1]);
3522 ifaces
= ifaces_array
[class->idepth
- 1];
3524 for (i
= 0; i
< ifaces
->len
; ++i
) {
3526 ic
= g_ptr_array_index (ifaces
, i
);
3527 if (set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ic
, cur_slot
, FALSE
))
3529 count
= count_virtual_methods (ic
);
3531 char *name
= mono_type_get_full_name (ic
);
3532 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Error calculating interface offset of %s", name
));
3541 if (MONO_CLASS_IS_INTERFACE (class))
3542 set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, class, cur_slot
, TRUE
);
3544 if (num_array_interfaces
) {
3545 if (is_enumerator
) {
3546 int ienumerator_idx
= find_array_interface (class, "IEnumerator`1");
3547 int ienumerator_offset
= find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, class->interfaces
[ienumerator_idx
]);
3548 g_assert (ienumerator_offset
>= 0);
3549 for (i
= 0; i
< num_array_interfaces
; ++i
) {
3550 ic
= array_interfaces
[i
];
3551 if (strcmp (ic
->name
, "IEnumerator`1") == 0)
3552 set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ic
, ienumerator_offset
, TRUE
);
3554 g_assert_not_reached ();
3555 /*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);*/
3558 int ilist_offset
, icollection_offset
, ienumerable_offset
, ireadonlylist_offset
, ireadonlycollection_offset
;
3559 int ilist_iface_idx
= find_array_interface (class, "IList`1");
3560 MonoClass
* ilist_class
= class->interfaces
[ilist_iface_idx
];
3561 int ireadonlylist_iface_idx
= find_array_interface (class, "IReadOnlyList`1");
3562 MonoClass
* ireadonlylist_class
= ireadonlylist_iface_idx
!= -1 ? class->interfaces
[ireadonlylist_iface_idx
] : NULL
;
3563 int icollection_iface_idx
= find_array_interface (ilist_class
, "ICollection`1");
3564 int ienumerable_iface_idx
= find_array_interface (ilist_class
, "IEnumerable`1");
3565 int ireadonlycollection_iface_idx
= ireadonlylist_iface_idx
!= -1 ? find_array_interface (ireadonlylist_class
, "IReadOnlyCollection`1") : -1;
3566 ilist_offset
= find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, class->interfaces
[ilist_iface_idx
]);
3567 icollection_offset
= find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ilist_class
->interfaces
[icollection_iface_idx
]);
3568 ienumerable_offset
= find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ilist_class
->interfaces
[ienumerable_iface_idx
]);
3569 ireadonlylist_offset
= ireadonlylist_iface_idx
!= -1 ? find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, class->interfaces
[ireadonlylist_iface_idx
]) : -1;
3570 ireadonlycollection_offset
= ireadonlycollection_iface_idx
!= -1 ? find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ireadonlylist_class
->interfaces
[ireadonlycollection_iface_idx
]) : -1;
3571 g_assert (ilist_offset
>= 0 && icollection_offset
>= 0 && ienumerable_offset
>= 0);
3572 for (i
= 0; i
< num_array_interfaces
; ++i
) {
3574 ic
= array_interfaces
[i
];
3575 if (ic
->generic_class
->container_class
== mono_defaults
.generic_ilist_class
)
3576 offset
= ilist_offset
;
3577 else if (strcmp (ic
->name
, "ICollection`1") == 0)
3578 offset
= icollection_offset
;
3579 else if (strcmp (ic
->name
, "IEnumerable`1") == 0)
3580 offset
= ienumerable_offset
;
3581 else if (strcmp (ic
->name
, "IReadOnlyList`1") == 0)
3582 offset
= ireadonlylist_offset
;
3583 else if (strcmp (ic
->name
, "IReadOnlyCollection`1") == 0)
3584 offset
= ireadonlycollection_offset
;
3586 g_assert_not_reached ();
3587 set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ic
, offset
, TRUE
);
3588 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3593 for (interface_offsets_count
= 0, i
= 0; i
< num_ifaces
; i
++) {
3594 if (interface_offsets_full
[i
] != -1) {
3595 interface_offsets_count
++;
3600 * We might get called multiple times:
3601 * - mono_class_init ()
3602 * - mono_class_setup_vtable ().
3603 * - mono_class_setup_interface_offsets ().
3604 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3605 * means we have to overwrite those when called from other places (#4440).
3607 if (class->interfaces_packed
&& !overwrite
) {
3608 g_assert (class->interface_offsets_count
== interface_offsets_count
);
3612 class->interface_offsets_count
= interface_offsets_count
;
3613 class->interfaces_packed
= mono_class_alloc (class, sizeof (MonoClass
*) * interface_offsets_count
);
3614 class->interface_offsets_packed
= mono_class_alloc (class, sizeof (guint16
) * interface_offsets_count
);
3615 bsize
= (sizeof (guint8
) * ((max_iid
+ 1) >> 3)) + (((max_iid
+ 1) & 7)? 1 :0);
3616 #ifdef COMPRESSED_INTERFACE_BITMAP
3617 bitmap
= g_malloc0 (bsize
);
3619 bitmap
= mono_class_alloc0 (class, bsize
);
3621 for (i
= 0; i
< interface_offsets_count
; i
++) {
3622 int id
= interfaces_full
[i
]->interface_id
;
3623 bitmap
[id
>> 3] |= (1 << (id
& 7));
3624 class->interfaces_packed
[i
] = interfaces_full
[i
];
3625 class->interface_offsets_packed
[i
] = interface_offsets_full
[i
];
3626 /*if (num_array_interfaces)
3627 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]);*/
3629 #ifdef COMPRESSED_INTERFACE_BITMAP
3630 i
= mono_compress_bitmap (NULL
, bitmap
, bsize
);
3631 class->interface_bitmap
= mono_class_alloc0 (class, i
);
3632 mono_compress_bitmap (class->interface_bitmap
, bitmap
, bsize
);
3635 class->interface_bitmap
= bitmap
;
3640 g_free (interfaces_full
);
3641 g_free (interface_offsets_full
);
3642 g_free (array_interfaces
);
3643 for (i
= 0; i
< class->idepth
; i
++) {
3644 ifaces
= ifaces_array
[i
];
3646 g_ptr_array_free (ifaces
, TRUE
);
3648 g_free (ifaces_array
);
3650 //printf ("JUST DONE: ");
3651 //print_implemented_interfaces (class);
3657 * Setup interface offsets for interfaces.
3659 * - class->max_interface_id
3660 * - class->interface_offsets_count
3661 * - class->interfaces_packed
3662 * - class->interface_offsets_packed
3663 * - class->interface_bitmap
3665 * This function can fail @class.
3668 mono_class_setup_interface_offsets (MonoClass
*class)
3670 mono_loader_lock ();
3672 setup_interface_offsets (class, 0, FALSE
);
3674 mono_loader_unlock ();
3677 /*Checks if @klass has @parent as one of it's parents type gtd
3681 * Bar<T> : Foo<Bar<Bar<T>>>
3685 mono_class_has_gtd_parent (MonoClass
*klass
, MonoClass
*parent
)
3687 klass
= mono_class_get_generic_type_definition (klass
);
3688 parent
= mono_class_get_generic_type_definition (parent
);
3689 mono_class_setup_supertypes (klass
);
3690 mono_class_setup_supertypes (parent
);
3692 return klass
->idepth
>= parent
->idepth
&&
3693 mono_class_get_generic_type_definition (klass
->supertypes
[parent
->idepth
- 1]) == parent
;
3697 mono_class_check_vtable_constraints (MonoClass
*class, GList
*in_setup
)
3699 MonoGenericInst
*ginst
;
3701 if (!class->generic_class
) {
3702 mono_class_setup_vtable_full (class, in_setup
);
3703 return class->exception_type
== 0;
3706 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup
);
3707 if (class->generic_class
->container_class
->exception_type
) {
3708 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Failed to load generic definition vtable"));
3712 ginst
= class->generic_class
->context
.class_inst
;
3713 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
3715 if (ginst
->type_argv
[i
]->type
!= MONO_TYPE_GENERICINST
)
3717 arg
= mono_class_from_mono_type (ginst
->type_argv
[i
]);
3718 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3719 if (mono_class_has_gtd_parent (class, arg
) || mono_class_has_gtd_parent (arg
, class))
3721 if (!mono_class_check_vtable_constraints (arg
, in_setup
)) {
3722 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Failed to load generic parameter %d", i
));
3730 * mono_class_setup_vtable:
3732 * Creates the generic vtable of CLASS.
3733 * Initializes the following fields in MonoClass:
3736 * Plus all the fields initialized by setup_interface_offsets ().
3737 * If there is an error during vtable construction, class->exception_type is set.
3739 * LOCKING: Acquires the loader lock.
3742 mono_class_setup_vtable (MonoClass
*class)
3744 mono_class_setup_vtable_full (class, NULL
);
3748 mono_class_setup_vtable_full (MonoClass
*class, GList
*in_setup
)
3750 MonoMethod
**overrides
;
3751 MonoGenericContext
*context
;
3759 if (MONO_CLASS_IS_INTERFACE (class)) {
3760 /* This sets method->slot for all methods if this is an interface */
3761 mono_class_setup_methods (class);
3765 if (class->exception_type
)
3768 if (g_list_find (in_setup
, class))
3771 mono_loader_lock ();
3773 if (class->vtable
) {
3774 mono_loader_unlock ();
3778 mono_stats
.generic_vtable_count
++;
3779 in_setup
= g_list_prepend (in_setup
, class);
3781 if (class->generic_class
) {
3782 if (!mono_class_check_vtable_constraints (class, in_setup
)) {
3783 mono_loader_unlock ();
3784 g_list_remove (in_setup
, class);
3788 context
= mono_class_get_context (class);
3789 type_token
= class->generic_class
->container_class
->type_token
;
3791 context
= (MonoGenericContext
*) class->generic_container
;
3792 type_token
= class->type_token
;
3795 if (image_is_dynamic (class->image
)) {
3796 /* Generic instances can have zero method overrides without causing any harm.
3797 * This is true since we don't do layout all over again for them, we simply inflate
3798 * the layout of the parent.
3800 mono_reflection_get_dynamic_overrides (class, &overrides
, &onum
);
3802 /* The following call fails if there are missing methods in the type */
3803 /* FIXME it's probably a good idea to avoid this for generic instances. */
3804 ok
= mono_class_get_overrides_full (class->image
, type_token
, &overrides
, &onum
, context
);
3808 mono_class_setup_vtable_general (class, overrides
, onum
, in_setup
);
3810 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not load list of method overrides"));
3814 mono_loader_unlock ();
3815 g_list_remove (in_setup
, class);
3820 #define DEBUG_INTERFACE_VTABLE_CODE 0
3821 #define TRACE_INTERFACE_VTABLE_CODE 0
3822 #define VERIFY_INTERFACE_VTABLE_CODE 0
3823 #define VTABLE_SELECTOR (1)
3825 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3826 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3827 if (!(VTABLE_SELECTOR)) break; \
3831 #define DEBUG_INTERFACE_VTABLE(stmt)
3834 #if TRACE_INTERFACE_VTABLE_CODE
3835 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3836 if (!(VTABLE_SELECTOR)) break; \
3840 #define TRACE_INTERFACE_VTABLE(stmt)
3843 #if VERIFY_INTERFACE_VTABLE_CODE
3844 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3845 if (!(VTABLE_SELECTOR)) break; \
3849 #define VERIFY_INTERFACE_VTABLE(stmt)
3853 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3855 mono_signature_get_full_desc (MonoMethodSignature
*sig
, gboolean include_namespace
)
3859 GString
*res
= g_string_new ("");
3861 g_string_append_c (res
, '(');
3862 for (i
= 0; i
< sig
->param_count
; ++i
) {
3864 g_string_append_c (res
, ',');
3865 mono_type_get_desc (res
, sig
->params
[i
], include_namespace
);
3867 g_string_append (res
, ")=>");
3868 if (sig
->ret
!= NULL
) {
3869 mono_type_get_desc (res
, sig
->ret
, include_namespace
);
3871 g_string_append (res
, "NULL");
3874 g_string_free (res
, FALSE
);
3878 print_method_signatures (MonoMethod
*im
, MonoMethod
*cm
) {
3879 char *im_sig
= mono_signature_get_full_desc (mono_method_signature (im
), TRUE
);
3880 char *cm_sig
= mono_signature_get_full_desc (mono_method_signature (cm
), TRUE
);
3881 printf ("(IM \"%s\", CM \"%s\")", im_sig
, cm_sig
);
3889 is_wcf_hack_disabled (void)
3891 static gboolean disabled
;
3892 static gboolean inited
= FALSE
;
3894 disabled
= g_getenv ("MONO_DISABLE_WCF_HACK") != NULL
;
3901 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
) {
3902 MonoMethodSignature
*cmsig
, *imsig
;
3903 if (strcmp (im
->name
, cm
->name
) == 0) {
3904 if (! (cm
->flags
& METHOD_ATTRIBUTE_PUBLIC
)) {
3905 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3908 if (! slot_is_empty
) {
3909 if (require_newslot
) {
3910 if (! interface_is_explicitly_implemented_by_class
) {
3911 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3914 if (! (cm
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)) {
3915 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3919 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3922 cmsig
= mono_method_signature (cm
);
3923 imsig
= mono_method_signature (im
);
3924 if (!cmsig
|| !imsig
) {
3925 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not resolve the signature of a virtual method"));
3929 if (! mono_metadata_signature_equal (cmsig
, imsig
)) {
3930 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3931 TRACE_INTERFACE_VTABLE (print_method_signatures (im
, cm
));
3932 TRACE_INTERFACE_VTABLE (printf ("]"));
3935 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3936 /* CAS - SecurityAction.InheritanceDemand on interface */
3937 if (security_enabled
&& (im
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
)) {
3938 mono_secman_inheritancedemand_method (cm
, im
);
3941 if (mono_security_core_clr_enabled ())
3942 mono_security_core_clr_check_override (class, cm
, im
);
3944 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3945 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm
, im
, NULL
)) {
3946 char *body_name
= mono_method_full_name (cm
, TRUE
);
3947 char *decl_name
= mono_method_full_name (im
, TRUE
);
3948 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
));
3956 MonoClass
*ic
= im
->klass
;
3957 const char *ic_name_space
= ic
->name_space
;
3958 const char *ic_name
= ic
->name
;
3961 if (! require_newslot
) {
3962 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3965 if (cm
->klass
->rank
== 0) {
3966 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3969 cmsig
= mono_method_signature (cm
);
3970 imsig
= mono_method_signature (im
);
3971 if (!cmsig
|| !imsig
) {
3972 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not resolve the signature of a virtual method"));
3976 if (! mono_metadata_signature_equal (cmsig
, imsig
)) {
3977 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3978 TRACE_INTERFACE_VTABLE (print_method_signatures (im
, cm
));
3979 TRACE_INTERFACE_VTABLE (printf ("]"));
3982 if (mono_class_get_image (ic
) != mono_defaults
.corlib
) {
3983 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3986 if ((ic_name_space
== NULL
) || (strcmp (ic_name_space
, "System.Collections.Generic") != 0)) {
3987 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3990 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))) {
3991 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3995 subname
= strstr (cm
->name
, ic_name_space
);
3996 if (subname
!= cm
->name
) {
3997 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4000 subname
+= strlen (ic_name_space
);
4001 if (subname
[0] != '.') {
4002 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4006 if (strstr (subname
, ic_name
) != subname
) {
4007 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4010 subname
+= strlen (ic_name
);
4011 if (subname
[0] != '.') {
4012 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4016 if (strcmp (subname
, im
->name
) != 0) {
4017 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4021 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4022 /* CAS - SecurityAction.InheritanceDemand on interface */
4023 if (security_enabled
&& (im
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
)) {
4024 mono_secman_inheritancedemand_method (cm
, im
);
4027 if (mono_security_core_clr_enabled ())
4028 mono_security_core_clr_check_override (class, cm
, im
);
4030 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4031 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm
, im
, NULL
)) {
4032 char *body_name
= mono_method_full_name (cm
, TRUE
);
4033 char *decl_name
= mono_method_full_name (im
, TRUE
);
4034 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
));
4044 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4046 foreach_override (gpointer key
, gpointer value
, gpointer user_data
) {
4047 MonoMethod
*method
= key
;
4048 MonoMethod
*override
= value
;
4049 MonoClass
*method_class
= mono_method_get_class (method
);
4050 MonoClass
*override_class
= mono_method_get_class (override
);
4052 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4053 mono_class_get_namespace (method_class
), mono_class_get_name (method_class
), mono_method_get_name (method
),
4054 mono_class_get_namespace (override_class
), mono_class_get_name (override_class
), mono_method_get_name (override
));
4057 print_overrides (GHashTable
*override_map
, const char *message
) {
4059 printf ("Override map \"%s\" START:\n", message
);
4060 g_hash_table_foreach (override_map
, foreach_override
, NULL
);
4061 printf ("Override map \"%s\" END.\n", message
);
4063 printf ("Override map \"%s\" EMPTY.\n", message
);
4067 print_vtable_full (MonoClass
*class, MonoMethod
** vtable
, int size
, int first_non_interface_slot
, const char *message
, gboolean print_interfaces
) {
4068 char *full_name
= mono_type_full_name (&class->byval_arg
);
4072 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name
, message
, size
);
4074 if (print_interfaces
) {
4075 print_implemented_interfaces (class);
4076 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name
, size
);
4079 if (class->parent
) {
4080 parent_size
= class->parent
->vtable_size
;
4084 for (i
= 0; i
< size
; ++i
) {
4085 MonoMethod
*cm
= vtable
[i
];
4086 char *cm_name
= cm
? mono_method_full_name (cm
, TRUE
) : g_strdup ("nil");
4087 char newness
= (i
< parent_size
) ? 'O' : ((i
< first_non_interface_slot
) ? 'I' : 'N');
4089 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness
, i
, cm
? cm
->slot
: - 1, cm_name
, cm
);
4097 #if VERIFY_INTERFACE_VTABLE_CODE
4099 mono_method_try_get_vtable_index (MonoMethod
*method
)
4101 if (method
->is_inflated
&& (method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
4102 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
4103 if (imethod
->declaring
->is_generic
)
4104 return imethod
->declaring
->slot
;
4106 return method
->slot
;
4110 mono_class_verify_vtable (MonoClass
*class)
4113 char *full_name
= mono_type_full_name (&class->byval_arg
);
4115 printf ("*** Verifying VTable of class '%s' \n", full_name
);
4119 if (!class->methods
)
4122 for (i
= 0; i
< class->method
.count
; ++i
) {
4123 MonoMethod
*cm
= class->methods
[i
];
4126 if (!(cm
->flags
& METHOD_ATTRIBUTE_VIRTUAL
))
4130 full_name
= mono_method_full_name (cm
, TRUE
);
4132 slot
= mono_method_try_get_vtable_index (cm
);
4134 if (slot
>= class->vtable_size
) {
4135 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name
, slot
, class->vtable_size
);
4139 if (slot
>= 0 && class->vtable
[slot
] != cm
&& (class->vtable
[slot
])) {
4140 char *other_name
= class->vtable
[slot
] ? mono_method_full_name (class->vtable
[slot
], TRUE
) : g_strdup ("[null value]");
4141 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name
, slot
, other_name
);
4142 g_free (other_name
);
4145 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name
);
4152 print_unimplemented_interface_method_info (MonoClass
*class, MonoClass
*ic
, MonoMethod
*im
, int im_slot
, MonoMethod
**overrides
, int onum
) {
4154 char *method_signature
;
4157 for (index
= 0; index
< onum
; ++index
) {
4158 mono_trace_warning (MONO_TRACE_TYPE
, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot
, overrides
[index
*2+1]->name
,
4159 overrides
[index
*2+1]->slot
, overrides
[index
*2]->name
, overrides
[index
*2]->slot
);
4161 method_signature
= mono_signature_get_desc (mono_method_signature (im
), FALSE
);
4162 type_name
= mono_type_full_name (&class->byval_arg
);
4163 mono_trace_warning (MONO_TRACE_TYPE
, "no implementation for interface method %s::%s(%s) in class %s\n",
4164 mono_type_get_name (&ic
->byval_arg
), im
->name
, method_signature
, type_name
);
4165 g_free (method_signature
);
4167 mono_class_setup_methods (class);
4168 if (class->exception_type
) {
4169 char *name
= mono_type_get_full_name (class);
4170 mono_trace_warning (MONO_TRACE_TYPE
, "CLASS %s failed to resolve methods\n", name
);
4174 for (index
= 0; index
< class->method
.count
; ++index
) {
4175 MonoMethod
*cm
= class->methods
[index
];
4176 method_signature
= mono_signature_get_desc (mono_method_signature (cm
), TRUE
);
4178 mono_trace_warning (MONO_TRACE_TYPE
, "METHOD %s(%s)\n", cm
->name
, method_signature
);
4179 g_free (method_signature
);
4184 mono_method_get_method_definition (MonoMethod
*method
)
4186 while (method
->is_inflated
)
4187 method
= ((MonoMethodInflated
*)method
)->declaring
;
4192 verify_class_overrides (MonoClass
*class, MonoMethod
**overrides
, int onum
)
4196 for (i
= 0; i
< onum
; ++i
) {
4197 MonoMethod
*decl
= overrides
[i
* 2];
4198 MonoMethod
*body
= overrides
[i
* 2 + 1];
4200 if (mono_class_get_generic_type_definition (body
->klass
) != mono_class_get_generic_type_definition (class)) {
4201 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Method belongs to a different class than the declared one"));
4205 if (!(body
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) || (body
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
4206 if (body
->flags
& METHOD_ATTRIBUTE_STATIC
)
4207 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Method must not be static to override a base type"));
4209 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Method must be virtual to override a base type"));
4213 if (!(decl
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) || (decl
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
4214 if (body
->flags
& METHOD_ATTRIBUTE_STATIC
)
4215 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Cannot override a static method in a base type"));
4217 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Cannot override a non virtual method in a base type"));
4221 if (!mono_class_is_assignable_from_slow (decl
->klass
, class)) {
4222 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4226 body
= mono_method_get_method_definition (body
);
4227 decl
= mono_method_get_method_definition (decl
);
4229 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body
, decl
, NULL
)) {
4230 char *body_name
= mono_method_full_name (body
, TRUE
);
4231 char *decl_name
= mono_method_full_name (decl
, TRUE
);
4232 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
));
4242 mono_class_need_stelemref_method (MonoClass
*class)
4244 return class->rank
== 1 && MONO_TYPE_IS_REFERENCE (&class->element_class
->byval_arg
);
4248 * LOCKING: this is supposed to be called with the loader lock held.
4251 mono_class_setup_vtable_general (MonoClass
*class, MonoMethod
**overrides
, int onum
, GList
*in_setup
)
4255 MonoMethod
**vtable
;
4256 int i
, max_vtsize
= 0, max_iid
, cur_slot
= 0;
4257 GPtrArray
*ifaces
= NULL
;
4258 GHashTable
*override_map
= NULL
;
4259 gboolean security_enabled
= mono_security_enabled ();
4261 gpointer class_iter
;
4262 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4263 int first_non_interface_slot
;
4265 GSList
*virt_methods
= NULL
, *l
;
4266 int stelemref_slot
= 0;
4271 if (overrides
&& !verify_class_overrides (class, overrides
, onum
))
4274 ifaces
= mono_class_get_implemented_interfaces (class, &error
);
4275 if (!mono_error_ok (&error
)) {
4276 char *name
= mono_type_get_full_name (class);
4277 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
)));
4279 mono_error_cleanup (&error
);
4281 } else if (ifaces
) {
4282 for (i
= 0; i
< ifaces
->len
; i
++) {
4283 MonoClass
*ic
= g_ptr_array_index (ifaces
, i
);
4284 max_vtsize
+= ic
->method
.count
;
4286 g_ptr_array_free (ifaces
, TRUE
);
4290 if (class->parent
) {
4291 mono_class_init (class->parent
);
4292 mono_class_setup_vtable_full (class->parent
, in_setup
);
4294 if (class->parent
->exception_type
) {
4295 char *name
= mono_type_get_full_name (class->parent
);
4296 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Parent %s failed to load", name
));
4301 max_vtsize
+= class->parent
->vtable_size
;
4302 cur_slot
= class->parent
->vtable_size
;
4305 max_vtsize
+= class->method
.count
;
4307 /*Array have a slot for stelemref*/
4308 if (mono_class_need_stelemref_method (class)) {
4309 stelemref_slot
= cur_slot
;
4314 vtable
= alloca (sizeof (gpointer
) * max_vtsize
);
4315 memset (vtable
, 0, sizeof (gpointer
) * max_vtsize
);
4317 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4319 cur_slot
= setup_interface_offsets (class, cur_slot
, TRUE
);
4320 if (cur_slot
== -1) /*setup_interface_offsets fails the type.*/
4323 max_iid
= class->max_interface_id
;
4324 DEBUG_INTERFACE_VTABLE (first_non_interface_slot
= cur_slot
);
4326 /* Optimized version for generic instances */
4327 if (class->generic_class
) {
4329 MonoClass
*gklass
= class->generic_class
->container_class
;
4332 mono_class_setup_vtable_full (gklass
, in_setup
);
4333 if (gklass
->exception_type
!= MONO_EXCEPTION_NONE
) {
4334 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
4338 tmp
= mono_class_alloc0 (class, sizeof (gpointer
) * gklass
->vtable_size
);
4339 class->vtable_size
= gklass
->vtable_size
;
4340 for (i
= 0; i
< gklass
->vtable_size
; ++i
)
4341 if (gklass
->vtable
[i
]) {
4342 MonoMethod
*inflated
= mono_class_inflate_generic_method_full_checked (gklass
->vtable
[i
], class, mono_class_get_context (class), &error
);
4343 if (!mono_error_ok (&error
)) {
4344 char *err_msg
= g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error
));
4345 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
4347 mono_error_cleanup (&error
);
4351 tmp
[i
]->slot
= gklass
->vtable
[i
]->slot
;
4353 mono_memory_barrier ();
4354 class->vtable
= tmp
;
4356 /* Have to set method->slot for abstract virtual methods */
4357 if (class->methods
&& gklass
->methods
) {
4358 for (i
= 0; i
< class->method
.count
; ++i
)
4359 if (class->methods
[i
]->slot
== -1)
4360 class->methods
[i
]->slot
= gklass
->methods
[i
]->slot
;
4366 if (class->parent
&& class->parent
->vtable_size
) {
4367 MonoClass
*parent
= class->parent
;
4370 memcpy (vtable
, parent
->vtable
, sizeof (gpointer
) * parent
->vtable_size
);
4372 // Also inherit parent interface vtables, just as a starting point.
4373 // This is needed otherwise bug-77127.exe fails when the property methods
4374 // have different names in the iterface and the class, because for child
4375 // classes the ".override" information is not used anymore.
4376 for (i
= 0; i
< parent
->interface_offsets_count
; i
++) {
4377 MonoClass
*parent_interface
= parent
->interfaces_packed
[i
];
4378 int interface_offset
= mono_class_interface_offset (class, parent_interface
);
4379 /*FIXME this is now dead code as this condition will never hold true.
4380 Since interface offsets are inherited then the offset of an interface implemented
4381 by a parent will never be the out of it's vtable boundary.
4383 if (interface_offset
>= parent
->vtable_size
) {
4384 int parent_interface_offset
= mono_class_interface_offset (parent
, parent_interface
);
4387 mono_class_setup_methods (parent_interface
); /*FIXME Just kill this whole chunk of dead code*/
4388 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface
->name_space
, parent_interface
->name
));
4389 for (j
= 0; j
< parent_interface
->method
.count
&& !class->exception_type
; j
++) {
4390 vtable
[interface_offset
+ j
] = parent
->vtable
[parent_interface_offset
+ j
];
4391 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4392 parent_interface_offset
+ j
, parent_interface_offset
, j
,
4393 interface_offset
+ j
, interface_offset
, j
));
4400 /*Array have a slot for stelemref*/
4401 if (mono_class_need_stelemref_method (class)) {
4402 MonoMethod
*method
= mono_marshal_get_virtual_stelemref (class);
4404 method
->slot
= stelemref_slot
;
4406 g_assert (method
->slot
== stelemref_slot
);
4408 vtable
[stelemref_slot
] = method
;
4411 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable
, cur_slot
, first_non_interface_slot
, "AFTER INHERITING PARENT VTABLE", TRUE
));
4412 /* override interface methods */
4413 for (i
= 0; i
< onum
; i
++) {
4414 MonoMethod
*decl
= overrides
[i
*2];
4415 if (MONO_CLASS_IS_INTERFACE (decl
->klass
)) {
4417 dslot
= mono_method_get_vtable_slot (decl
);
4419 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
4423 dslot
+= mono_class_interface_offset (class, decl
->klass
);
4424 vtable
[dslot
] = overrides
[i
*2 + 1];
4425 vtable
[dslot
]->slot
= dslot
;
4427 override_map
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
4429 g_hash_table_insert (override_map
, overrides
[i
* 2], overrides
[i
* 2 + 1]);
4431 if (mono_security_core_clr_enabled ())
4432 mono_security_core_clr_check_override (class, vtable
[dslot
], decl
);
4435 TRACE_INTERFACE_VTABLE (print_overrides (override_map
, "AFTER OVERRIDING INTERFACE METHODS"));
4436 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable
, cur_slot
, first_non_interface_slot
, "AFTER OVERRIDING INTERFACE METHODS", FALSE
));
4439 * Create a list of virtual methods to avoid calling
4440 * mono_class_get_virtual_methods () which is slow because of the metadata
4444 gpointer iter
= NULL
;
4447 virt_methods
= NULL
;
4448 while ((cm
= mono_class_get_virtual_methods (class, &iter
))) {
4449 virt_methods
= g_slist_prepend (virt_methods
, cm
);
4451 if (class->exception_type
)
4455 // Loop on all implemented interfaces...
4456 for (i
= 0; i
< class->interface_offsets_count
; i
++) {
4457 MonoClass
*parent
= class->parent
;
4459 gboolean interface_is_explicitly_implemented_by_class
;
4462 ic
= class->interfaces_packed
[i
];
4463 ic_offset
= mono_class_interface_offset (class, ic
);
4465 mono_class_setup_methods (ic
);
4466 if (ic
->exception_type
)
4469 // Check if this interface is explicitly implemented (instead of just inherited)
4470 if (parent
!= NULL
) {
4471 int implemented_interfaces_index
;
4472 interface_is_explicitly_implemented_by_class
= FALSE
;
4473 for (implemented_interfaces_index
= 0; implemented_interfaces_index
< class->interface_count
; implemented_interfaces_index
++) {
4474 if (ic
== class->interfaces
[implemented_interfaces_index
]) {
4475 interface_is_explicitly_implemented_by_class
= TRUE
;
4480 interface_is_explicitly_implemented_by_class
= TRUE
;
4483 // Loop on all interface methods...
4484 for (im_index
= 0; im_index
< ic
->method
.count
; im_index
++) {
4485 MonoMethod
*im
= ic
->methods
[im_index
];
4486 int im_slot
= ic_offset
+ im
->slot
;
4487 MonoMethod
*override_im
= (override_map
!= NULL
) ? g_hash_table_lookup (override_map
, im
) : NULL
;
4489 if (im
->flags
& METHOD_ATTRIBUTE_STATIC
)
4492 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im
,1)));
4494 // If there is an explicit implementation, just use it right away,
4495 // otherwise look for a matching method
4496 if (override_im
== NULL
) {
4501 // First look for a suitable method among the class methods
4503 for (l
= virt_methods
; l
; l
= l
->next
) {
4505 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
)));
4506 if (check_interface_method_override (class, im
, cm
, TRUE
, interface_is_explicitly_implemented_by_class
, (vtable
[im_slot
] == NULL
), security_enabled
)) {
4507 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4508 vtable
[im_slot
] = cm
;
4509 /* Why do we need this? */
4514 TRACE_INTERFACE_VTABLE (printf ("\n"));
4515 if (class->exception_type
) /*Might be set by check_interface_method_override*/
4519 // If the slot is still empty, look in all the inherited virtual methods...
4520 if ((vtable
[im_slot
] == NULL
) && class->parent
!= NULL
) {
4521 MonoClass
*parent
= class->parent
;
4522 // Reverse order, so that last added methods are preferred
4523 for (cm_index
= parent
->vtable_size
- 1; cm_index
>= 0; cm_index
--) {
4524 MonoMethod
*cm
= parent
->vtable
[cm_index
];
4526 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
));
4527 if ((cm
!= NULL
) && check_interface_method_override (class, im
, cm
, FALSE
, FALSE
, TRUE
, security_enabled
)) {
4528 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4529 vtable
[im_slot
] = cm
;
4530 /* Why do we need this? */
4536 if (class->exception_type
) /*Might be set by check_interface_method_override*/
4538 TRACE_INTERFACE_VTABLE ((cm
!= NULL
) && printf ("\n"));
4542 g_assert (vtable
[im_slot
] == override_im
);
4547 // If the class is not abstract, check that all its interface slots are full.
4548 // The check is done here and not directly at the end of the loop above because
4549 // it can happen (for injected generic array interfaces) that the same slot is
4550 // processed multiple times (those interfaces have overlapping slots), and it
4551 // will not always be the first pass the one that fills the slot.
4552 if (! (class->flags
& TYPE_ATTRIBUTE_ABSTRACT
)) {
4553 for (i
= 0; i
< class->interface_offsets_count
; i
++) {
4557 ic
= class->interfaces_packed
[i
];
4558 ic_offset
= mono_class_interface_offset (class, ic
);
4560 for (im_index
= 0; im_index
< ic
->method
.count
; im_index
++) {
4561 MonoMethod
*im
= ic
->methods
[im_index
];
4562 int im_slot
= ic_offset
+ im
->slot
;
4564 if (im
->flags
& METHOD_ATTRIBUTE_STATIC
)
4567 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4568 im_slot
, ic
->name_space
, ic
->name
, im
->name
, (vtable
[im_slot
] == NULL
)));
4569 if (vtable
[im_slot
] == NULL
) {
4570 print_unimplemented_interface_method_info (class, ic
, im
, im_slot
, overrides
, onum
);
4577 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable
, cur_slot
, first_non_interface_slot
, "AFTER SETTING UP INTERFACE METHODS", FALSE
));
4579 for (l
= virt_methods
; l
; l
= l
->next
) {
4582 * If the method is REUSE_SLOT, we must check in the
4583 * base class for a method to override.
4585 if (!(cm
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)) {
4587 for (k
= class->parent
; k
; k
= k
->parent
) {
4592 while ((m1
= mono_class_get_virtual_methods (k
, &k_iter
))) {
4593 MonoMethodSignature
*cmsig
, *m1sig
;
4595 cmsig
= mono_method_signature (cm
);
4596 m1sig
= mono_method_signature (m1
);
4598 if (!cmsig
|| !m1sig
) {
4599 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
4603 if (!strcmp(cm
->name
, m1
->name
) &&
4604 mono_metadata_signature_equal (cmsig
, m1sig
)) {
4606 /* CAS - SecurityAction.InheritanceDemand */
4607 if (security_enabled
&& (m1
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
)) {
4608 mono_secman_inheritancedemand_method (cm
, m1
);
4611 if (mono_security_core_clr_enabled ())
4612 mono_security_core_clr_check_override (class, cm
, m1
);
4614 slot
= mono_method_get_vtable_slot (m1
);
4618 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm
, m1
, NULL
)) {
4619 char *body_name
= mono_method_full_name (cm
, TRUE
);
4620 char *decl_name
= mono_method_full_name (m1
, TRUE
);
4621 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
));
4627 g_assert (cm
->slot
< max_vtsize
);
4629 override_map
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
4630 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4631 mono_method_full_name (m1
, 1), m1
,
4632 mono_method_full_name (cm
, 1), cm
));
4633 g_hash_table_insert (override_map
, m1
, cm
);
4637 if (k
->exception_type
)
4647 /*Non final newslot methods must be given a non-interface vtable slot*/
4648 if ((cm
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
) && !(cm
->flags
& METHOD_ATTRIBUTE_FINAL
) && cm
->slot
>= 0)
4652 cm
->slot
= cur_slot
++;
4654 if (!(cm
->flags
& METHOD_ATTRIBUTE_ABSTRACT
))
4655 vtable
[cm
->slot
] = cm
;
4658 /* override non interface methods */
4659 for (i
= 0; i
< onum
; i
++) {
4660 MonoMethod
*decl
= overrides
[i
*2];
4661 if (!MONO_CLASS_IS_INTERFACE (decl
->klass
)) {
4662 g_assert (decl
->slot
!= -1);
4663 vtable
[decl
->slot
] = overrides
[i
*2 + 1];
4664 overrides
[i
* 2 + 1]->slot
= decl
->slot
;
4666 override_map
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
4667 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4668 mono_method_full_name (decl
, 1), decl
,
4669 mono_method_full_name (overrides
[i
* 2 + 1], 1), overrides
[i
* 2 + 1]));
4670 g_hash_table_insert (override_map
, decl
, overrides
[i
* 2 + 1]);
4672 if (mono_security_core_clr_enabled ())
4673 mono_security_core_clr_check_override (class, vtable
[decl
->slot
], decl
);
4678 * If a method occupies more than one place in the vtable, and it is
4679 * overriden, then change the other occurances too.
4684 for (i
= 0; i
< max_vtsize
; ++i
)
4686 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i
, mono_method_full_name (vtable
[i
], 1), vtable
[i
]));
4688 cm
= g_hash_table_lookup (override_map
, vtable
[i
]);
4693 g_hash_table_destroy (override_map
);
4694 override_map
= NULL
;
4697 g_slist_free (virt_methods
);
4698 virt_methods
= NULL
;
4700 /* Ensure that all vtable slots are filled with concrete instance methods */
4701 if (!(class->flags
& TYPE_ATTRIBUTE_ABSTRACT
)) {
4702 for (i
= 0; i
< cur_slot
; ++i
) {
4703 if (vtable
[i
] == NULL
|| (vtable
[i
]->flags
& (METHOD_ATTRIBUTE_ABSTRACT
| METHOD_ATTRIBUTE_STATIC
))) {
4704 char *type_name
= mono_type_get_full_name (class);
4705 char *method_name
= vtable
[i
] ? mono_method_full_name (vtable
[i
], TRUE
) : g_strdup ("none");
4706 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
));
4708 g_free (method_name
);
4714 if (class->generic_class
) {
4715 MonoClass
*gklass
= class->generic_class
->container_class
;
4717 mono_class_init (gklass
);
4719 class->vtable_size
= MAX (gklass
->vtable_size
, cur_slot
);
4721 /* Check that the vtable_size value computed in mono_class_init () is correct */
4722 if (class->vtable_size
)
4723 g_assert (cur_slot
== class->vtable_size
);
4724 class->vtable_size
= cur_slot
;
4727 /* Try to share the vtable with our parent. */
4728 if (class->parent
&& (class->parent
->vtable_size
== class->vtable_size
) && (memcmp (class->parent
->vtable
, vtable
, sizeof (gpointer
) * class->vtable_size
) == 0)) {
4729 mono_memory_barrier ();
4730 class->vtable
= class->parent
->vtable
;
4732 MonoMethod
**tmp
= mono_class_alloc0 (class, sizeof (gpointer
) * class->vtable_size
);
4733 memcpy (tmp
, vtable
, sizeof (gpointer
) * class->vtable_size
);
4734 mono_memory_barrier ();
4735 class->vtable
= tmp
;
4738 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable
, class->vtable_size
, first_non_interface_slot
, "FINALLY", FALSE
));
4739 if (mono_print_vtable
) {
4742 print_implemented_interfaces (class);
4744 for (i
= 0; i
<= max_iid
; i
++)
4745 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i
))
4748 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg
),
4749 class->vtable_size
, icount
);
4751 for (i
= 0; i
< cur_slot
; ++i
) {
4756 printf (" slot assigned: %03d, slot index: %03d %s\n", i
, cm
->slot
,
4757 mono_method_full_name (cm
, TRUE
));
4763 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space
,
4764 class->name
, max_iid
);
4766 for (i
= 0; i
< class->interface_count
; i
++) {
4767 ic
= class->interfaces
[i
];
4768 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4769 mono_class_interface_offset (class, ic
),
4770 count_virtual_methods (ic
), ic
->interface_id
, mono_type_full_name (&ic
->byval_arg
));
4773 for (k
= class->parent
; k
; k
= k
->parent
) {
4774 for (i
= 0; i
< k
->interface_count
; i
++) {
4775 ic
= k
->interfaces
[i
];
4776 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4777 mono_class_interface_offset (class, ic
),
4778 count_virtual_methods (ic
), ic
->interface_id
, mono_type_full_name (&ic
->byval_arg
));
4784 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4789 char *name
= mono_type_get_full_name (class);
4790 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("VTable setup of type %s failed", name
));
4793 g_hash_table_destroy (override_map
);
4795 g_slist_free (virt_methods
);
4800 * mono_method_get_vtable_slot:
4802 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4803 * LOCKING: Acquires the loader lock.
4805 * FIXME Use proper MonoError machinery here.
4808 mono_method_get_vtable_slot (MonoMethod
*method
)
4810 if (method
->slot
== -1) {
4811 mono_class_setup_vtable (method
->klass
);
4812 if (method
->klass
->exception_type
)
4814 if (method
->slot
== -1) {
4818 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4819 g_assert (method
->klass
->generic_class
);
4820 gklass
= method
->klass
->generic_class
->container_class
;
4821 mono_class_setup_methods (method
->klass
);
4822 g_assert (method
->klass
->methods
);
4823 for (i
= 0; i
< method
->klass
->method
.count
; ++i
) {
4824 if (method
->klass
->methods
[i
] == method
)
4827 g_assert (i
< method
->klass
->method
.count
);
4828 g_assert (gklass
->methods
);
4829 method
->slot
= gklass
->methods
[i
]->slot
;
4831 g_assert (method
->slot
!= -1);
4833 return method
->slot
;
4837 * mono_method_get_vtable_index:
4840 * Returns the index into the runtime vtable to access the method or,
4841 * in the case of a virtual generic method, the virtual generic method
4842 * thunk. Returns -1 on failure.
4844 * FIXME Use proper MonoError machinery here.
4847 mono_method_get_vtable_index (MonoMethod
*method
)
4849 if (method
->is_inflated
&& (method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
4850 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
4851 if (imethod
->declaring
->is_generic
)
4852 return mono_method_get_vtable_slot (imethod
->declaring
);
4854 return mono_method_get_vtable_slot (method
);
4857 static MonoMethod
*default_ghc
= NULL
;
4858 static MonoMethod
*default_finalize
= NULL
;
4859 static int finalize_slot
= -1;
4860 static int ghc_slot
= -1;
4863 initialize_object_slots (MonoClass
*class)
4868 if (class == mono_defaults
.object_class
) {
4869 mono_class_setup_vtable (class);
4870 for (i
= 0; i
< class->vtable_size
; ++i
) {
4871 MonoMethod
*cm
= class->vtable
[i
];
4873 if (!strcmp (cm
->name
, "GetHashCode"))
4875 else if (!strcmp (cm
->name
, "Finalize"))
4879 g_assert (ghc_slot
> 0);
4880 default_ghc
= class->vtable
[ghc_slot
];
4882 g_assert (finalize_slot
> 0);
4883 default_finalize
= class->vtable
[finalize_slot
];
4888 MonoMethod
*array_method
;
4890 } GenericArrayMethodInfo
;
4892 static int generic_array_method_num
= 0;
4893 static GenericArrayMethodInfo
*generic_array_method_info
= NULL
;
4896 generic_array_methods (MonoClass
*class)
4898 int i
, count_generic
= 0;
4899 GList
*list
= NULL
, *tmp
;
4900 if (generic_array_method_num
)
4901 return generic_array_method_num
;
4902 mono_class_setup_methods (class->parent
); /*This is setting up System.Array*/
4903 g_assert (!class->parent
->exception_type
); /*So hitting this assert is a huge problem*/
4904 for (i
= 0; i
< class->parent
->method
.count
; i
++) {
4905 MonoMethod
*m
= class->parent
->methods
[i
];
4906 if (!strncmp (m
->name
, "InternalArray__", 15)) {
4908 list
= g_list_prepend (list
, m
);
4911 list
= g_list_reverse (list
);
4912 generic_array_method_info
= mono_image_alloc (mono_defaults
.corlib
, sizeof (GenericArrayMethodInfo
) * count_generic
);
4914 for (tmp
= list
; tmp
; tmp
= tmp
->next
) {
4915 const char *mname
, *iname
;
4917 MonoMethod
*m
= tmp
->data
;
4918 const char *ireadonlylist_prefix
= "InternalArray__IReadOnlyList_";
4919 const char *ireadonlycollection_prefix
= "InternalArray__IReadOnlyCollection_";
4921 generic_array_method_info
[i
].array_method
= m
;
4922 if (!strncmp (m
->name
, "InternalArray__ICollection_", 27)) {
4923 iname
= "System.Collections.Generic.ICollection`1.";
4924 mname
= m
->name
+ 27;
4925 } else if (!strncmp (m
->name
, "InternalArray__IEnumerable_", 27)) {
4926 iname
= "System.Collections.Generic.IEnumerable`1.";
4927 mname
= m
->name
+ 27;
4928 } else if (!strncmp (m
->name
, ireadonlylist_prefix
, strlen (ireadonlylist_prefix
))) {
4929 iname
= "System.Collections.Generic.IReadOnlyList`1.";
4930 mname
= m
->name
+ strlen (ireadonlylist_prefix
);
4931 } else if (!strncmp (m
->name
, ireadonlycollection_prefix
, strlen (ireadonlycollection_prefix
))) {
4932 iname
= "System.Collections.Generic.IReadOnlyCollection`1.";
4933 mname
= m
->name
+ strlen (ireadonlycollection_prefix
);
4934 } else if (!strncmp (m
->name
, "InternalArray__", 15)) {
4935 iname
= "System.Collections.Generic.IList`1.";
4936 mname
= m
->name
+ 15;
4938 g_assert_not_reached ();
4941 name
= mono_image_alloc (mono_defaults
.corlib
, strlen (iname
) + strlen (mname
) + 1);
4942 strcpy (name
, iname
);
4943 strcpy (name
+ strlen (iname
), mname
);
4944 generic_array_method_info
[i
].name
= name
;
4947 /*g_print ("array generic methods: %d\n", count_generic);*/
4949 generic_array_method_num
= count_generic
;
4951 return generic_array_method_num
;
4955 setup_generic_array_ifaces (MonoClass
*class, MonoClass
*iface
, MonoMethod
**methods
, int pos
)
4957 MonoGenericContext tmp_context
;
4960 tmp_context
.class_inst
= NULL
;
4961 tmp_context
.method_inst
= iface
->generic_class
->context
.class_inst
;
4962 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4964 for (i
= 0; i
< generic_array_method_num
; i
++) {
4966 MonoMethod
*m
= generic_array_method_info
[i
].array_method
;
4967 MonoMethod
*inflated
;
4969 inflated
= mono_class_inflate_generic_method_checked (m
, &tmp_context
, &error
);
4970 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
4971 methods
[pos
++] = mono_marshal_get_generic_array_helper (class, iface
, generic_array_method_info
[i
].name
, inflated
);
4976 concat_two_strings_with_zero (MonoImage
*image
, const char *s1
, const char *s2
)
4978 int null_length
= strlen ("(null)");
4979 int len
= (s1
? strlen (s1
) : null_length
) + (s2
? strlen (s2
) : null_length
) + 2;
4980 char *s
= mono_image_alloc (image
, len
);
4983 result
= g_snprintf (s
, len
, "%s%c%s", s1
? s1
: "(null)", '\0', s2
? s2
: "(null)");
4984 g_assert (result
== len
- 1);
4990 set_failure_from_loader_error (MonoClass
*class, MonoLoaderError
*error
)
4992 gpointer exception_data
= NULL
;
4994 switch (error
->exception_type
) {
4995 case MONO_EXCEPTION_TYPE_LOAD
:
4996 exception_data
= concat_two_strings_with_zero (class->image
, error
->class_name
, error
->assembly_name
);
4999 case MONO_EXCEPTION_MISSING_METHOD
:
5000 exception_data
= concat_two_strings_with_zero (class->image
, error
->class_name
, error
->member_name
);
5003 case MONO_EXCEPTION_MISSING_FIELD
: {
5004 const char *name_space
= error
->klass
->name_space
? error
->klass
->name_space
: NULL
;
5005 const char *class_name
;
5008 class_name
= g_strdup_printf ("%s.%s", name_space
, error
->klass
->name
);
5010 class_name
= error
->klass
->name
;
5012 exception_data
= concat_two_strings_with_zero (class->image
, class_name
, error
->member_name
);
5015 g_free ((void*)class_name
);
5019 case MONO_EXCEPTION_FILE_NOT_FOUND
: {
5022 if (error
->ref_only
)
5023 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.";
5025 msg
= "Could not load file or assembly '%s' or one of its dependencies.";
5027 exception_data
= concat_two_strings_with_zero (class->image
, msg
, error
->assembly_name
);
5031 case MONO_EXCEPTION_BAD_IMAGE
:
5032 exception_data
= error
->msg
;
5036 g_assert_not_reached ();
5039 mono_class_set_failure (class, error
->exception_type
, exception_data
);
5044 * @class: the class to initialize
5046 * Compute the instance_size, class_size and other infos that cannot be
5047 * computed at mono_class_get() time. Also compute vtable_size if possible.
5048 * Returns TRUE on success or FALSE if there was a problem in loading
5049 * the type (incorrect assemblies, missing assemblies, methods, etc).
5051 * LOCKING: Acquires the loader lock.
5054 mono_class_init (MonoClass
*class)
5057 MonoCachedClassInfo cached_info
;
5058 gboolean has_cached_info
;
5062 /* Double-checking locking pattern */
5063 if (class->inited
|| class->exception_type
)
5064 return class->exception_type
== MONO_EXCEPTION_NONE
;
5066 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5068 /* We do everything inside the lock to prevent races */
5069 mono_loader_lock ();
5071 if (class->inited
|| class->exception_type
) {
5072 mono_loader_unlock ();
5073 /* Somebody might have gotten in before us */
5074 return class->exception_type
== MONO_EXCEPTION_NONE
;
5077 if (class->init_pending
) {
5078 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Recursive type definition detected"));
5082 class->init_pending
= 1;
5084 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5085 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, concat_two_strings_with_zero (class->image
, class->name
, class->image
->assembly_name
));
5090 if (class->byval_arg
.type
== MONO_TYPE_ARRAY
|| class->byval_arg
.type
== MONO_TYPE_SZARRAY
) {
5091 MonoClass
*element_class
= class->element_class
;
5092 if (!element_class
->inited
)
5093 mono_class_init (element_class
);
5094 if (element_class
->exception_type
!= MONO_EXCEPTION_NONE
) {
5095 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5100 /* CAS - SecurityAction.InheritanceDemand */
5101 if (mono_security_enabled () && class->parent
&& (class->parent
->flags
& TYPE_ATTRIBUTE_HAS_SECURITY
)) {
5102 mono_secman_inheritancedemand_class (class, class->parent
);
5105 mono_stats
.initialized_class_count
++;
5107 if (class->generic_class
&& !class->generic_class
->is_dynamic
) {
5108 MonoClass
*gklass
= class->generic_class
->container_class
;
5110 mono_stats
.generic_class_count
++;
5112 class->method
= gklass
->method
;
5113 class->field
= gklass
->field
;
5115 mono_class_init (gklass
);
5116 // FIXME: Why is this needed ?
5117 if (!gklass
->exception_type
)
5118 mono_class_setup_methods (gklass
);
5119 if (gklass
->exception_type
) {
5120 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Generic Type Defintion failed to init"));
5124 if (MONO_CLASS_IS_INTERFACE (class))
5125 class->interface_id
= mono_get_unique_iid (class);
5128 if (class->parent
&& !class->parent
->inited
)
5129 mono_class_init (class->parent
);
5131 has_cached_info
= mono_class_get_cached_class_info (class, &cached_info
);
5133 if (class->generic_class
|| image_is_dynamic (class->image
) || !class->type_token
|| (has_cached_info
&& !cached_info
.has_nested_classes
))
5134 class->nested_classes_inited
= TRUE
;
5137 * Computes the size used by the fields, and their locations
5139 if (has_cached_info
) {
5140 class->instance_size
= cached_info
.instance_size
;
5141 class->sizes
.class_size
= cached_info
.class_size
;
5142 class->packing_size
= cached_info
.packing_size
;
5143 class->min_align
= cached_info
.min_align
;
5144 class->blittable
= cached_info
.blittable
;
5145 class->has_references
= cached_info
.has_references
;
5146 class->has_static_refs
= cached_info
.has_static_refs
;
5147 class->no_special_static_fields
= cached_info
.no_special_static_fields
;
5150 if (!class->size_inited
){
5151 mono_class_setup_fields (class);
5152 if (class->exception_type
|| mono_loader_get_last_error ())
5156 /* Initialize arrays */
5158 class->method
.count
= 3 + (class->rank
> 1? 2: 1);
5160 if (class->interface_count
) {
5161 int count_generic
= generic_array_methods (class);
5162 class->method
.count
+= class->interface_count
* count_generic
;
5166 mono_class_setup_supertypes (class);
5169 initialize_object_slots (class);
5172 * Initialize the rest of the data without creating a generic vtable if possible.
5173 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5174 * also avoid computing a generic vtable.
5176 if (has_cached_info
) {
5178 class->vtable_size
= cached_info
.vtable_size
;
5179 class->has_finalize
= cached_info
.has_finalize
;
5180 class->has_finalize_inited
= TRUE
;
5181 class->ghcimpl
= cached_info
.ghcimpl
;
5182 class->has_cctor
= cached_info
.has_cctor
;
5183 } else if (class->rank
== 1 && class->byval_arg
.type
== MONO_TYPE_SZARRAY
) {
5184 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5185 * The first slot if for array with.
5187 static int szarray_vtable_size
[2] = { 0 };
5189 int slot
= MONO_TYPE_IS_REFERENCE (&class->element_class
->byval_arg
) ? 0 : 1;
5192 if (!szarray_vtable_size
[slot
]) {
5193 mono_class_setup_vtable (class);
5194 szarray_vtable_size
[slot
] = class->vtable_size
;
5196 class->vtable_size
= szarray_vtable_size
[slot
];
5198 } else if (class->generic_class
&& !MONO_CLASS_IS_INTERFACE (class)) {
5199 MonoClass
*gklass
= class->generic_class
->container_class
;
5201 /* Generic instance case */
5202 class->ghcimpl
= gklass
->ghcimpl
;
5203 class->has_cctor
= gklass
->has_cctor
;
5205 mono_class_setup_vtable (gklass
);
5206 if (gklass
->exception_type
) {
5207 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5211 class->vtable_size
= gklass
->vtable_size
;
5215 /* ghcimpl is not currently used
5217 if (class->parent) {
5218 MonoMethod *cmethod = class->vtable [ghc_slot];
5219 if (cmethod->is_inflated)
5220 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5221 if (cmethod == default_ghc) {
5227 /* C# doesn't allow interfaces to have cctors */
5228 if (!MONO_CLASS_IS_INTERFACE (class) || class->image
!= mono_defaults
.corlib
) {
5229 MonoMethod
*cmethod
= NULL
;
5231 if (class->type_token
) {
5232 cmethod
= find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME
);
5233 /* The find_method function ignores the 'flags' argument */
5234 if (cmethod
&& (cmethod
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
))
5235 class->has_cctor
= 1;
5237 mono_class_setup_methods (class);
5238 if (class->exception_type
)
5241 for (i
= 0; i
< class->method
.count
; ++i
) {
5242 MonoMethod
*method
= class->methods
[i
];
5243 if ((method
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
) &&
5244 (strcmp (".cctor", method
->name
) == 0)) {
5245 class->has_cctor
= 1;
5253 if (class->parent
) {
5254 int first_iface_slot
;
5255 /* This will compute class->parent->vtable_size for some classes */
5256 mono_class_init (class->parent
);
5257 if (class->parent
->exception_type
) {
5258 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5261 if (mono_loader_get_last_error ())
5263 if (!class->parent
->vtable_size
) {
5264 /* FIXME: Get rid of this somehow */
5265 mono_class_setup_vtable (class->parent
);
5266 if (class->parent
->exception_type
) {
5267 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5270 if (mono_loader_get_last_error ())
5273 first_iface_slot
= class->parent
->vtable_size
;
5274 if (mono_class_need_stelemref_method (class))
5276 setup_interface_offsets (class, first_iface_slot
, TRUE
);
5278 setup_interface_offsets (class, 0, TRUE
);
5281 if (mono_security_core_clr_enabled ())
5282 mono_security_core_clr_check_inheritance (class);
5284 if (mono_loader_get_last_error ()) {
5285 if (class->exception_type
== MONO_EXCEPTION_NONE
) {
5286 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5288 mono_loader_clear_error ();
5291 if (class->generic_class
&& !mono_verifier_class_is_valid_generic_instantiation (class))
5292 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Invalid generic instantiation"));
5297 /* Because of the double-checking locking pattern */
5298 mono_memory_barrier ();
5300 class->init_pending
= 0;
5302 mono_loader_unlock ();
5304 return class->exception_type
== MONO_EXCEPTION_NONE
;
5308 * mono_class_has_finalizer:
5310 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5314 mono_class_has_finalizer (MonoClass
*klass
)
5316 MonoClass
*class = klass
;
5317 gboolean has_finalize
= FALSE
;
5319 if (klass
->has_finalize_inited
)
5320 return klass
->has_finalize
;
5322 /* Interfaces and valuetypes are not supposed to have finalizers */
5323 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype
)) {
5324 MonoMethod
*cmethod
= NULL
;
5326 if (class->rank
== 1 && class->byval_arg
.type
== MONO_TYPE_SZARRAY
) {
5327 } else if (class->generic_class
) {
5328 MonoClass
*gklass
= class->generic_class
->container_class
;
5330 has_finalize
= mono_class_has_finalizer (gklass
);
5331 } else if (class->parent
&& class->parent
->has_finalize
) {
5332 has_finalize
= TRUE
;
5334 if (class->parent
) {
5336 * Can't search in metadata for a method named Finalize, because that
5337 * ignores overrides.
5339 mono_class_setup_vtable (class);
5340 if (class->exception_type
|| mono_loader_get_last_error ())
5343 cmethod
= class->vtable
[finalize_slot
];
5347 g_assert (class->vtable_size
> finalize_slot
);
5349 if (class->parent
) {
5350 if (cmethod
->is_inflated
)
5351 cmethod
= ((MonoMethodInflated
*)cmethod
)->declaring
;
5352 if (cmethod
!= default_finalize
)
5353 has_finalize
= TRUE
;
5359 mono_image_lock (klass
->image
);
5361 if (!klass
->has_finalize_inited
) {
5362 klass
->has_finalize
= has_finalize
? 1 : 0;
5364 mono_memory_barrier ();
5365 klass
->has_finalize_inited
= TRUE
;
5368 mono_image_unlock (klass
->image
);
5370 return klass
->has_finalize
;
5374 mono_is_corlib_image (MonoImage
*image
)
5376 /* FIXME: allow the dynamic case for our compilers and with full trust */
5377 if (image_is_dynamic (image
))
5378 return image
->assembly
&& !strcmp (image
->assembly
->aname
.name
, "mscorlib");
5380 return image
== mono_defaults
.corlib
;
5384 * LOCKING: this assumes the loader lock is held
5387 mono_class_setup_mono_type (MonoClass
*class)
5389 const char *name
= class->name
;
5390 const char *nspace
= class->name_space
;
5391 gboolean is_corlib
= mono_is_corlib_image (class->image
);
5393 class->this_arg
.byref
= 1;
5394 class->this_arg
.data
.klass
= class;
5395 class->this_arg
.type
= MONO_TYPE_CLASS
;
5396 class->byval_arg
.data
.klass
= class;
5397 class->byval_arg
.type
= MONO_TYPE_CLASS
;
5399 if (is_corlib
&& !strcmp (nspace
, "System")) {
5400 if (!strcmp (name
, "ValueType")) {
5402 * do not set the valuetype bit for System.ValueType.
5403 * class->valuetype = 1;
5405 class->blittable
= TRUE
;
5406 } else if (!strcmp (name
, "Enum")) {
5408 * do not set the valuetype bit for System.Enum.
5409 * class->valuetype = 1;
5411 class->valuetype
= 0;
5412 class->enumtype
= 0;
5413 } else if (!strcmp (name
, "Object")) {
5414 class->this_arg
.type
= class->byval_arg
.type
= MONO_TYPE_OBJECT
;
5415 } else if (!strcmp (name
, "String")) {
5416 class->this_arg
.type
= class->byval_arg
.type
= MONO_TYPE_STRING
;
5417 } else if (!strcmp (name
, "TypedReference")) {
5418 class->this_arg
.type
= class->byval_arg
.type
= MONO_TYPE_TYPEDBYREF
;
5422 if (class->valuetype
) {
5423 int t
= MONO_TYPE_VALUETYPE
;
5425 if (is_corlib
&& !strcmp (nspace
, "System")) {
5428 if (!strcmp (name
, "Boolean")) {
5429 t
= MONO_TYPE_BOOLEAN
;
5430 } else if (!strcmp(name
, "Byte")) {
5432 class->blittable
= TRUE
;
5436 if (!strcmp (name
, "Char")) {
5441 if (!strcmp (name
, "Double")) {
5443 class->blittable
= TRUE
;
5447 if (!strcmp (name
, "Int32")) {
5449 class->blittable
= TRUE
;
5450 } else if (!strcmp(name
, "Int16")) {
5452 class->blittable
= TRUE
;
5453 } else if (!strcmp(name
, "Int64")) {
5455 class->blittable
= TRUE
;
5456 } else if (!strcmp(name
, "IntPtr")) {
5458 class->blittable
= TRUE
;
5462 if (!strcmp (name
, "Single")) {
5464 class->blittable
= TRUE
;
5465 } else if (!strcmp(name
, "SByte")) {
5467 class->blittable
= TRUE
;
5471 if (!strcmp (name
, "UInt32")) {
5473 class->blittable
= TRUE
;
5474 } else if (!strcmp(name
, "UInt16")) {
5476 class->blittable
= TRUE
;
5477 } else if (!strcmp(name
, "UInt64")) {
5479 class->blittable
= TRUE
;
5480 } else if (!strcmp(name
, "UIntPtr")) {
5482 class->blittable
= TRUE
;
5486 if (!strcmp (name
, "TypedReference")) {
5487 t
= MONO_TYPE_TYPEDBYREF
;
5488 class->blittable
= TRUE
;
5492 if (!strcmp (name
, "Void")) {
5500 class->this_arg
.type
= class->byval_arg
.type
= t
;
5503 if (MONO_CLASS_IS_INTERFACE (class))
5504 class->interface_id
= mono_get_unique_iid (class);
5510 * COM initialization is delayed until needed.
5511 * However when a [ComImport] attribute is present on a type it will trigger
5512 * the initialization. This is not a problem unless the BCL being executed
5513 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5516 init_com_from_comimport (MonoClass
*class)
5518 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5519 if (mono_security_core_clr_enabled ()) {
5520 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5521 if (!mono_security_core_clr_determine_platform_image (class->image
)) {
5522 /* but it can not be made available for application (i.e. user code) since all COM calls
5523 * are considered native calls. In this case we fail with a TypeLoadException (just like
5524 * Silverlight 2 does */
5525 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5530 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5532 #endif /*DISABLE_COM*/
5535 * LOCKING: this assumes the loader lock is held
5538 mono_class_setup_parent (MonoClass
*class, MonoClass
*parent
)
5540 gboolean system_namespace
;
5541 gboolean is_corlib
= mono_is_corlib_image (class->image
);
5543 system_namespace
= !strcmp (class->name_space
, "System") && is_corlib
;
5545 /* if root of the hierarchy */
5546 if (system_namespace
&& !strcmp (class->name
, "Object")) {
5547 class->parent
= NULL
;
5548 class->instance_size
= sizeof (MonoObject
);
5551 if (!strcmp (class->name
, "<Module>")) {
5552 class->parent
= NULL
;
5553 class->instance_size
= 0;
5557 if (!MONO_CLASS_IS_INTERFACE (class)) {
5558 /* Imported COM Objects always derive from __ComObject. */
5560 if (MONO_CLASS_IS_IMPORT (class)) {
5561 init_com_from_comimport (class);
5562 if (parent
== mono_defaults
.object_class
)
5563 parent
= mono_class_get_com_object_class ();
5567 /* set the parent to something useful and safe, but mark the type as broken */
5568 parent
= mono_defaults
.object_class
;
5569 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5572 class->parent
= parent
;
5574 if (parent
->generic_class
&& !parent
->name
) {
5576 * If the parent is a generic instance, we may get
5577 * called before it is fully initialized, especially
5578 * before it has its name.
5583 #ifndef DISABLE_REMOTING
5584 class->marshalbyref
= parent
->marshalbyref
;
5585 class->contextbound
= parent
->contextbound
;
5588 class->delegate
= parent
->delegate
;
5590 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent
))
5591 mono_class_set_is_com_object (class);
5593 if (system_namespace
) {
5594 #ifndef DISABLE_REMOTING
5595 if (*class->name
== 'M' && !strcmp (class->name
, "MarshalByRefObject"))
5596 class->marshalbyref
= 1;
5598 if (*class->name
== 'C' && !strcmp (class->name
, "ContextBoundObject"))
5599 class->contextbound
= 1;
5601 if (*class->name
== 'D' && !strcmp (class->name
, "Delegate"))
5602 class->delegate
= 1;
5605 if (class->parent
->enumtype
|| (mono_is_corlib_image (class->parent
->image
) && (strcmp (class->parent
->name
, "ValueType") == 0) &&
5606 (strcmp (class->parent
->name_space
, "System") == 0)))
5607 class->valuetype
= 1;
5608 if (mono_is_corlib_image (class->parent
->image
) && ((strcmp (class->parent
->name
, "Enum") == 0) && (strcmp (class->parent
->name_space
, "System") == 0))) {
5609 class->valuetype
= class->enumtype
= 1;
5611 /*class->enumtype = class->parent->enumtype; */
5613 /* initialize com types if COM interfaces are present */
5615 if (MONO_CLASS_IS_IMPORT (class))
5616 init_com_from_comimport (class);
5618 class->parent
= NULL
;
5624 * mono_class_setup_supertypes:
5627 * Build the data structure needed to make fast type checks work.
5628 * This currently sets two fields in @class:
5629 * - idepth: distance between @class and System.Object in the type
5631 * - supertypes: array of classes: each element has a class in the hierarchy
5632 * starting from @class up to System.Object
5634 * LOCKING: This function is atomic, in case of contention we waste memory.
5637 mono_class_setup_supertypes (MonoClass
*class)
5640 MonoClass
**supertypes
;
5642 mono_atomic_load_acquire (supertypes
, void*, &class->supertypes
);
5646 if (class->parent
&& !class->parent
->supertypes
)
5647 mono_class_setup_supertypes (class->parent
);
5649 class->idepth
= class->parent
->idepth
+ 1;
5653 ms
= MAX (MONO_DEFAULT_SUPERTABLE_SIZE
, class->idepth
);
5654 supertypes
= mono_class_alloc0 (class, sizeof (MonoClass
*) * ms
);
5656 if (class->parent
) {
5657 supertypes
[class->idepth
- 1] = class;
5658 memcpy (supertypes
, class->parent
->supertypes
, class->parent
->idepth
* sizeof (gpointer
));
5660 supertypes
[0] = class;
5663 mono_atomic_store_release (&class->supertypes
, supertypes
);
5667 fix_gclass_incomplete_instantiation (MonoClass
*gclass
, void *user_data
)
5669 MonoClass
*gtd
= (MonoClass
*)user_data
;
5670 /* Only try to fix generic instances of @gtd */
5671 if (gclass
->generic_class
->container_class
!= gtd
)
5674 /* Check if the generic instance has no parent. */
5675 if (gtd
->parent
&& !gclass
->parent
)
5676 mono_generic_class_setup_parent (gclass
, gtd
);
5682 mono_class_set_failure_and_error (MonoClass
*class, MonoError
*error
, const char *msg
)
5684 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup (msg
));
5685 mono_error_set_type_load_class (error
, class, msg
);
5689 mono_class_set_failure_from_loader_error (MonoClass
*class, MonoError
*error
, char *msg
)
5691 MonoLoaderError
*lerror
= mono_loader_get_last_error ();
5694 set_failure_from_loader_error (class, lerror
);
5695 mono_error_set_from_loader_error (error
);
5699 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, msg
);
5700 mono_error_set_type_load_class (error
, class, msg
);
5705 * mono_class_create_from_typedef:
5706 * @image: image where the token is valid
5707 * @type_token: typedef token
5708 * @error: used to return any error found while creating the type
5710 * Create the MonoClass* representing the specified type token.
5711 * @type_token must be a TypeDef token.
5713 * FIXME: don't return NULL on failure, just the the caller figure it out.
5716 mono_class_create_from_typedef (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
5718 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
5719 MonoClass
*class, *parent
= NULL
;
5720 guint32 cols
[MONO_TYPEDEF_SIZE
];
5721 guint32 cols_next
[MONO_TYPEDEF_SIZE
];
5722 guint tidx
= mono_metadata_token_index (type_token
);
5723 MonoGenericContext
*context
= NULL
;
5724 const char *name
, *nspace
;
5726 MonoClass
**interfaces
;
5727 guint32 field_last
, method_last
;
5728 guint32 nesting_tokeen
;
5730 mono_error_init (error
);
5732 if (mono_metadata_token_table (type_token
) != MONO_TABLE_TYPEDEF
|| tidx
> tt
->rows
) {
5733 mono_error_set_bad_image (error
, image
, "Invalid typedef token %x", type_token
);
5734 g_assert (!mono_loader_get_last_error ());
5738 mono_loader_lock ();
5740 if ((class = mono_internal_hash_table_lookup (&image
->class_cache
, GUINT_TO_POINTER (type_token
)))) {
5741 mono_loader_unlock ();
5742 g_assert (!mono_loader_get_last_error ());
5746 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
5748 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
5749 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
5751 class = mono_image_alloc0 (image
, sizeof (MonoClass
));
5754 class->name_space
= nspace
;
5756 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD
);
5758 class->image
= image
;
5759 class->type_token
= type_token
;
5760 class->flags
= cols
[MONO_TYPEDEF_FLAGS
];
5762 mono_internal_hash_table_insert (&image
->class_cache
, GUINT_TO_POINTER (type_token
), class);
5764 classes_size
+= sizeof (MonoClass
);
5767 * Check whether we're a generic type definition.
5769 class->generic_container
= mono_metadata_load_generic_params (image
, class->type_token
, NULL
);
5770 if (class->generic_container
) {
5771 class->is_generic
= 1;
5772 class->generic_container
->owner
.klass
= class;
5773 context
= &class->generic_container
->context
;
5776 if (class->generic_container
)
5777 enable_gclass_recording ();
5779 if (cols
[MONO_TYPEDEF_EXTENDS
]) {
5781 guint32 parent_token
= mono_metadata_token_from_dor (cols
[MONO_TYPEDEF_EXTENDS
]);
5783 if (mono_metadata_token_table (parent_token
) == MONO_TABLE_TYPESPEC
) {
5784 /*WARNING: this must satisfy mono_metadata_type_hash*/
5785 class->this_arg
.byref
= 1;
5786 class->this_arg
.data
.klass
= class;
5787 class->this_arg
.type
= MONO_TYPE_CLASS
;
5788 class->byval_arg
.data
.klass
= class;
5789 class->byval_arg
.type
= MONO_TYPE_CLASS
;
5791 parent
= mono_class_get_checked (image
, parent_token
, error
);
5792 if (parent
&& context
) /* Always inflate */
5793 parent
= mono_class_inflate_generic_class_checked (parent
, context
, error
);
5795 if (parent
== NULL
) {
5796 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup (mono_error_get_message (error
)));
5797 goto parent_failure
;
5800 for (tmp
= parent
; tmp
; tmp
= tmp
->parent
) {
5802 mono_class_set_failure_and_error (class, error
, "Cycle found while resolving parent");
5803 goto parent_failure
;
5805 if (class->generic_container
&& tmp
->generic_class
&& tmp
->generic_class
->container_class
== class) {
5806 mono_class_set_failure_and_error (class, error
, "Parent extends generic instance of this type");
5807 goto parent_failure
;
5812 mono_class_setup_parent (class, parent
);
5814 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5815 mono_class_setup_mono_type (class);
5817 if (class->generic_container
)
5818 disable_gclass_recording (fix_gclass_incomplete_instantiation
, class);
5821 * This might access class->byval_arg for recursion generated by generic constraints,
5822 * so it has to come after setup_mono_type ().
5824 if ((nesting_tokeen
= mono_metadata_nested_in_typedef (image
, type_token
))) {
5825 class->nested_in
= mono_class_create_from_typedef (image
, nesting_tokeen
, error
);
5826 if (!mono_error_ok (error
)) {
5827 /*FIXME implement a mono_class_set_failure_from_mono_error */
5828 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup (mono_error_get_message (error
)));
5829 mono_loader_unlock ();
5830 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5831 g_assert (!mono_loader_get_last_error ());
5836 if ((class->flags
& TYPE_ATTRIBUTE_STRING_FORMAT_MASK
) == TYPE_ATTRIBUTE_UNICODE_CLASS
)
5840 if ((class->flags
& TYPE_ATTRIBUTE_STRING_FORMAT_MASK
) == TYPE_ATTRIBUTE_AUTO_CLASS
)
5844 class->cast_class
= class->element_class
= class;
5846 if (!class->enumtype
) {
5847 if (!mono_metadata_interfaces_from_typedef_full (
5848 image
, type_token
, &interfaces
, &icount
, FALSE
, context
, error
)){
5850 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup (mono_error_get_message (error
)));
5851 mono_loader_unlock ();
5852 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5856 class->interfaces
= interfaces
;
5857 class->interface_count
= icount
;
5858 class->interfaces_inited
= 1;
5861 /*g_print ("Load class %s\n", name);*/
5864 * Compute the field and method lists
5866 class->field
.first
= cols
[MONO_TYPEDEF_FIELD_LIST
] - 1;
5867 class->method
.first
= cols
[MONO_TYPEDEF_METHOD_LIST
] - 1;
5869 if (tt
->rows
> tidx
){
5870 mono_metadata_decode_row (tt
, tidx
, cols_next
, MONO_TYPEDEF_SIZE
);
5871 field_last
= cols_next
[MONO_TYPEDEF_FIELD_LIST
] - 1;
5872 method_last
= cols_next
[MONO_TYPEDEF_METHOD_LIST
] - 1;
5874 field_last
= image
->tables
[MONO_TABLE_FIELD
].rows
;
5875 method_last
= image
->tables
[MONO_TABLE_METHOD
].rows
;
5878 if (cols
[MONO_TYPEDEF_FIELD_LIST
] &&
5879 cols
[MONO_TYPEDEF_FIELD_LIST
] <= image
->tables
[MONO_TABLE_FIELD
].rows
)
5880 class->field
.count
= field_last
- class->field
.first
;
5882 class->field
.count
= 0;
5884 if (cols
[MONO_TYPEDEF_METHOD_LIST
] <= image
->tables
[MONO_TABLE_METHOD
].rows
)
5885 class->method
.count
= method_last
- class->method
.first
;
5887 class->method
.count
= 0;
5889 /* reserve space to store vector pointer in arrays */
5890 if (mono_is_corlib_image (image
) && !strcmp (nspace
, "System") && !strcmp (name
, "Array")) {
5891 class->instance_size
+= 2 * sizeof (gpointer
);
5892 g_assert (class->field
.count
== 0);
5895 if (class->enumtype
) {
5896 MonoType
*enum_basetype
= mono_class_find_enum_basetype (class, error
);
5897 if (!enum_basetype
) {
5898 /*set it to a default value as the whole runtime can't handle this to be null*/
5899 class->cast_class
= class->element_class
= mono_defaults
.int32_class
;
5900 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup (mono_error_get_message (error
)));
5901 mono_loader_unlock ();
5902 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5903 g_assert (!mono_loader_get_last_error ());
5906 class->cast_class
= class->element_class
= mono_class_from_mono_type (enum_basetype
);
5910 * If we're a generic type definition, load the constraints.
5911 * We must do this after the class has been constructed to make certain recursive scenarios
5914 if (class->generic_container
&& !mono_metadata_load_generic_param_constraints_checked (image
, type_token
, class->generic_container
, error
)) {
5915 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
)));
5916 mono_loader_unlock ();
5917 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5918 g_assert (!mono_loader_get_last_error ());
5922 if (class->image
->assembly_name
&& !strcmp (class->image
->assembly_name
, "Mono.Simd") && !strcmp (nspace
, "Mono.Simd")) {
5923 if (!strncmp (name
, "Vector", 6))
5924 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");
5927 mono_loader_unlock ();
5929 mono_profiler_class_loaded (class, MONO_PROFILE_OK
);
5930 g_assert (!mono_loader_get_last_error ());
5935 mono_class_setup_mono_type (class);
5936 mono_loader_unlock ();
5937 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5938 g_assert (!mono_loader_get_last_error ());
5942 /** is klass Nullable<T>? */
5944 mono_class_is_nullable (MonoClass
*klass
)
5946 return klass
->generic_class
!= NULL
&&
5947 klass
->generic_class
->container_class
== mono_defaults
.generic_nullable_class
;
5951 /** if klass is T? return T */
5953 mono_class_get_nullable_param (MonoClass
*klass
)
5955 g_assert (mono_class_is_nullable (klass
));
5956 return mono_class_from_mono_type (klass
->generic_class
->context
.class_inst
->type_argv
[0]);
5960 mono_generic_class_setup_parent (MonoClass
*klass
, MonoClass
*gtd
)
5964 MonoGenericClass
*gclass
= klass
->generic_class
;
5966 klass
->parent
= mono_class_inflate_generic_class_checked (gtd
->parent
, mono_generic_class_get_context (gclass
), &error
);
5967 if (!mono_error_ok (&error
)) {
5968 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5969 klass
->parent
= mono_defaults
.object_class
;
5970 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5971 mono_error_cleanup (&error
);
5975 mono_class_setup_parent (klass
, klass
->parent
);
5977 if (klass
->enumtype
) {
5978 klass
->cast_class
= gtd
->cast_class
;
5979 klass
->element_class
= gtd
->element_class
;
5985 * Create the `MonoClass' for an instantiation of a generic type.
5986 * We only do this if we actually need it.
5989 mono_generic_class_get_class (MonoGenericClass
*gclass
)
5991 MonoClass
*klass
, *gklass
;
5993 if (gclass
->cached_class
)
5994 return gclass
->cached_class
;
5996 mono_loader_lock ();
5997 if (gclass
->cached_class
) {
5998 mono_loader_unlock ();
5999 return gclass
->cached_class
;
6002 klass
= mono_image_set_alloc0 (gclass
->owner
, sizeof (MonoClass
));
6004 gklass
= gclass
->container_class
;
6006 if (record_gclass_instantiation
> 0)
6007 gclass_recorded_list
= g_slist_append (gclass_recorded_list
, klass
);
6009 if (gklass
->nested_in
) {
6010 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6011 klass
->nested_in
= gklass
->nested_in
;
6014 klass
->name
= gklass
->name
;
6015 klass
->name_space
= gklass
->name_space
;
6017 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
6019 klass
->image
= gklass
->image
;
6020 klass
->flags
= gklass
->flags
;
6021 klass
->type_token
= gklass
->type_token
;
6022 klass
->field
.count
= gklass
->field
.count
;
6024 klass
->is_inflated
= 1;
6025 klass
->generic_class
= gclass
;
6027 klass
->this_arg
.type
= klass
->byval_arg
.type
= MONO_TYPE_GENERICINST
;
6028 klass
->this_arg
.data
.generic_class
= klass
->byval_arg
.data
.generic_class
= gclass
;
6029 klass
->this_arg
.byref
= TRUE
;
6030 klass
->enumtype
= gklass
->enumtype
;
6031 klass
->valuetype
= gklass
->valuetype
;
6033 klass
->cast_class
= klass
->element_class
= klass
;
6035 if (mono_class_is_nullable (klass
))
6036 klass
->cast_class
= klass
->element_class
= mono_class_get_nullable_param (klass
);
6039 * We're not interested in the nested classes of a generic instance.
6040 * We use the generic type definition to look for nested classes.
6043 mono_generic_class_setup_parent (klass
, gklass
);
6045 if (gclass
->is_dynamic
) {
6048 mono_class_setup_supertypes (klass
);
6050 if (klass
->enumtype
) {
6052 * For enums, gklass->fields might not been set, but instance_size etc. is
6053 * already set in mono_reflection_create_internal_class (). For non-enums,
6054 * these will be computed normally in mono_class_layout_fields ().
6056 klass
->instance_size
= gklass
->instance_size
;
6057 klass
->sizes
.class_size
= gklass
->sizes
.class_size
;
6058 mono_memory_barrier ();
6059 klass
->size_inited
= 1;
6063 mono_memory_barrier ();
6064 gclass
->cached_class
= klass
;
6066 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
6068 inflated_classes
++;
6069 inflated_classes_size
+= sizeof (MonoClass
);
6071 mono_loader_unlock ();
6077 make_generic_param_class (MonoGenericParam
*param
, MonoImage
*image
, gboolean is_mvar
, MonoGenericParamInfo
*pinfo
)
6079 MonoClass
*klass
, **ptr
;
6081 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
6085 image
= mono_defaults
.corlib
;
6087 klass
= mono_image_alloc0 (image
, sizeof (MonoClass
));
6088 classes_size
+= sizeof (MonoClass
);
6091 klass
->name
= pinfo
->name
;
6093 int n
= mono_generic_param_num (param
);
6094 klass
->name
= mono_image_alloc0 (image
, 16);
6095 sprintf ((char*)klass
->name
, "%d", n
);
6100 MonoMethod
*omethod
= container
->owner
.method
;
6101 klass
->name_space
= (omethod
&& omethod
->klass
) ? omethod
->klass
->name_space
: "";
6103 MonoClass
*oklass
= container
->owner
.klass
;
6104 klass
->name_space
= oklass
? oklass
->name_space
: "";
6107 klass
->name_space
= "";
6110 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
6114 for (ptr
= pinfo
->constraints
; ptr
&& *ptr
; ptr
++, count
++)
6118 if ((count
> 0) && !MONO_CLASS_IS_INTERFACE (pinfo
->constraints
[0])) {
6119 klass
->parent
= pinfo
->constraints
[0];
6121 } else if (pinfo
&& pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
)
6122 klass
->parent
= mono_class_from_name (mono_defaults
.corlib
, "System", "ValueType");
6124 klass
->parent
= mono_defaults
.object_class
;
6127 if (count
- pos
> 0) {
6128 klass
->interface_count
= count
- pos
;
6129 klass
->interfaces
= mono_image_alloc0 (image
, sizeof (MonoClass
*) * (count
- pos
));
6130 klass
->interfaces_inited
= TRUE
;
6131 for (i
= pos
; i
< count
; i
++)
6132 klass
->interfaces
[i
- pos
] = pinfo
->constraints
[i
];
6135 klass
->image
= image
;
6137 klass
->inited
= TRUE
;
6138 klass
->cast_class
= klass
->element_class
= klass
;
6139 klass
->flags
= TYPE_ATTRIBUTE_PUBLIC
;
6141 klass
->this_arg
.type
= klass
->byval_arg
.type
= is_mvar
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
6142 klass
->this_arg
.data
.generic_param
= klass
->byval_arg
.data
.generic_param
= param
;
6143 klass
->this_arg
.byref
= TRUE
;
6145 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6146 klass
->sizes
.generic_param_token
= pinfo
? pinfo
->token
: 0;
6148 /*Init these fields to sane values*/
6149 klass
->min_align
= 1;
6150 klass
->instance_size
= sizeof (gpointer
);
6151 mono_memory_barrier ();
6152 klass
->size_inited
= 1;
6154 mono_class_setup_supertypes (klass
);
6156 if (count
- pos
> 0) {
6157 mono_class_setup_vtable (klass
->parent
);
6158 if (klass
->parent
->exception_type
)
6159 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Failed to setup parent interfaces"));
6161 setup_interface_offsets (klass
, klass
->parent
->vtable_size
, TRUE
);
6167 #define FAST_CACHE_SIZE 16
6170 * LOCKING: Takes the image lock depending on @take_lock.
6173 get_anon_gparam_class (MonoGenericParam
*param
, gboolean is_mvar
, gboolean take_lock
)
6175 int n
= mono_generic_param_num (param
) | ((guint32
)param
->serial
<< 16);
6176 MonoImage
*image
= param
->image
;
6181 if (n
< FAST_CACHE_SIZE
) {
6183 return image
->mvar_cache_fast
? image
->mvar_cache_fast
[n
] : NULL
;
6185 return image
->var_cache_fast
? image
->var_cache_fast
[n
] : NULL
;
6187 MonoClass
*klass
= NULL
;
6188 ht
= is_mvar
? image
->mvar_cache_slow
: image
->var_cache_slow
;
6191 mono_image_lock (image
);
6192 klass
= g_hash_table_lookup (ht
, GINT_TO_POINTER (n
));
6194 mono_image_unlock (image
);
6201 * LOCKING: Image lock (param->image) must be held
6204 set_anon_gparam_class (MonoGenericParam
*param
, gboolean is_mvar
, MonoClass
*klass
)
6206 int n
= mono_generic_param_num (param
) | ((guint32
)param
->serial
<< 16);
6207 MonoImage
*image
= param
->image
;
6211 if (n
< FAST_CACHE_SIZE
) {
6213 /* Requires locking to avoid droping an already published class */
6214 if (!image
->mvar_cache_fast
)
6215 image
->mvar_cache_fast
= mono_image_alloc0 (image
, sizeof (MonoClass
*) * FAST_CACHE_SIZE
);
6216 image
->mvar_cache_fast
[n
] = klass
;
6218 if (!image
->var_cache_fast
)
6219 image
->var_cache_fast
= mono_image_alloc0 (image
, sizeof (MonoClass
*) * FAST_CACHE_SIZE
);
6220 image
->var_cache_fast
[n
] = klass
;
6223 GHashTable
*ht
= is_mvar
? image
->mvar_cache_slow
: image
->var_cache_slow
;
6225 ht
= is_mvar
? image
->mvar_cache_slow
: image
->var_cache_slow
;
6227 ht
= g_hash_table_new (NULL
, NULL
);
6228 mono_memory_barrier ();
6230 image
->mvar_cache_slow
= ht
;
6232 image
->var_cache_slow
= ht
;
6235 g_hash_table_insert (ht
, GINT_TO_POINTER (n
), klass
);
6240 * LOCKING: Acquires the image lock (@image).
6243 mono_class_from_generic_parameter (MonoGenericParam
*param
, MonoImage
*image
, gboolean is_mvar
)
6245 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
6246 MonoGenericParamInfo
*pinfo
= NULL
;
6247 MonoClass
*klass
, *klass2
;
6250 pinfo
= mono_generic_param_info (param
);
6251 klass
= pinfo
->pklass
;
6254 klass
= get_anon_gparam_class (param
, is_mvar
, TRUE
);
6259 if (!image
&& container
) {
6261 MonoMethod
*method
= container
->owner
.method
;
6262 image
= (method
&& method
->klass
) ? method
->klass
->image
: NULL
;
6264 MonoClass
*klass
= container
->owner
.klass
;
6265 // FIXME: 'klass' should not be null
6266 // But, monodis creates GenericContainers without associating a owner to it
6267 image
= klass
? klass
->image
: NULL
;
6271 klass
= make_generic_param_class (param
, image
, is_mvar
, pinfo
);
6273 mono_memory_barrier ();
6275 if (!image
) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6276 image
= mono_defaults
.corlib
;
6278 mono_image_lock (image
);
6280 klass2
= pinfo
->pklass
;
6282 klass2
= get_anon_gparam_class (param
, is_mvar
, FALSE
);
6288 pinfo
->pklass
= klass
;
6290 set_anon_gparam_class (param
, is_mvar
, klass
);
6292 mono_image_unlock (image
);
6294 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6296 mono_profiler_class_loaded (klass2
, MONO_PROFILE_FAILED
);
6298 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
6304 mono_ptr_class_get (MonoType
*type
)
6307 MonoClass
*el_class
;
6311 el_class
= mono_class_from_mono_type (type
);
6312 image
= el_class
->image
;
6314 mono_image_lock (image
);
6315 if (image
->ptr_cache
) {
6316 if ((result
= g_hash_table_lookup (image
->ptr_cache
, el_class
))) {
6317 mono_image_unlock (image
);
6321 mono_image_unlock (image
);
6323 result
= mono_image_alloc0 (image
, sizeof (MonoClass
));
6325 classes_size
+= sizeof (MonoClass
);
6327 result
->parent
= NULL
; /* no parent for PTR types */
6328 result
->name_space
= el_class
->name_space
;
6329 name
= g_strdup_printf ("%s*", el_class
->name
);
6330 result
->name
= mono_image_strdup (image
, name
);
6333 mono_profiler_class_event (result
, MONO_PROFILE_START_LOAD
);
6335 result
->image
= el_class
->image
;
6336 result
->inited
= TRUE
;
6337 result
->flags
= TYPE_ATTRIBUTE_CLASS
| (el_class
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
);
6338 /* Can pointers get boxed? */
6339 result
->instance_size
= sizeof (gpointer
);
6340 result
->cast_class
= result
->element_class
= el_class
;
6341 result
->blittable
= TRUE
;
6343 result
->this_arg
.type
= result
->byval_arg
.type
= MONO_TYPE_PTR
;
6344 result
->this_arg
.data
.type
= result
->byval_arg
.data
.type
= &result
->element_class
->byval_arg
;
6345 result
->this_arg
.byref
= TRUE
;
6347 mono_class_setup_supertypes (result
);
6349 mono_image_lock (image
);
6350 if (image
->ptr_cache
) {
6352 if ((result2
= g_hash_table_lookup (image
->ptr_cache
, el_class
))) {
6353 mono_image_unlock (image
);
6354 mono_profiler_class_loaded (result
, MONO_PROFILE_FAILED
);
6358 image
->ptr_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
6360 g_hash_table_insert (image
->ptr_cache
, el_class
, result
);
6361 mono_image_unlock (image
);
6363 mono_profiler_class_loaded (result
, MONO_PROFILE_OK
);
6369 mono_fnptr_class_get (MonoMethodSignature
*sig
)
6372 static GHashTable
*ptr_hash
= NULL
;
6374 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6376 mono_loader_lock ();
6379 ptr_hash
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
6381 if ((result
= g_hash_table_lookup (ptr_hash
, sig
))) {
6382 mono_loader_unlock ();
6385 result
= g_new0 (MonoClass
, 1);
6387 result
->parent
= NULL
; /* no parent for PTR types */
6388 result
->name_space
= "System";
6389 result
->name
= "MonoFNPtrFakeClass";
6391 mono_profiler_class_event (result
, MONO_PROFILE_START_LOAD
);
6393 result
->image
= mono_defaults
.corlib
; /* need to fix... */
6394 result
->inited
= TRUE
;
6395 result
->flags
= TYPE_ATTRIBUTE_CLASS
; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6396 /* Can pointers get boxed? */
6397 result
->instance_size
= sizeof (gpointer
);
6398 result
->cast_class
= result
->element_class
= result
;
6399 result
->blittable
= TRUE
;
6401 result
->this_arg
.type
= result
->byval_arg
.type
= MONO_TYPE_FNPTR
;
6402 result
->this_arg
.data
.method
= result
->byval_arg
.data
.method
= sig
;
6403 result
->this_arg
.byref
= TRUE
;
6404 result
->blittable
= TRUE
;
6406 mono_class_setup_supertypes (result
);
6408 g_hash_table_insert (ptr_hash
, sig
, result
);
6410 mono_loader_unlock ();
6412 mono_profiler_class_loaded (result
, MONO_PROFILE_OK
);
6418 mono_class_from_mono_type (MonoType
*type
)
6420 switch (type
->type
) {
6421 case MONO_TYPE_OBJECT
:
6422 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.object_class
;
6423 case MONO_TYPE_VOID
:
6424 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.void_class
;
6425 case MONO_TYPE_BOOLEAN
:
6426 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.boolean_class
;
6427 case MONO_TYPE_CHAR
:
6428 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.char_class
;
6430 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.sbyte_class
;
6432 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.byte_class
;
6434 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int16_class
;
6436 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint16_class
;
6438 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int32_class
;
6440 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint32_class
;
6442 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int_class
;
6444 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint_class
;
6446 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int64_class
;
6448 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint64_class
;
6450 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.single_class
;
6452 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.double_class
;
6453 case MONO_TYPE_STRING
:
6454 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.string_class
;
6455 case MONO_TYPE_TYPEDBYREF
:
6456 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.typed_reference_class
;
6457 case MONO_TYPE_ARRAY
:
6458 return mono_bounded_array_class_get (type
->data
.array
->eklass
, type
->data
.array
->rank
, TRUE
);
6460 return mono_ptr_class_get (type
->data
.type
);
6461 case MONO_TYPE_FNPTR
:
6462 return mono_fnptr_class_get (type
->data
.method
);
6463 case MONO_TYPE_SZARRAY
:
6464 return mono_array_class_get (type
->data
.klass
, 1);
6465 case MONO_TYPE_CLASS
:
6466 case MONO_TYPE_VALUETYPE
:
6467 return type
->data
.klass
;
6468 case MONO_TYPE_GENERICINST
:
6469 return mono_generic_class_get_class (type
->data
.generic_class
);
6471 return mono_class_from_generic_parameter (type
->data
.generic_param
, NULL
, FALSE
);
6472 case MONO_TYPE_MVAR
:
6473 return mono_class_from_generic_parameter (type
->data
.generic_param
, NULL
, TRUE
);
6475 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type
->type
);
6476 g_assert_not_reached ();
6483 * mono_type_retrieve_from_typespec
6484 * @image: context where the image is created
6485 * @type_spec: typespec token
6486 * @context: the generic context used to evaluate generic instantiations in
6489 mono_type_retrieve_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, gboolean
*did_inflate
, MonoError
*error
)
6491 MonoType
*t
= mono_type_create_from_typespec_checked (image
, type_spec
, error
);
6493 *did_inflate
= FALSE
;
6498 if (context
&& (context
->class_inst
|| context
->method_inst
)) {
6499 MonoType
*inflated
= inflate_generic_type (NULL
, t
, context
, error
);
6501 if (!mono_error_ok (error
)) {
6502 g_assert (!mono_loader_get_last_error ());
6508 *did_inflate
= TRUE
;
6515 * mono_class_create_from_typespec
6516 * @image: context where the image is created
6517 * @type_spec: typespec token
6518 * @context: the generic context used to evaluate generic instantiations in
6521 mono_class_create_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, MonoError
*error
)
6524 gboolean inflated
= FALSE
;
6525 MonoType
*t
= mono_type_retrieve_from_typespec (image
, type_spec
, context
, &inflated
, error
);
6526 if (!mono_error_ok (error
))
6528 ret
= mono_class_from_mono_type (t
);
6530 mono_metadata_free_type (t
);
6535 * mono_bounded_array_class_get:
6536 * @element_class: element class
6537 * @rank: the dimension of the array class
6538 * @bounded: whenever the array has non-zero bounds
6540 * Returns: a class object describing the array with element type @element_type and
6544 mono_bounded_array_class_get (MonoClass
*eclass
, guint32 rank
, gboolean bounded
)
6548 MonoClass
*parent
= NULL
;
6549 GSList
*list
, *rootlist
= NULL
;
6552 gboolean corlib_type
= FALSE
;
6554 g_assert (rank
<= 255);
6557 /* bounded only matters for one-dimensional arrays */
6560 image
= eclass
->image
;
6562 if (rank
== 1 && !bounded
) {
6564 * This case is very frequent not just during compilation because of calls
6565 * from mono_class_from_mono_type (), mono_array_new (),
6566 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6568 mono_mutex_lock (&image
->szarray_cache_lock
);
6569 if (!image
->szarray_cache
)
6570 image
->szarray_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
6571 class = g_hash_table_lookup (image
->szarray_cache
, eclass
);
6572 mono_mutex_unlock (&image
->szarray_cache_lock
);
6576 mono_loader_lock ();
6578 mono_loader_lock ();
6580 if (!image
->array_cache
)
6581 image
->array_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
6583 if ((rootlist
= list
= g_hash_table_lookup (image
->array_cache
, eclass
))) {
6584 for (; list
; list
= list
->next
) {
6586 if ((class->rank
== rank
) && (class->byval_arg
.type
== (((rank
> 1) || bounded
) ? MONO_TYPE_ARRAY
: MONO_TYPE_SZARRAY
))) {
6587 mono_loader_unlock ();
6594 /* for the building corlib use System.Array from it */
6595 if (image
->assembly
&& assembly_is_dynamic (image
->assembly
) && image
->assembly_name
&& strcmp (image
->assembly_name
, "mscorlib") == 0) {
6596 parent
= mono_class_from_name (image
, "System", "Array");
6599 parent
= mono_defaults
.array_class
;
6600 if (!parent
->inited
)
6601 mono_class_init (parent
);
6604 class = mono_image_alloc0 (image
, sizeof (MonoClass
));
6606 class->image
= image
;
6607 class->name_space
= eclass
->name_space
;
6608 nsize
= strlen (eclass
->name
);
6609 name
= g_malloc (nsize
+ 2 + rank
+ 1);
6610 memcpy (name
, eclass
->name
, nsize
);
6613 memset (name
+ nsize
+ 1, ',', rank
- 1);
6615 name
[nsize
+ rank
] = '*';
6616 name
[nsize
+ rank
+ bounded
] = ']';
6617 name
[nsize
+ rank
+ bounded
+ 1] = 0;
6618 class->name
= mono_image_strdup (image
, name
);
6621 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD
);
6623 classes_size
+= sizeof (MonoClass
);
6625 class->type_token
= 0;
6626 /* all arrays are marked serializable and sealed, bug #42779 */
6627 class->flags
= TYPE_ATTRIBUTE_CLASS
| TYPE_ATTRIBUTE_SERIALIZABLE
| TYPE_ATTRIBUTE_SEALED
| TYPE_ATTRIBUTE_PUBLIC
;
6628 class->parent
= parent
;
6629 class->instance_size
= mono_class_instance_size (class->parent
);
6631 if (eclass
->byval_arg
.type
== MONO_TYPE_TYPEDBYREF
|| eclass
->byval_arg
.type
== MONO_TYPE_VOID
) {
6632 /*Arrays of those two types are invalid.*/
6633 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
6634 } else if (eclass
->enumtype
&& !mono_class_enum_basetype (eclass
)) {
6635 if (!eclass
->ref_info_handle
|| eclass
->wastypebuilder
) {
6636 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6637 g_assert (eclass
->ref_info_handle
&& !eclass
->wastypebuilder
);
6639 /* element_size -1 is ok as this is not an instantitable type*/
6640 class->sizes
.element_size
= -1;
6642 class->sizes
.element_size
= mono_class_array_element_size (eclass
);
6644 mono_class_setup_supertypes (class);
6646 if (eclass
->generic_class
)
6647 mono_class_init (eclass
);
6648 if (!eclass
->size_inited
)
6649 mono_class_setup_fields (eclass
);
6650 if (eclass
->exception_type
) /*FIXME we fail the array type, but we have to let other fields be set.*/
6651 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
6653 class->has_references
= MONO_TYPE_IS_REFERENCE (&eclass
->byval_arg
) || eclass
->has_references
? TRUE
: FALSE
;
6657 if (eclass
->enumtype
)
6658 class->cast_class
= eclass
->element_class
;
6660 class->cast_class
= eclass
;
6662 switch (class->cast_class
->byval_arg
.type
) {
6664 class->cast_class
= mono_defaults
.byte_class
;
6667 class->cast_class
= mono_defaults
.int16_class
;
6670 #if SIZEOF_VOID_P == 4
6674 class->cast_class
= mono_defaults
.int32_class
;
6677 #if SIZEOF_VOID_P == 8
6681 class->cast_class
= mono_defaults
.int64_class
;
6685 class->element_class
= eclass
;
6687 if ((rank
> 1) || bounded
) {
6688 MonoArrayType
*at
= mono_image_alloc0 (image
, sizeof (MonoArrayType
));
6689 class->byval_arg
.type
= MONO_TYPE_ARRAY
;
6690 class->byval_arg
.data
.array
= at
;
6691 at
->eklass
= eclass
;
6693 /* FIXME: complete.... */
6695 class->byval_arg
.type
= MONO_TYPE_SZARRAY
;
6696 class->byval_arg
.data
.klass
= eclass
;
6698 class->this_arg
= class->byval_arg
;
6699 class->this_arg
.byref
= 1;
6704 class->generic_container
= eclass
->generic_container
;
6706 if (rank
== 1 && !bounded
) {
6707 MonoClass
*prev_class
;
6709 mono_mutex_lock (&image
->szarray_cache_lock
);
6710 prev_class
= g_hash_table_lookup (image
->szarray_cache
, eclass
);
6712 /* Someone got in before us */
6715 g_hash_table_insert (image
->szarray_cache
, eclass
, class);
6716 mono_mutex_unlock (&image
->szarray_cache_lock
);
6718 list
= g_slist_append (rootlist
, class);
6719 g_hash_table_insert (image
->array_cache
, eclass
, list
);
6722 mono_loader_unlock ();
6724 mono_profiler_class_loaded (class, MONO_PROFILE_OK
);
6730 * mono_array_class_get:
6731 * @element_class: element class
6732 * @rank: the dimension of the array class
6734 * Returns: a class object describing the array with element type @element_type and
6738 mono_array_class_get (MonoClass
*eclass
, guint32 rank
)
6740 return mono_bounded_array_class_get (eclass
, rank
, FALSE
);
6744 * mono_class_instance_size:
6747 * Returns: the size of an object instance
6750 mono_class_instance_size (MonoClass
*klass
)
6752 if (!klass
->size_inited
)
6753 mono_class_init (klass
);
6755 return klass
->instance_size
;
6759 * mono_class_min_align:
6762 * Returns: minimm alignment requirements
6765 mono_class_min_align (MonoClass
*klass
)
6767 if (!klass
->size_inited
)
6768 mono_class_init (klass
);
6770 return klass
->min_align
;
6774 * mono_class_value_size:
6777 * This function is used for value types, and return the
6778 * space and the alignment to store that kind of value object.
6780 * Returns: the size of a value of kind @klass
6783 mono_class_value_size (MonoClass
*klass
, guint32
*align
)
6787 /* fixme: check disable, because we still have external revereces to
6788 * mscorlib and Dummy Objects
6790 /*g_assert (klass->valuetype);*/
6792 size
= mono_class_instance_size (klass
) - sizeof (MonoObject
);
6795 *align
= klass
->min_align
;
6801 * mono_class_data_size:
6804 * Returns: the size of the static class data
6807 mono_class_data_size (MonoClass
*klass
)
6810 mono_class_init (klass
);
6811 /* This can happen with dynamically created types */
6812 if (!klass
->fields_inited
)
6813 mono_class_setup_fields_locking (klass
);
6815 /* in arrays, sizes.class_size is unioned with element_size
6816 * and arrays have no static fields
6820 return klass
->sizes
.class_size
;
6824 * Auxiliary routine to mono_class_get_field
6826 * Takes a field index instead of a field token.
6828 static MonoClassField
*
6829 mono_class_get_field_idx (MonoClass
*class, int idx
)
6831 mono_class_setup_fields_locking (class);
6832 if (class->exception_type
)
6836 if (class->image
->uncompressed_metadata
) {
6838 * class->field.first points to the FieldPtr table, while idx points into the
6839 * Field table, so we have to do a search.
6841 /*FIXME this is broken for types with multiple fields with the same name.*/
6842 const char *name
= mono_metadata_string_heap (class->image
, mono_metadata_decode_row_col (&class->image
->tables
[MONO_TABLE_FIELD
], idx
, MONO_FIELD_NAME
));
6845 for (i
= 0; i
< class->field
.count
; ++i
)
6846 if (mono_field_get_name (&class->fields
[i
]) == name
)
6847 return &class->fields
[i
];
6848 g_assert_not_reached ();
6850 if (class->field
.count
) {
6851 if ((idx
>= class->field
.first
) && (idx
< class->field
.first
+ class->field
.count
)){
6852 return &class->fields
[idx
- class->field
.first
];
6856 class = class->parent
;
6862 * mono_class_get_field:
6863 * @class: the class to lookup the field.
6864 * @field_token: the field token
6866 * Returns: A MonoClassField representing the type and offset of
6867 * the field, or a NULL value if the field does not belong to this
6871 mono_class_get_field (MonoClass
*class, guint32 field_token
)
6873 int idx
= mono_metadata_token_index (field_token
);
6875 g_assert (mono_metadata_token_code (field_token
) == MONO_TOKEN_FIELD_DEF
);
6877 return mono_class_get_field_idx (class, idx
- 1);
6881 * mono_class_get_field_from_name:
6882 * @klass: the class to lookup the field.
6883 * @name: the field name
6885 * Search the class @klass and it's parents for a field with the name @name.
6887 * Returns: the MonoClassField pointer of the named field or NULL
6890 mono_class_get_field_from_name (MonoClass
*klass
, const char *name
)
6892 return mono_class_get_field_from_name_full (klass
, name
, NULL
);
6896 * mono_class_get_field_from_name_full:
6897 * @klass: the class to lookup the field.
6898 * @name: the field name
6899 * @type: the type of the fields. This optional.
6901 * Search the class @klass and it's parents for a field with the name @name and type @type.
6903 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6904 * of its generic type definition.
6906 * Returns: the MonoClassField pointer of the named field or NULL
6909 mono_class_get_field_from_name_full (MonoClass
*klass
, const char *name
, MonoType
*type
)
6913 mono_class_setup_fields_locking (klass
);
6914 if (klass
->exception_type
)
6918 for (i
= 0; i
< klass
->field
.count
; ++i
) {
6919 MonoClassField
*field
= &klass
->fields
[i
];
6921 if (strcmp (name
, mono_field_get_name (field
)) != 0)
6925 MonoType
*field_type
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
)->type
;
6926 if (!mono_metadata_type_equal_full (type
, field_type
, TRUE
))
6931 klass
= klass
->parent
;
6937 * mono_class_get_field_token:
6938 * @field: the field we need the token of
6940 * Get the token of a field. Note that the tokesn is only valid for the image
6941 * the field was loaded from. Don't use this function for fields in dynamic types.
6943 * Returns: the token representing the field in the image it was loaded from.
6946 mono_class_get_field_token (MonoClassField
*field
)
6948 MonoClass
*klass
= field
->parent
;
6951 mono_class_setup_fields_locking (klass
);
6956 for (i
= 0; i
< klass
->field
.count
; ++i
) {
6957 if (&klass
->fields
[i
] == field
) {
6958 int idx
= klass
->field
.first
+ i
+ 1;
6960 if (klass
->image
->uncompressed_metadata
)
6961 idx
= mono_metadata_translate_token_index (klass
->image
, MONO_TABLE_FIELD
, idx
);
6962 return mono_metadata_make_token (MONO_TABLE_FIELD
, idx
);
6965 klass
= klass
->parent
;
6968 g_assert_not_reached ();
6973 mono_field_get_index (MonoClassField
*field
)
6975 int index
= field
- field
->parent
->fields
;
6977 g_assert (index
>= 0 && index
< field
->parent
->field
.count
);
6983 * mono_class_get_field_default_value:
6985 * Return the default value of the field as a pointer into the metadata blob.
6988 mono_class_get_field_default_value (MonoClassField
*field
, MonoTypeEnum
*def_type
)
6991 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
6993 MonoClass
*klass
= field
->parent
;
6995 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
);
6997 if (!klass
->ext
|| !klass
->ext
->field_def_values
) {
6998 MonoFieldDefaultValue
*def_values
;
7000 mono_class_alloc_ext (klass
);
7002 def_values
= mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * klass
->field
.count
);
7004 mono_image_lock (klass
->image
);
7005 mono_memory_barrier ();
7006 if (!klass
->ext
->field_def_values
)
7007 klass
->ext
->field_def_values
= def_values
;
7008 mono_image_unlock (klass
->image
);
7011 field_index
= mono_field_get_index (field
);
7013 if (!klass
->ext
->field_def_values
[field_index
].data
) {
7014 cindex
= mono_metadata_get_constant_index (field
->parent
->image
, mono_class_get_field_token (field
), 0);
7018 g_assert (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
));
7020 mono_metadata_decode_row (&field
->parent
->image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
7021 klass
->ext
->field_def_values
[field_index
].def_type
= constant_cols
[MONO_CONSTANT_TYPE
];
7022 klass
->ext
->field_def_values
[field_index
].data
= (gpointer
)mono_metadata_blob_heap (field
->parent
->image
, constant_cols
[MONO_CONSTANT_VALUE
]);
7025 *def_type
= klass
->ext
->field_def_values
[field_index
].def_type
;
7026 return klass
->ext
->field_def_values
[field_index
].data
;
7030 mono_property_get_index (MonoProperty
*prop
)
7032 int index
= prop
- prop
->parent
->ext
->properties
;
7034 g_assert (index
>= 0 && index
< prop
->parent
->ext
->property
.count
);
7040 * mono_class_get_property_default_value:
7042 * Return the default value of the field as a pointer into the metadata blob.
7045 mono_class_get_property_default_value (MonoProperty
*property
, MonoTypeEnum
*def_type
)
7048 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
7049 MonoClass
*klass
= property
->parent
;
7051 g_assert (property
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
);
7053 * We don't cache here because it is not used by C# so it's quite rare, but
7054 * we still do the lookup in klass->ext because that is where the data
7055 * is stored for dynamic assemblies.
7058 if (image_is_dynamic (klass
->image
)) {
7059 int prop_index
= mono_property_get_index (property
);
7060 if (klass
->ext
->prop_def_values
&& klass
->ext
->prop_def_values
[prop_index
].data
) {
7061 *def_type
= klass
->ext
->prop_def_values
[prop_index
].def_type
;
7062 return klass
->ext
->prop_def_values
[prop_index
].data
;
7066 cindex
= mono_metadata_get_constant_index (klass
->image
, mono_class_get_property_token (property
), 0);
7070 mono_metadata_decode_row (&klass
->image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
7071 *def_type
= constant_cols
[MONO_CONSTANT_TYPE
];
7072 return (gpointer
)mono_metadata_blob_heap (klass
->image
, constant_cols
[MONO_CONSTANT_VALUE
]);
7076 mono_class_get_event_token (MonoEvent
*event
)
7078 MonoClass
*klass
= event
->parent
;
7083 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
7084 if (&klass
->ext
->events
[i
] == event
)
7085 return mono_metadata_make_token (MONO_TABLE_EVENT
, klass
->ext
->event
.first
+ i
+ 1);
7088 klass
= klass
->parent
;
7091 g_assert_not_reached ();
7096 mono_class_get_property_from_name (MonoClass
*klass
, const char *name
)
7100 gpointer iter
= NULL
;
7101 while ((p
= mono_class_get_properties (klass
, &iter
))) {
7102 if (! strcmp (name
, p
->name
))
7105 klass
= klass
->parent
;
7111 mono_class_get_property_token (MonoProperty
*prop
)
7113 MonoClass
*klass
= prop
->parent
;
7117 gpointer iter
= NULL
;
7118 while ((p
= mono_class_get_properties (klass
, &iter
))) {
7119 if (&klass
->ext
->properties
[i
] == prop
)
7120 return mono_metadata_make_token (MONO_TABLE_PROPERTY
, klass
->ext
->property
.first
+ i
+ 1);
7124 klass
= klass
->parent
;
7127 g_assert_not_reached ();
7132 mono_class_name_from_token (MonoImage
*image
, guint32 type_token
)
7134 const char *name
, *nspace
;
7135 if (image_is_dynamic (image
))
7136 return g_strdup_printf ("DynamicType 0x%08x", type_token
);
7138 switch (type_token
& 0xff000000){
7139 case MONO_TOKEN_TYPE_DEF
: {
7140 guint32 cols
[MONO_TYPEDEF_SIZE
];
7141 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
7142 guint tidx
= mono_metadata_token_index (type_token
);
7144 if (tidx
> tt
->rows
)
7145 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
7147 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
7148 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
7149 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
7150 if (strlen (nspace
) == 0)
7151 return g_strdup_printf ("%s", name
);
7153 return g_strdup_printf ("%s.%s", nspace
, name
);
7156 case MONO_TOKEN_TYPE_REF
: {
7158 guint32 cols
[MONO_TYPEREF_SIZE
];
7159 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
7160 guint tidx
= mono_metadata_token_index (type_token
);
7163 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
7165 if (!mono_verifier_verify_typeref_row (image
, tidx
- 1, &error
)) {
7166 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (&error
));
7167 mono_error_cleanup (&error
);
7171 mono_metadata_decode_row (t
, tidx
-1, cols
, MONO_TYPEREF_SIZE
);
7172 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
7173 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
7174 if (strlen (nspace
) == 0)
7175 return g_strdup_printf ("%s", name
);
7177 return g_strdup_printf ("%s.%s", nspace
, name
);
7180 case MONO_TOKEN_TYPE_SPEC
:
7181 return g_strdup_printf ("Typespec 0x%08x", type_token
);
7183 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
7188 mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
)
7190 if (image_is_dynamic (image
))
7191 return g_strdup_printf ("DynamicAssembly %s", image
->name
);
7193 switch (type_token
& 0xff000000){
7194 case MONO_TOKEN_TYPE_DEF
:
7195 if (image
->assembly
)
7196 return mono_stringify_assembly_name (&image
->assembly
->aname
);
7197 else if (image
->assembly_name
)
7198 return g_strdup (image
->assembly_name
);
7199 return g_strdup_printf ("%s", image
->name
? image
->name
: "[Could not resolve assembly name");
7200 case MONO_TOKEN_TYPE_REF
: {
7202 MonoAssemblyName aname
;
7203 guint32 cols
[MONO_TYPEREF_SIZE
];
7204 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
7205 guint32 idx
= mono_metadata_token_index (type_token
);
7208 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
7210 if (!mono_verifier_verify_typeref_row (image
, idx
- 1, &error
)) {
7211 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (&error
));
7212 mono_error_cleanup (&error
);
7215 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPEREF_SIZE
);
7217 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
7218 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
7219 case MONO_RESOLUTION_SCOPE_MODULE
:
7221 return g_strdup ("");
7222 case MONO_RESOLUTION_SCOPE_MODULEREF
:
7224 return g_strdup ("");
7225 case MONO_RESOLUTION_SCOPE_TYPEREF
:
7227 return g_strdup ("");
7228 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
7229 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
7230 return mono_stringify_assembly_name (&aname
);
7232 g_assert_not_reached ();
7236 case MONO_TOKEN_TYPE_SPEC
:
7238 return g_strdup ("");
7240 g_assert_not_reached ();
7247 * mono_class_get_full:
7248 * @image: the image where the class resides
7249 * @type_token: the token for the class
7250 * @context: the generic context used to evaluate generic instantiations in
7251 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7253 * Returns: the MonoClass that represents @type_token in @image
7256 mono_class_get_full (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
)
7260 class = mono_class_get_checked (image
, type_token
, &error
);
7262 if (class && context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
7263 class = mono_class_inflate_generic_class_checked (class, context
, &error
);
7265 g_assert (mono_error_ok (&error
)); /* FIXME deprecate this function and forbit the runtime from using it. */
7271 mono_class_get_and_inflate_typespec_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
7275 mono_error_init (error
);
7276 class = mono_class_get_checked (image
, type_token
, error
);
7278 if (class && context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
7279 class = mono_class_inflate_generic_class_checked (class, context
, error
);
7284 * mono_class_get_checked:
7285 * @image: the image where the class resides
7286 * @type_token: the token for the class
7287 * @error: error object to return any error
7289 * Returns: the MonoClass that represents @type_token in @image
7292 mono_class_get_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
7294 MonoClass
*class = NULL
;
7296 mono_error_init (error
);
7298 if (image_is_dynamic (image
)) {
7299 int table
= mono_metadata_token_table (type_token
);
7301 if (table
!= MONO_TABLE_TYPEDEF
&& table
!= MONO_TABLE_TYPEREF
&& table
!= MONO_TABLE_TYPESPEC
) {
7302 mono_error_set_bad_image (error
, image
,"Bad token table for dynamic image: %x", table
);
7305 class = mono_lookup_dynamic_token (image
, type_token
, NULL
); /*FIXME proper error handling*/
7309 switch (type_token
& 0xff000000){
7310 case MONO_TOKEN_TYPE_DEF
:
7311 class = mono_class_create_from_typedef (image
, type_token
, error
);
7313 case MONO_TOKEN_TYPE_REF
:
7314 class = mono_class_from_typeref_checked (image
, type_token
, error
);
7316 case MONO_TOKEN_TYPE_SPEC
:
7317 class = mono_class_create_from_typespec (image
, type_token
, NULL
, error
);
7320 mono_error_set_bad_image (error
, image
, "Unknown type token %x", type_token
& 0xff000000);
7324 /* Generic case, should be avoided for when a better error is possible. */
7325 if (!class && mono_error_ok (error
)) {
7326 char *name
= mono_class_name_from_token (image
, type_token
);
7327 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
7328 mono_error_set_type_load_name (error
, name
, assembly
, "Could not resolve type with token %08x", type_token
);
7336 * mono_type_get_checked:
7337 * @image: the image where the type resides
7338 * @type_token: the token for the type
7339 * @context: the generic context used to evaluate generic instantiations in
7340 * @error: Error handling context
7342 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7344 * Returns: the MonoType that represents @type_token in @image
7347 mono_type_get_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
7349 MonoType
*type
= NULL
;
7350 gboolean inflated
= FALSE
;
7352 mono_error_init (error
);
7354 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7355 if (image_is_dynamic (image
))
7356 return mono_class_get_type (mono_lookup_dynamic_token (image
, type_token
, context
));
7358 if ((type_token
& 0xff000000) != MONO_TOKEN_TYPE_SPEC
) {
7359 MonoClass
*class = mono_class_get_checked (image
, type_token
, error
);
7362 g_assert (!mono_loader_get_last_error ());
7367 return mono_class_get_type (class);
7370 type
= mono_type_retrieve_from_typespec (image
, type_token
, context
, &inflated
, error
);
7373 g_assert (!mono_loader_get_last_error ());
7378 MonoType
*tmp
= type
;
7379 type
= mono_class_get_type (mono_class_from_mono_type (type
));
7380 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7381 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7382 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7384 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7386 if (type
->type
!= tmp
->type
)
7389 mono_metadata_free_type (tmp
);
7396 mono_class_get (MonoImage
*image
, guint32 type_token
)
7398 return mono_class_get_full (image
, type_token
, NULL
);
7402 * mono_image_init_name_cache:
7404 * Initializes the class name cache stored in image->name_cache.
7406 * LOCKING: Acquires the corresponding image lock.
7409 mono_image_init_name_cache (MonoImage
*image
)
7411 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
7412 guint32 cols
[MONO_TYPEDEF_SIZE
];
7415 guint32 i
, visib
, nspace_index
;
7416 GHashTable
*name_cache2
, *nspace_table
;
7418 mono_image_lock (image
);
7420 if (image
->name_cache
) {
7421 mono_image_unlock (image
);
7425 image
->name_cache
= g_hash_table_new (g_str_hash
, g_str_equal
);
7427 if (image_is_dynamic (image
)) {
7428 mono_image_unlock (image
);
7432 /* Temporary hash table to avoid lookups in the nspace_table */
7433 name_cache2
= g_hash_table_new (NULL
, NULL
);
7435 for (i
= 1; i
<= t
->rows
; ++i
) {
7436 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
7437 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
7439 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7440 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7442 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
7444 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
7445 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
7447 nspace_index
= cols
[MONO_TYPEDEF_NAMESPACE
];
7448 nspace_table
= g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
7449 if (!nspace_table
) {
7450 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
7451 g_hash_table_insert (image
->name_cache
, (char*)nspace
, nspace_table
);
7452 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
7455 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (i
));
7458 /* Load type names from EXPORTEDTYPES table */
7460 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
7461 guint32 cols
[MONO_EXP_TYPE_SIZE
];
7464 for (i
= 0; i
< t
->rows
; ++i
) {
7465 mono_metadata_decode_row (t
, i
, cols
, MONO_EXP_TYPE_SIZE
);
7466 name
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAME
]);
7467 nspace
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAMESPACE
]);
7469 nspace_index
= cols
[MONO_EXP_TYPE_NAMESPACE
];
7470 nspace_table
= g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
7471 if (!nspace_table
) {
7472 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
7473 g_hash_table_insert (image
->name_cache
, (char*)nspace
, nspace_table
);
7474 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
7477 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE
, i
+ 1)));
7481 g_hash_table_destroy (name_cache2
);
7482 mono_image_unlock (image
);
7485 /*FIXME Only dynamic assemblies should allow this operation.*/
7487 mono_image_add_to_name_cache (MonoImage
*image
, const char *nspace
,
7488 const char *name
, guint32 index
)
7490 GHashTable
*nspace_table
;
7491 GHashTable
*name_cache
;
7494 mono_image_lock (image
);
7496 if (!image
->name_cache
)
7497 mono_image_init_name_cache (image
);
7499 name_cache
= image
->name_cache
;
7500 if (!(nspace_table
= g_hash_table_lookup (name_cache
, nspace
))) {
7501 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
7502 g_hash_table_insert (name_cache
, (char *)nspace
, (char *)nspace_table
);
7505 if ((old_index
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, (char*) name
))))
7506 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index
, image
->name
, nspace
, name
);
7508 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (index
));
7510 mono_image_unlock (image
);
7519 find_nocase (gpointer key
, gpointer value
, gpointer user_data
)
7521 char *name
= (char*)key
;
7522 FindUserData
*data
= (FindUserData
*)user_data
;
7524 if (!data
->value
&& (mono_utf8_strcasecmp (name
, (char*)data
->key
) == 0))
7525 data
->value
= value
;
7529 * mono_class_from_name_case:
7530 * @image: The MonoImage where the type is looked up in
7531 * @name_space: the type namespace
7532 * @name: the type short name.
7533 * @deprecated: use the _checked variant
7535 * Obtains a MonoClass with a given namespace and a given name which
7536 * is located in the given MonoImage. The namespace and name
7537 * lookups are case insensitive.
7540 mono_class_from_name_case (MonoImage
*image
, const char* name_space
, const char *name
)
7543 MonoClass
*res
= mono_class_from_name_case_checked (image
, name_space
, name
, &error
);
7544 g_assert (!mono_error_ok (&error
));
7549 mono_class_from_name_case_checked (MonoImage
*image
, const char* name_space
, const char *name
, MonoError
*error
)
7551 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
7552 guint32 cols
[MONO_TYPEDEF_SIZE
];
7557 mono_error_init (error
);
7559 if (image_is_dynamic (image
)) {
7561 FindUserData user_data
;
7563 mono_image_lock (image
);
7565 if (!image
->name_cache
)
7566 mono_image_init_name_cache (image
);
7568 user_data
.key
= name_space
;
7569 user_data
.value
= NULL
;
7570 g_hash_table_foreach (image
->name_cache
, find_nocase
, &user_data
);
7572 if (user_data
.value
) {
7573 GHashTable
*nspace_table
= (GHashTable
*)user_data
.value
;
7575 user_data
.key
= name
;
7576 user_data
.value
= NULL
;
7578 g_hash_table_foreach (nspace_table
, find_nocase
, &user_data
);
7580 if (user_data
.value
)
7581 token
= GPOINTER_TO_UINT (user_data
.value
);
7584 mono_image_unlock (image
);
7587 return mono_class_get_checked (image
, MONO_TOKEN_TYPE_DEF
| token
, error
);
7593 /* add a cache if needed */
7594 for (i
= 1; i
<= t
->rows
; ++i
) {
7595 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
7596 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
7598 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7599 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7601 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
7603 n
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
7604 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
7605 if (mono_utf8_strcasecmp (n
, name
) == 0 && mono_utf8_strcasecmp (nspace
, name_space
) == 0)
7606 return mono_class_get_checked (image
, MONO_TOKEN_TYPE_DEF
| i
, error
);
7612 return_nested_in (MonoClass
*class, char *nested
)
7615 char *s
= strchr (nested
, '/');
7616 gpointer iter
= NULL
;
7623 while ((found
= mono_class_get_nested_types (class, &iter
))) {
7624 if (strcmp (found
->name
, nested
) == 0) {
7626 return return_nested_in (found
, s
);
7634 search_modules (MonoImage
*image
, const char *name_space
, const char *name
)
7636 MonoTableInfo
*file_table
= &image
->tables
[MONO_TABLE_FILE
];
7637 MonoImage
*file_image
;
7642 * The EXPORTEDTYPES table only contains public types, so have to search the
7644 * Note: image->modules contains the contents of the MODULEREF table, while
7645 * the real module list is in the FILE table.
7647 for (i
= 0; i
< file_table
->rows
; i
++) {
7648 guint32 cols
[MONO_FILE_SIZE
];
7649 mono_metadata_decode_row (file_table
, i
, cols
, MONO_FILE_SIZE
);
7650 if (cols
[MONO_FILE_FLAGS
] == FILE_CONTAINS_NO_METADATA
)
7653 file_image
= mono_image_load_file_for_image (image
, i
+ 1);
7655 class = mono_class_from_name (file_image
, name_space
, name
);
7665 * mono_class_from_name:
7666 * @image: The MonoImage where the type is looked up in
7667 * @name_space: the type namespace
7668 * @name: the type short name.
7670 * Obtains a MonoClass with a given namespace and a given name which
7671 * is located in the given MonoImage.
7673 * To reference nested classes, use the "/" character as a separator.
7674 * For example use "Foo/Bar" to reference the class Bar that is nested
7675 * inside Foo, like this: "class Foo { class Bar {} }".
7678 mono_class_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
7681 GHashTable
*nspace_table
;
7682 MonoImage
*loaded_image
;
7689 if ((nested
= strchr (name
, '/'))) {
7690 int pos
= nested
- name
;
7691 int len
= strlen (name
);
7694 memcpy (buf
, name
, len
+ 1);
7696 nested
= buf
+ pos
+ 1;
7700 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7701 if (get_class_from_name
&& image
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
== 0) {
7702 gboolean res
= get_class_from_name (image
, name_space
, name
, &class);
7705 class = search_modules (image
, name_space
, name
);
7707 return class ? return_nested_in (class, nested
) : NULL
;
7713 mono_image_lock (image
);
7715 if (!image
->name_cache
)
7716 mono_image_init_name_cache (image
);
7718 nspace_table
= g_hash_table_lookup (image
->name_cache
, name_space
);
7721 token
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, name
));
7723 mono_image_unlock (image
);
7725 if (!token
&& image_is_dynamic (image
) && image
->modules
) {
7726 /* Search modules as well */
7727 for (i
= 0; i
< image
->module_count
; ++i
) {
7728 MonoImage
*module
= image
->modules
[i
];
7730 class = mono_class_from_name (module
, name_space
, name
);
7737 class = search_modules (image
, name_space
, name
);
7745 if (mono_metadata_token_table (token
) == MONO_TABLE_EXPORTEDTYPE
) {
7746 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
7747 guint32 cols
[MONO_EXP_TYPE_SIZE
];
7750 idx
= mono_metadata_token_index (token
);
7752 mono_metadata_decode_row (t
, idx
- 1, cols
, MONO_EXP_TYPE_SIZE
);
7754 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
7755 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
) {
7756 loaded_image
= mono_assembly_load_module (image
->assembly
, impl
>> MONO_IMPLEMENTATION_BITS
);
7759 class = mono_class_from_name (loaded_image
, name_space
, name
);
7761 return return_nested_in (class, nested
);
7763 } else if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_ASSEMBLYREF
) {
7764 guint32 assembly_idx
;
7766 assembly_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
7768 mono_assembly_load_reference (image
, assembly_idx
- 1);
7769 g_assert (image
->references
[assembly_idx
- 1]);
7770 if (image
->references
[assembly_idx
- 1] == (gpointer
)-1)
7773 /* FIXME: Cycle detection */
7774 return mono_class_from_name (image
->references
[assembly_idx
- 1]->image
, name_space
, name
);
7776 g_error ("not yet implemented");
7780 token
= MONO_TOKEN_TYPE_DEF
| token
;
7782 class = mono_class_get_checked (image
, token
, &error
);
7783 if (!mono_error_ok (&error
)) {
7784 mono_loader_set_error_from_mono_error (&error
);
7785 mono_error_cleanup (&error
); /* FIXME Don't swallow the error */
7788 return return_nested_in (class, nested
);
7793 * mono_class_is_subclass_of:
7794 * @klass: class to probe if it is a subclass of another one
7795 * @klassc: the class we suspect is the base class
7796 * @check_interfaces: whether we should perform interface checks
7798 * This method determines whether @klass is a subclass of @klassc.
7800 * If the @check_interfaces flag is set, then if @klassc is an interface
7801 * this method return true if the @klass implements the interface or
7802 * if @klass is an interface, if one of its base classes is @klass.
7804 * If @check_interfaces is false then, then if @klass is not an interface
7805 * then it returns true if the @klass is a subclass of @klassc.
7807 * if @klass is an interface and @klassc is System.Object, then this function
7812 mono_class_is_subclass_of (MonoClass
*klass
, MonoClass
*klassc
,
7813 gboolean check_interfaces
)
7815 /*FIXME test for interfaces with variant generic arguments*/
7817 if (check_interfaces
&& MONO_CLASS_IS_INTERFACE (klassc
) && !MONO_CLASS_IS_INTERFACE (klass
)) {
7818 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass
, klassc
->interface_id
))
7820 } else if (check_interfaces
&& MONO_CLASS_IS_INTERFACE (klassc
) && MONO_CLASS_IS_INTERFACE (klass
)) {
7823 for (i
= 0; i
< klass
->interface_count
; i
++) {
7824 MonoClass
*ic
= klass
->interfaces
[i
];
7829 if (!MONO_CLASS_IS_INTERFACE (klass
) && mono_class_has_parent (klass
, klassc
))
7834 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7837 if (klassc
== mono_defaults
.object_class
)
7844 mono_type_is_generic_argument (MonoType
*type
)
7846 return type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
;
7850 mono_class_has_variant_generic_params (MonoClass
*klass
)
7853 MonoGenericContainer
*container
;
7855 if (!klass
->generic_class
)
7858 container
= klass
->generic_class
->container_class
->generic_container
;
7860 for (i
= 0; i
< container
->type_argc
; ++i
)
7861 if (mono_generic_container_get_param_info (container
, i
)->flags
& (MONO_GEN_PARAM_VARIANT
|MONO_GEN_PARAM_COVARIANT
))
7868 mono_gparam_is_reference_conversible (MonoClass
*target
, MonoClass
*candidate
, gboolean check_for_reference_conv
)
7870 if (target
== candidate
)
7873 if (check_for_reference_conv
&&
7874 mono_type_is_generic_argument (&target
->byval_arg
) &&
7875 mono_type_is_generic_argument (&candidate
->byval_arg
)) {
7876 MonoGenericParam
*gparam
= candidate
->byval_arg
.data
.generic_param
;
7877 MonoGenericParamInfo
*pinfo
= mono_generic_param_info (gparam
);
7879 if (!pinfo
|| (pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0)
7882 if (!mono_class_is_assignable_from (target
, candidate
))
7888 * @container the generic container from the GTD
7889 * @klass: the class to be assigned to
7890 * @oklass: the source class
7892 * Both klass and oklass must be instances of the same generic interface.
7893 * Return true if @klass can be assigned to a @klass variable
7896 mono_class_is_variant_compatible (MonoClass
*klass
, MonoClass
*oklass
, gboolean check_for_reference_conv
)
7899 MonoType
**klass_argv
, **oklass_argv
;
7900 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
7901 MonoGenericContainer
*container
= klass_gtd
->generic_container
;
7903 if (klass
== oklass
)
7906 /*Viable candidates are instances of the same generic interface*/
7907 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
7910 klass_argv
= &klass
->generic_class
->context
.class_inst
->type_argv
[0];
7911 oklass_argv
= &oklass
->generic_class
->context
.class_inst
->type_argv
[0];
7913 for (j
= 0; j
< container
->type_argc
; ++j
) {
7914 MonoClass
*param1_class
= mono_class_from_mono_type (klass_argv
[j
]);
7915 MonoClass
*param2_class
= mono_class_from_mono_type (oklass_argv
[j
]);
7917 if (param1_class
->valuetype
!= param2_class
->valuetype
|| (param1_class
->valuetype
&& param1_class
!= param2_class
))
7921 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7922 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7924 if (param1_class
!= param2_class
) {
7925 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
7926 if (!mono_gparam_is_reference_conversible (param1_class
, param2_class
, check_for_reference_conv
))
7928 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
7929 if (!mono_gparam_is_reference_conversible (param2_class
, param1_class
, check_for_reference_conv
))
7939 mono_gparam_is_assignable_from (MonoClass
*target
, MonoClass
*candidate
)
7941 MonoGenericParam
*gparam
, *ogparam
;
7942 MonoGenericParamInfo
*tinfo
, *cinfo
;
7943 MonoClass
**candidate_class
;
7944 gboolean class_constraint_satisfied
, valuetype_constraint_satisfied
;
7947 if (target
== candidate
)
7949 if (target
->byval_arg
.type
!= candidate
->byval_arg
.type
)
7952 gparam
= target
->byval_arg
.data
.generic_param
;
7953 ogparam
= candidate
->byval_arg
.data
.generic_param
;
7954 tinfo
= mono_generic_param_info (gparam
);
7955 cinfo
= mono_generic_param_info (ogparam
);
7957 class_constraint_satisfied
= FALSE
;
7958 valuetype_constraint_satisfied
= FALSE
;
7960 /*candidate must have a super set of target's special constraints*/
7961 tmask
= tinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
7962 cmask
= cinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
7964 if (cinfo
->constraints
) {
7965 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
7966 MonoClass
*cc
= *candidate_class
;
7968 if (mono_type_is_reference (&cc
->byval_arg
) && !MONO_CLASS_IS_INTERFACE (cc
))
7969 class_constraint_satisfied
= TRUE
;
7970 else if (!mono_type_is_reference (&cc
->byval_arg
) && !MONO_CLASS_IS_INTERFACE (cc
))
7971 valuetype_constraint_satisfied
= TRUE
;
7974 class_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) != 0;
7975 valuetype_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0;
7977 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) && !class_constraint_satisfied
)
7979 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) && !valuetype_constraint_satisfied
)
7981 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) && !((cmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) ||
7982 valuetype_constraint_satisfied
)) {
7987 /*candidate type constraints must be a superset of target's*/
7988 if (tinfo
->constraints
) {
7989 MonoClass
**target_class
;
7990 for (target_class
= tinfo
->constraints
; *target_class
; ++target_class
) {
7991 MonoClass
*tc
= *target_class
;
7994 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7995 * check it's constraints since it satisfy the constraint by itself.
7997 if (mono_metadata_type_equal (&tc
->byval_arg
, &candidate
->byval_arg
))
8000 if (!cinfo
->constraints
)
8003 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
8004 MonoClass
*cc
= *candidate_class
;
8006 if (mono_class_is_assignable_from (tc
, cc
))
8010 * This happens when we have the following:
8012 * Bar<K> where K : IFace
8013 * Foo<T, U> where T : U where U : IFace
8015 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8018 if (mono_type_is_generic_argument (&cc
->byval_arg
)) {
8019 if (mono_gparam_is_assignable_from (target
, cc
))
8023 if (!*candidate_class
)
8028 /*candidate itself must have a constraint that satisfy target*/
8029 if (cinfo
->constraints
) {
8030 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
8031 MonoClass
*cc
= *candidate_class
;
8032 if (mono_class_is_assignable_from (target
, cc
))
8040 * mono_class_is_assignable_from:
8041 * @klass: the class to be assigned to
8042 * @oklass: the source class
8044 * Return: true if an instance of object oklass can be assigned to an
8045 * instance of object @klass
8048 mono_class_is_assignable_from (MonoClass
*klass
, MonoClass
*oklass
)
8050 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8052 mono_class_init (klass
);
8054 if (!oklass
->inited
)
8055 mono_class_init (oklass
);
8057 if (klass
->exception_type
|| oklass
->exception_type
)
8060 if (mono_type_is_generic_argument (&klass
->byval_arg
)) {
8061 if (!mono_type_is_generic_argument (&oklass
->byval_arg
))
8063 return mono_gparam_is_assignable_from (klass
, oklass
);
8066 if (MONO_CLASS_IS_INTERFACE (klass
)) {
8067 if ((oklass
->byval_arg
.type
== MONO_TYPE_VAR
) || (oklass
->byval_arg
.type
== MONO_TYPE_MVAR
)) {
8068 MonoGenericParam
*gparam
= oklass
->byval_arg
.data
.generic_param
;
8069 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
8073 for (i
= 0; constraints
[i
]; ++i
) {
8074 if (mono_class_is_assignable_from (klass
, constraints
[i
]))
8082 /* interface_offsets might not be set for dynamic classes */
8083 if (oklass
->ref_info_handle
&& !oklass
->interface_bitmap
)
8085 * oklass might be a generic type parameter but they have
8086 * interface_offsets set.
8088 return mono_reflection_call_is_assignable_to (oklass
, klass
);
8089 if (!oklass
->interface_bitmap
)
8090 /* Happens with generic instances of not-yet created dynamic types */
8092 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass
, klass
->interface_id
))
8095 if (mono_class_has_variant_generic_params (klass
)) {
8098 mono_class_setup_interfaces (oklass
, &error
);
8099 if (!mono_error_ok (&error
)) {
8100 mono_error_cleanup (&error
);
8104 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8105 for (i
= 0; i
< oklass
->interface_offsets_count
; ++i
) {
8106 MonoClass
*iface
= oklass
->interfaces_packed
[i
];
8108 if (mono_class_is_variant_compatible (klass
, iface
, FALSE
))
8113 } else if (klass
->delegate
) {
8114 if (mono_class_has_variant_generic_params (klass
) && mono_class_is_variant_compatible (klass
, oklass
, FALSE
))
8116 }else if (klass
->rank
) {
8117 MonoClass
*eclass
, *eoclass
;
8119 if (oklass
->rank
!= klass
->rank
)
8122 /* vectors vs. one dimensional arrays */
8123 if (oklass
->byval_arg
.type
!= klass
->byval_arg
.type
)
8126 eclass
= klass
->cast_class
;
8127 eoclass
= oklass
->cast_class
;
8130 * a is b does not imply a[] is b[] when a is a valuetype, and
8131 * b is a reference type.
8134 if (eoclass
->valuetype
) {
8135 if ((eclass
== mono_defaults
.enum_class
) ||
8136 (eclass
== mono_defaults
.enum_class
->parent
) ||
8137 (eclass
== mono_defaults
.object_class
))
8141 return mono_class_is_assignable_from (klass
->cast_class
, oklass
->cast_class
);
8142 } else if (mono_class_is_nullable (klass
)) {
8143 if (mono_class_is_nullable (oklass
))
8144 return mono_class_is_assignable_from (klass
->cast_class
, oklass
->cast_class
);
8146 return mono_class_is_assignable_from (klass
->cast_class
, oklass
);
8147 } else if (klass
== mono_defaults
.object_class
)
8150 return mono_class_has_parent (oklass
, klass
);
8153 /*Check if @oklass is variant compatible with @klass.*/
8155 mono_class_is_variant_compatible_slow (MonoClass
*klass
, MonoClass
*oklass
)
8158 MonoType
**klass_argv
, **oklass_argv
;
8159 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
8160 MonoGenericContainer
*container
= klass_gtd
->generic_container
;
8162 /*Viable candidates are instances of the same generic interface*/
8163 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
8166 klass_argv
= &klass
->generic_class
->context
.class_inst
->type_argv
[0];
8167 oklass_argv
= &oklass
->generic_class
->context
.class_inst
->type_argv
[0];
8169 for (j
= 0; j
< container
->type_argc
; ++j
) {
8170 MonoClass
*param1_class
= mono_class_from_mono_type (klass_argv
[j
]);
8171 MonoClass
*param2_class
= mono_class_from_mono_type (oklass_argv
[j
]);
8173 if (param1_class
->valuetype
!= param2_class
->valuetype
)
8177 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8178 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8180 if (param1_class
!= param2_class
) {
8181 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
8182 if (!mono_class_is_assignable_from_slow (param1_class
, param2_class
))
8184 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
8185 if (!mono_class_is_assignable_from_slow (param2_class
, param1_class
))
8193 /*Check if @candidate implements the interface @target*/
8195 mono_class_implement_interface_slow (MonoClass
*target
, MonoClass
*candidate
)
8199 gboolean is_variant
= mono_class_has_variant_generic_params (target
);
8201 if (is_variant
&& MONO_CLASS_IS_INTERFACE (candidate
)) {
8202 if (mono_class_is_variant_compatible_slow (target
, candidate
))
8207 if (candidate
== target
)
8210 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8211 if (image_is_dynamic (candidate
->image
) && !candidate
->wastypebuilder
) {
8212 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info (candidate
);
8214 if (tb
&& tb
->interfaces
) {
8215 for (j
= mono_array_length (tb
->interfaces
) - 1; j
>= 0; --j
) {
8216 MonoReflectionType
*iface
= mono_array_get (tb
->interfaces
, MonoReflectionType
*, j
);
8217 MonoClass
*iface_class
;
8219 /* we can't realize the type here since it can do pretty much anything. */
8222 iface_class
= mono_class_from_mono_type (iface
->type
);
8223 if (iface_class
== target
)
8225 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, iface_class
))
8227 if (mono_class_implement_interface_slow (target
, iface_class
))
8232 /*setup_interfaces don't mono_class_init anything*/
8233 /*FIXME this doesn't handle primitive type arrays.
8234 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8235 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8237 mono_class_setup_interfaces (candidate
, &error
);
8238 if (!mono_error_ok (&error
)) {
8239 mono_error_cleanup (&error
);
8243 for (i
= 0; i
< candidate
->interface_count
; ++i
) {
8244 if (candidate
->interfaces
[i
] == target
)
8247 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, candidate
->interfaces
[i
]))
8250 if (mono_class_implement_interface_slow (target
, candidate
->interfaces
[i
]))
8254 candidate
= candidate
->parent
;
8255 } while (candidate
);
8261 * Check if @oklass can be assigned to @klass.
8262 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8265 mono_class_is_assignable_from_slow (MonoClass
*target
, MonoClass
*candidate
)
8267 if (candidate
== target
)
8269 if (target
== mono_defaults
.object_class
)
8272 if (mono_class_has_parent (candidate
, target
))
8275 /*If target is not an interface there is no need to check them.*/
8276 if (MONO_CLASS_IS_INTERFACE (target
))
8277 return mono_class_implement_interface_slow (target
, candidate
);
8279 if (target
->delegate
&& mono_class_has_variant_generic_params (target
))
8280 return mono_class_is_variant_compatible (target
, candidate
, FALSE
);
8283 MonoClass
*eclass
, *eoclass
;
8285 if (target
->rank
!= candidate
->rank
)
8288 /* vectors vs. one dimensional arrays */
8289 if (target
->byval_arg
.type
!= candidate
->byval_arg
.type
)
8292 eclass
= target
->cast_class
;
8293 eoclass
= candidate
->cast_class
;
8296 * a is b does not imply a[] is b[] when a is a valuetype, and
8297 * b is a reference type.
8300 if (eoclass
->valuetype
) {
8301 if ((eclass
== mono_defaults
.enum_class
) ||
8302 (eclass
== mono_defaults
.enum_class
->parent
) ||
8303 (eclass
== mono_defaults
.object_class
))
8307 return mono_class_is_assignable_from_slow (target
->cast_class
, candidate
->cast_class
);
8309 /*FIXME properly handle nullables */
8310 /*FIXME properly handle (M)VAR */
8315 * mono_class_get_cctor:
8316 * @klass: A MonoClass pointer
8318 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8321 mono_class_get_cctor (MonoClass
*klass
)
8323 MonoCachedClassInfo cached_info
;
8325 if (image_is_dynamic (klass
->image
)) {
8327 * has_cctor is not set for these classes because mono_class_init () is
8330 return mono_class_get_method_from_name_flags (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
);
8333 if (!klass
->has_cctor
)
8336 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
8338 MonoMethod
*result
= mono_get_method_checked (klass
->image
, cached_info
.cctor_token
, klass
, NULL
, &error
);
8339 if (!mono_error_ok (&error
))
8340 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error
));
8344 if (klass
->generic_class
&& !klass
->methods
)
8345 return mono_class_get_inflated_method (klass
, mono_class_get_cctor (klass
->generic_class
->container_class
));
8347 return mono_class_get_method_from_name_flags (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
);
8351 * mono_class_get_finalizer:
8352 * @klass: The MonoClass pointer
8354 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8357 mono_class_get_finalizer (MonoClass
*klass
)
8359 MonoCachedClassInfo cached_info
;
8362 mono_class_init (klass
);
8363 if (!mono_class_has_finalizer (klass
))
8366 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
8368 MonoMethod
*result
= mono_get_method_checked (cached_info
.finalize_image
, cached_info
.finalize_token
, NULL
, NULL
, &error
);
8369 if (!mono_error_ok (&error
))
8370 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error
));
8373 mono_class_setup_vtable (klass
);
8374 return klass
->vtable
[finalize_slot
];
8379 * mono_class_needs_cctor_run:
8380 * @klass: the MonoClass pointer
8381 * @caller: a MonoMethod describing the caller
8383 * Determines whenever the class has a static constructor and whenever it
8384 * needs to be called when executing CALLER.
8387 mono_class_needs_cctor_run (MonoClass
*klass
, MonoMethod
*caller
)
8391 method
= mono_class_get_cctor (klass
);
8393 return (method
== caller
) ? FALSE
: TRUE
;
8399 * mono_class_array_element_size:
8402 * Returns: the number of bytes an element of type @klass
8403 * uses when stored into an array.
8406 mono_class_array_element_size (MonoClass
*klass
)
8408 MonoType
*type
= &klass
->byval_arg
;
8411 switch (type
->type
) {
8414 case MONO_TYPE_BOOLEAN
:
8418 case MONO_TYPE_CHAR
:
8427 case MONO_TYPE_CLASS
:
8428 case MONO_TYPE_STRING
:
8429 case MONO_TYPE_OBJECT
:
8430 case MONO_TYPE_SZARRAY
:
8431 case MONO_TYPE_ARRAY
:
8433 case MONO_TYPE_MVAR
:
8434 return sizeof (gpointer
);
8439 case MONO_TYPE_VALUETYPE
:
8440 if (type
->data
.klass
->enumtype
) {
8441 type
= mono_class_enum_basetype (type
->data
.klass
);
8442 klass
= klass
->element_class
;
8445 return mono_class_instance_size (klass
) - sizeof (MonoObject
);
8446 case MONO_TYPE_GENERICINST
:
8447 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
8450 case MONO_TYPE_VOID
:
8454 g_error ("unknown type 0x%02x in mono_class_array_element_size", type
->type
);
8460 * mono_array_element_size:
8461 * @ac: pointer to a #MonoArrayClass
8463 * Returns: the size of single array element.
8466 mono_array_element_size (MonoClass
*ac
)
8468 g_assert (ac
->rank
);
8469 return ac
->sizes
.element_size
;
8473 mono_ldtoken (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
8474 MonoGenericContext
*context
)
8477 gpointer res
= mono_ldtoken_checked (image
, token
, handle_class
, context
, &error
);
8478 g_assert (mono_error_ok (&error
));
8483 mono_ldtoken_checked (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
8484 MonoGenericContext
*context
, MonoError
*error
)
8486 mono_error_init (error
);
8488 if (image_is_dynamic (image
)) {
8489 MonoClass
*tmp_handle_class
;
8490 gpointer obj
= mono_lookup_dynamic_token_class (image
, token
, TRUE
, &tmp_handle_class
, context
);
8492 g_assert (tmp_handle_class
);
8494 *handle_class
= tmp_handle_class
;
8496 if (tmp_handle_class
== mono_defaults
.typehandle_class
)
8497 return &((MonoClass
*)obj
)->byval_arg
;
8502 switch (token
& 0xff000000) {
8503 case MONO_TOKEN_TYPE_DEF
:
8504 case MONO_TOKEN_TYPE_REF
:
8505 case MONO_TOKEN_TYPE_SPEC
: {
8508 *handle_class
= mono_defaults
.typehandle_class
;
8509 type
= mono_type_get_checked (image
, token
, context
, error
);
8513 mono_class_init (mono_class_from_mono_type (type
));
8514 /* We return a MonoType* as handle */
8517 case MONO_TOKEN_FIELD_DEF
: {
8519 guint32 type
= mono_metadata_typedef_from_field (image
, mono_metadata_token_index (token
));
8521 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
8525 *handle_class
= mono_defaults
.fieldhandle_class
;
8526 class = mono_class_get_and_inflate_typespec_checked (image
, MONO_TOKEN_TYPE_DEF
| type
, context
, error
);
8530 mono_class_init (class);
8531 return mono_class_get_field (class, token
);
8533 case MONO_TOKEN_METHOD_DEF
:
8534 case MONO_TOKEN_METHOD_SPEC
: {
8536 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
8538 *handle_class
= mono_defaults
.methodhandle_class
;
8544 case MONO_TOKEN_MEMBER_REF
: {
8545 guint32 cols
[MONO_MEMBERREF_SIZE
];
8547 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
8548 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
8549 mono_metadata_decode_blob_size (sig
, &sig
);
8550 if (*sig
== 0x6) { /* it's a field */
8552 MonoClassField
*field
;
8553 field
= mono_field_from_token_checked (image
, token
, &klass
, context
, error
);
8555 *handle_class
= mono_defaults
.fieldhandle_class
;
8559 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
8561 *handle_class
= mono_defaults
.methodhandle_class
;
8566 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
8572 * This function might need to call runtime functions so it can't be part
8573 * of the metadata library.
8575 static MonoLookupDynamicToken lookup_dynamic
= NULL
;
8578 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func
)
8580 lookup_dynamic
= func
;
8584 mono_lookup_dynamic_token (MonoImage
*image
, guint32 token
, MonoGenericContext
*context
)
8586 MonoClass
*handle_class
;
8588 return lookup_dynamic (image
, token
, TRUE
, &handle_class
, context
);
8592 mono_lookup_dynamic_token_class (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
8594 return lookup_dynamic (image
, token
, valid_token
, handle_class
, context
);
8597 static MonoGetCachedClassInfo get_cached_class_info
= NULL
;
8600 mono_install_get_cached_class_info (MonoGetCachedClassInfo func
)
8602 get_cached_class_info
= func
;
8606 mono_class_get_cached_class_info (MonoClass
*klass
, MonoCachedClassInfo
*res
)
8608 if (!get_cached_class_info
)
8611 return get_cached_class_info (klass
, res
);
8615 mono_install_get_class_from_name (MonoGetClassFromName func
)
8617 get_class_from_name
= func
;
8621 mono_class_get_image (MonoClass
*klass
)
8623 return klass
->image
;
8627 * mono_class_get_element_class:
8628 * @klass: the MonoClass to act on
8630 * Returns: the element class of an array or an enumeration.
8633 mono_class_get_element_class (MonoClass
*klass
)
8635 return klass
->element_class
;
8639 * mono_class_is_valuetype:
8640 * @klass: the MonoClass to act on
8642 * Returns: true if the MonoClass represents a ValueType.
8645 mono_class_is_valuetype (MonoClass
*klass
)
8647 return klass
->valuetype
;
8651 * mono_class_is_enum:
8652 * @klass: the MonoClass to act on
8654 * Returns: true if the MonoClass represents an enumeration.
8657 mono_class_is_enum (MonoClass
*klass
)
8659 return klass
->enumtype
;
8663 * mono_class_enum_basetype:
8664 * @klass: the MonoClass to act on
8666 * Returns: the underlying type representation for an enumeration.
8669 mono_class_enum_basetype (MonoClass
*klass
)
8671 if (klass
->element_class
== klass
)
8672 /* SRE or broken types */
8675 return &klass
->element_class
->byval_arg
;
8679 * mono_class_get_parent
8680 * @klass: the MonoClass to act on
8682 * Returns: the parent class for this class.
8685 mono_class_get_parent (MonoClass
*klass
)
8687 return klass
->parent
;
8691 * mono_class_get_nesting_type;
8692 * @klass: the MonoClass to act on
8694 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8697 mono_class_get_nesting_type (MonoClass
*klass
)
8699 return klass
->nested_in
;
8703 * mono_class_get_rank:
8704 * @klass: the MonoClass to act on
8706 * Returns: the rank for the array (the number of dimensions).
8709 mono_class_get_rank (MonoClass
*klass
)
8715 * mono_class_get_flags:
8716 * @klass: the MonoClass to act on
8718 * The type flags from the TypeDef table from the metadata.
8719 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8722 * Returns: the flags from the TypeDef table.
8725 mono_class_get_flags (MonoClass
*klass
)
8727 return klass
->flags
;
8731 * mono_class_get_name
8732 * @klass: the MonoClass to act on
8734 * Returns: the name of the class.
8737 mono_class_get_name (MonoClass
*klass
)
8743 * mono_class_get_namespace:
8744 * @klass: the MonoClass to act on
8746 * Returns: the namespace of the class.
8749 mono_class_get_namespace (MonoClass
*klass
)
8751 return klass
->name_space
;
8755 * mono_class_get_type:
8756 * @klass: the MonoClass to act on
8758 * This method returns the internal Type representation for the class.
8760 * Returns: the MonoType from the class.
8763 mono_class_get_type (MonoClass
*klass
)
8765 return &klass
->byval_arg
;
8769 * mono_class_get_type_token
8770 * @klass: the MonoClass to act on
8772 * This method returns type token for the class.
8774 * Returns: the type token for the class.
8777 mono_class_get_type_token (MonoClass
*klass
)
8779 return klass
->type_token
;
8783 * mono_class_get_byref_type:
8784 * @klass: the MonoClass to act on
8789 mono_class_get_byref_type (MonoClass
*klass
)
8791 return &klass
->this_arg
;
8795 * mono_class_num_fields:
8796 * @klass: the MonoClass to act on
8798 * Returns: the number of static and instance fields in the class.
8801 mono_class_num_fields (MonoClass
*klass
)
8803 return klass
->field
.count
;
8807 * mono_class_num_methods:
8808 * @klass: the MonoClass to act on
8810 * Returns: the number of methods in the class.
8813 mono_class_num_methods (MonoClass
*klass
)
8815 return klass
->method
.count
;
8819 * mono_class_num_properties
8820 * @klass: the MonoClass to act on
8822 * Returns: the number of properties in the class.
8825 mono_class_num_properties (MonoClass
*klass
)
8827 mono_class_setup_properties (klass
);
8829 return klass
->ext
->property
.count
;
8833 * mono_class_num_events:
8834 * @klass: the MonoClass to act on
8836 * Returns: the number of events in the class.
8839 mono_class_num_events (MonoClass
*klass
)
8841 mono_class_setup_events (klass
);
8843 return klass
->ext
->event
.count
;
8847 * mono_class_get_fields:
8848 * @klass: the MonoClass to act on
8850 * This routine is an iterator routine for retrieving the fields in a class.
8852 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8853 * iterate over all of the elements. When no more values are
8854 * available, the return value is NULL.
8856 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8859 mono_class_get_fields (MonoClass
* klass
, gpointer
*iter
)
8861 MonoClassField
* field
;
8865 mono_class_setup_fields_locking (klass
);
8866 if (klass
->exception_type
)
8868 /* start from the first */
8869 if (klass
->field
.count
) {
8870 return *iter
= &klass
->fields
[0];
8878 if (field
< &klass
->fields
[klass
->field
.count
]) {
8879 return *iter
= field
;
8885 * mono_class_get_methods
8886 * @klass: the MonoClass to act on
8888 * This routine is an iterator routine for retrieving the fields in a class.
8890 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8891 * iterate over all of the elements. When no more values are
8892 * available, the return value is NULL.
8894 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8897 mono_class_get_methods (MonoClass
* klass
, gpointer
*iter
)
8899 MonoMethod
** method
;
8903 mono_class_setup_methods (klass
);
8906 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8907 * FIXME we should better report this error to the caller
8909 if (!klass
->methods
)
8911 /* start from the first */
8912 if (klass
->method
.count
) {
8913 *iter
= &klass
->methods
[0];
8914 return klass
->methods
[0];
8922 if (method
< &klass
->methods
[klass
->method
.count
]) {
8930 * mono_class_get_virtual_methods:
8932 * Iterate over the virtual methods of KLASS.
8934 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8937 mono_class_get_virtual_methods (MonoClass
* klass
, gpointer
*iter
)
8939 MonoMethod
** method
;
8942 if (klass
->methods
|| !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
8944 mono_class_setup_methods (klass
);
8946 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8947 * FIXME we should better report this error to the caller
8949 if (!klass
->methods
)
8951 /* start from the first */
8952 method
= &klass
->methods
[0];
8957 while (method
< &klass
->methods
[klass
->method
.count
]) {
8958 if (*method
&& ((*method
)->flags
& METHOD_ATTRIBUTE_VIRTUAL
))
8962 if (method
< &klass
->methods
[klass
->method
.count
]) {
8969 /* Search directly in metadata to avoid calling setup_methods () */
8970 MonoMethod
*res
= NULL
;
8976 start_index
= GPOINTER_TO_UINT (*iter
);
8979 for (i
= start_index
; i
< klass
->method
.count
; ++i
) {
8982 /* class->method.first points into the methodptr table */
8983 flags
= mono_metadata_decode_table_row_col (klass
->image
, MONO_TABLE_METHOD
, klass
->method
.first
+ i
, MONO_METHOD_FLAGS
);
8985 if (flags
& METHOD_ATTRIBUTE_VIRTUAL
)
8989 if (i
< klass
->method
.count
) {
8991 res
= mono_get_method_checked (klass
->image
, MONO_TOKEN_METHOD_DEF
| (klass
->method
.first
+ i
+ 1), klass
, NULL
, &error
);
8992 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
8994 /* Add 1 here so the if (*iter) check fails */
8995 *iter
= GUINT_TO_POINTER (i
+ 1);
9004 * mono_class_get_properties:
9005 * @klass: the MonoClass to act on
9007 * This routine is an iterator routine for retrieving the properties in a class.
9009 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9010 * iterate over all of the elements. When no more values are
9011 * available, the return value is NULL.
9013 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9016 mono_class_get_properties (MonoClass
* klass
, gpointer
*iter
)
9018 MonoProperty
* property
;
9022 mono_class_setup_properties (klass
);
9023 /* start from the first */
9024 if (klass
->ext
->property
.count
) {
9025 return *iter
= &klass
->ext
->properties
[0];
9033 if (property
< &klass
->ext
->properties
[klass
->ext
->property
.count
]) {
9034 return *iter
= property
;
9040 * mono_class_get_events:
9041 * @klass: the MonoClass to act on
9043 * This routine is an iterator routine for retrieving the properties in a class.
9045 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9046 * iterate over all of the elements. When no more values are
9047 * available, the return value is NULL.
9049 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9052 mono_class_get_events (MonoClass
* klass
, gpointer
*iter
)
9058 mono_class_setup_events (klass
);
9059 /* start from the first */
9060 if (klass
->ext
->event
.count
) {
9061 return *iter
= &klass
->ext
->events
[0];
9069 if (event
< &klass
->ext
->events
[klass
->ext
->event
.count
]) {
9070 return *iter
= event
;
9076 * mono_class_get_interfaces
9077 * @klass: the MonoClass to act on
9079 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9081 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9082 * iterate over all of the elements. When no more values are
9083 * available, the return value is NULL.
9085 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9088 mono_class_get_interfaces (MonoClass
* klass
, gpointer
*iter
)
9096 mono_class_init (klass
);
9097 if (!klass
->interfaces_inited
) {
9098 mono_class_setup_interfaces (klass
, &error
);
9099 if (!mono_error_ok (&error
)) {
9100 mono_error_cleanup (&error
);
9104 /* start from the first */
9105 if (klass
->interface_count
) {
9106 *iter
= &klass
->interfaces
[0];
9107 return klass
->interfaces
[0];
9115 if (iface
< &klass
->interfaces
[klass
->interface_count
]) {
9123 setup_nested_types (MonoClass
*klass
)
9126 GList
*classes
, *nested_classes
, *l
;
9129 if (klass
->nested_classes_inited
)
9132 if (!klass
->type_token
)
9133 klass
->nested_classes_inited
= TRUE
;
9135 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, 1);
9139 guint32 cols
[MONO_NESTED_CLASS_SIZE
];
9140 mono_metadata_decode_row (&klass
->image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, cols
, MONO_NESTED_CLASS_SIZE
);
9141 nclass
= mono_class_create_from_typedef (klass
->image
, MONO_TOKEN_TYPE_DEF
| cols
[MONO_NESTED_CLASS_NESTED
], &error
);
9142 if (!mono_error_ok (&error
)) {
9143 /*FIXME don't swallow the error message*/
9144 mono_error_cleanup (&error
);
9146 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, i
+ 1);
9150 classes
= g_list_prepend (classes
, nclass
);
9152 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, i
+ 1);
9155 mono_class_alloc_ext (klass
);
9157 nested_classes
= NULL
;
9158 for (l
= classes
; l
; l
= l
->next
)
9159 nested_classes
= g_list_prepend_image (klass
->image
, nested_classes
, l
->data
);
9160 g_list_free (classes
);
9162 mono_image_lock (klass
->image
);
9164 mono_memory_barrier ();
9165 if (!klass
->nested_classes_inited
) {
9166 klass
->ext
->nested_classes
= nested_classes
;
9167 mono_memory_barrier ();
9168 klass
->nested_classes_inited
= TRUE
;
9171 mono_image_unlock (klass
->image
);
9175 * mono_class_get_nested_types
9176 * @klass: the MonoClass to act on
9178 * This routine is an iterator routine for retrieving the nested types of a class.
9179 * This works only if @klass is non-generic, or a generic type definition.
9181 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9182 * iterate over all of the elements. When no more values are
9183 * available, the return value is NULL.
9185 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9188 mono_class_get_nested_types (MonoClass
* klass
, gpointer
*iter
)
9194 if (!klass
->nested_classes_inited
)
9195 setup_nested_types (klass
);
9198 /* start from the first */
9199 if (klass
->ext
&& klass
->ext
->nested_classes
) {
9200 *iter
= klass
->ext
->nested_classes
;
9201 return klass
->ext
->nested_classes
->data
;
9203 /* no nested types */
9218 * mono_class_is_delegate
9219 * @klass: the MonoClass to act on
9221 * Returns: true if the MonoClass represents a System.Delegate.
9224 mono_class_is_delegate (MonoClass
*klass
)
9226 return klass
->delegate
;
9230 * mono_class_implements_interface
9231 * @klass: The MonoClass to act on
9232 * @interface: The interface to check if @klass implements.
9234 * Returns: true if @klass implements @interface.
9237 mono_class_implements_interface (MonoClass
* klass
, MonoClass
* iface
)
9239 return mono_class_is_assignable_from (iface
, klass
);
9243 * mono_field_get_name:
9244 * @field: the MonoClassField to act on
9246 * Returns: the name of the field.
9249 mono_field_get_name (MonoClassField
*field
)
9255 * mono_field_get_type:
9256 * @field: the MonoClassField to act on
9258 * Returns: MonoType of the field.
9261 mono_field_get_type (MonoClassField
*field
)
9264 MonoType
*type
= mono_field_get_type_checked (field
, &error
);
9265 if (!mono_error_ok (&error
)) {
9266 mono_trace_warning (MONO_TRACE_TYPE
, "Could not load field's type due to %s", mono_error_get_message (&error
));
9267 mono_error_cleanup (&error
);
9274 * mono_field_get_type_checked:
9275 * @field: the MonoClassField to act on
9276 * @error: used to return any erro found while retrieving @field type
9278 * Returns: MonoType of the field.
9281 mono_field_get_type_checked (MonoClassField
*field
, MonoError
*error
)
9283 mono_error_init (error
);
9285 mono_field_resolve_type (field
, error
);
9290 * mono_field_get_parent:
9291 * @field: the MonoClassField to act on
9293 * Returns: MonoClass where the field was defined.
9296 mono_field_get_parent (MonoClassField
*field
)
9298 return field
->parent
;
9302 * mono_field_get_flags;
9303 * @field: the MonoClassField to act on
9305 * The metadata flags for a field are encoded using the
9306 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9308 * Returns: the flags for the field.
9311 mono_field_get_flags (MonoClassField
*field
)
9314 return mono_field_resolve_flags (field
);
9315 return field
->type
->attrs
;
9319 * mono_field_get_offset;
9320 * @field: the MonoClassField to act on
9322 * Returns: the field offset.
9325 mono_field_get_offset (MonoClassField
*field
)
9327 return field
->offset
;
9331 mono_field_get_rva (MonoClassField
*field
)
9335 MonoClass
*klass
= field
->parent
;
9336 MonoFieldDefaultValue
*field_def_values
;
9338 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
);
9340 if (!klass
->ext
|| !klass
->ext
->field_def_values
) {
9341 mono_class_alloc_ext (klass
);
9343 field_def_values
= mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * klass
->field
.count
);
9345 mono_image_lock (klass
->image
);
9346 if (!klass
->ext
->field_def_values
)
9347 klass
->ext
->field_def_values
= field_def_values
;
9348 mono_image_unlock (klass
->image
);
9351 field_index
= mono_field_get_index (field
);
9353 if (!klass
->ext
->field_def_values
[field_index
].data
&& !image_is_dynamic (klass
->image
)) {
9354 mono_metadata_field_info (field
->parent
->image
, klass
->field
.first
+ field_index
, NULL
, &rva
, NULL
);
9356 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field
), field
->parent
->name
);
9357 klass
->ext
->field_def_values
[field_index
].data
= mono_image_rva_map (field
->parent
->image
, rva
);
9360 return klass
->ext
->field_def_values
[field_index
].data
;
9364 * mono_field_get_data;
9365 * @field: the MonoClassField to act on
9367 * Returns: pointer to the metadata constant value or to the field
9368 * data if it has an RVA flag.
9371 mono_field_get_data (MonoClassField
*field
)
9373 if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
) {
9374 MonoTypeEnum def_type
;
9376 return mono_class_get_field_default_value (field
, &def_type
);
9377 } else if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
9378 return mono_field_get_rva (field
);
9385 * mono_property_get_name:
9386 * @prop: the MonoProperty to act on
9388 * Returns: the name of the property
9391 mono_property_get_name (MonoProperty
*prop
)
9397 * mono_property_get_set_method
9398 * @prop: the MonoProperty to act on.
9400 * Returns: the setter method of the property (A MonoMethod)
9403 mono_property_get_set_method (MonoProperty
*prop
)
9409 * mono_property_get_get_method
9410 * @prop: the MonoProperty to act on.
9412 * Returns: the setter method of the property (A MonoMethod)
9415 mono_property_get_get_method (MonoProperty
*prop
)
9421 * mono_property_get_parent:
9422 * @prop: the MonoProperty to act on.
9424 * Returns: the MonoClass where the property was defined.
9427 mono_property_get_parent (MonoProperty
*prop
)
9429 return prop
->parent
;
9433 * mono_property_get_flags:
9434 * @prop: the MonoProperty to act on.
9436 * The metadata flags for a property are encoded using the
9437 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9439 * Returns: the flags for the property.
9442 mono_property_get_flags (MonoProperty
*prop
)
9448 * mono_event_get_name:
9449 * @event: the MonoEvent to act on
9451 * Returns: the name of the event.
9454 mono_event_get_name (MonoEvent
*event
)
9460 * mono_event_get_add_method:
9461 * @event: The MonoEvent to act on.
9463 * Returns: the @add' method for the event (a MonoMethod).
9466 mono_event_get_add_method (MonoEvent
*event
)
9472 * mono_event_get_remove_method:
9473 * @event: The MonoEvent to act on.
9475 * Returns: the @remove method for the event (a MonoMethod).
9478 mono_event_get_remove_method (MonoEvent
*event
)
9480 return event
->remove
;
9484 * mono_event_get_raise_method:
9485 * @event: The MonoEvent to act on.
9487 * Returns: the @raise method for the event (a MonoMethod).
9490 mono_event_get_raise_method (MonoEvent
*event
)
9492 return event
->raise
;
9496 * mono_event_get_parent:
9497 * @event: the MonoEvent to act on.
9499 * Returns: the MonoClass where the event is defined.
9502 mono_event_get_parent (MonoEvent
*event
)
9504 return event
->parent
;
9508 * mono_event_get_flags
9509 * @event: the MonoEvent to act on.
9511 * The metadata flags for an event are encoded using the
9512 * EVENT_* constants. See the tabledefs.h file for details.
9514 * Returns: the flags for the event.
9517 mono_event_get_flags (MonoEvent
*event
)
9519 return event
->attrs
;
9523 * mono_class_get_method_from_name:
9524 * @klass: where to look for the method
9525 * @name: name of the method
9526 * @param_count: number of parameters. -1 for any number.
9528 * Obtains a MonoMethod with a given name and number of parameters.
9529 * It only works if there are no multiple signatures for any given method name.
9532 mono_class_get_method_from_name (MonoClass
*klass
, const char *name
, int param_count
)
9534 return mono_class_get_method_from_name_flags (klass
, name
, param_count
, 0);
9538 find_method_in_metadata (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
9540 MonoMethod
*res
= NULL
;
9543 /* Search directly in the metadata to avoid calling setup_methods () */
9544 for (i
= 0; i
< klass
->method
.count
; ++i
) {
9546 guint32 cols
[MONO_METHOD_SIZE
];
9548 MonoMethodSignature
*sig
;
9550 /* class->method.first points into the methodptr table */
9551 mono_metadata_decode_table_row (klass
->image
, MONO_TABLE_METHOD
, klass
->method
.first
+ i
, cols
, MONO_METHOD_SIZE
);
9553 if (!strcmp (mono_metadata_string_heap (klass
->image
, cols
[MONO_METHOD_NAME
]), name
)) {
9554 method
= mono_get_method_checked (klass
->image
, MONO_TOKEN_METHOD_DEF
| (klass
->method
.first
+ i
+ 1), klass
, NULL
, &error
);
9556 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
9559 if (param_count
== -1) {
9563 sig
= mono_method_signature_checked (method
, &error
);
9565 mono_error_cleanup (&error
); /* FIXME don't swallow the error */
9568 if (sig
->param_count
== param_count
) {
9579 * mono_class_get_method_from_name_flags:
9580 * @klass: where to look for the method
9581 * @name_space: name of the method
9582 * @param_count: number of parameters. -1 for any number.
9583 * @flags: flags which must be set in the method
9585 * Obtains a MonoMethod with a given name and number of parameters.
9586 * It only works if there are no multiple signatures for any given method name.
9589 mono_class_get_method_from_name_flags (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
9591 MonoMethod
*res
= NULL
;
9594 mono_class_init (klass
);
9596 if (klass
->generic_class
&& !klass
->methods
) {
9597 res
= mono_class_get_method_from_name_flags (klass
->generic_class
->container_class
, name
, param_count
, flags
);
9600 res
= mono_class_inflate_generic_method_full_checked (res
, klass
, mono_class_get_context (klass
), &error
);
9601 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
9606 if (klass
->methods
|| !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
9607 mono_class_setup_methods (klass
);
9609 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9610 See mono/tests/array_load_exception.il
9611 FIXME we should better report this error to the caller
9613 if (!klass
->methods
)
9615 for (i
= 0; i
< klass
->method
.count
; ++i
) {
9616 MonoMethod
*method
= klass
->methods
[i
];
9618 if (method
->name
[0] == name
[0] &&
9619 !strcmp (name
, method
->name
) &&
9620 (param_count
== -1 || mono_method_signature (method
)->param_count
== param_count
) &&
9621 ((method
->flags
& flags
) == flags
)) {
9628 res
= find_method_in_metadata (klass
, name
, param_count
, flags
);
9635 * mono_class_set_failure:
9636 * @klass: class in which the failure was detected
9637 * @ex_type: the kind of exception/error to be thrown (later)
9638 * @ex_data: exception data (specific to each type of exception/error)
9640 * Keep a detected failure informations in the class for later processing.
9641 * Note that only the first failure is kept.
9643 * LOCKING: Acquires the loader lock.
9646 mono_class_set_failure (MonoClass
*klass
, guint32 ex_type
, void *ex_data
)
9648 if (klass
->exception_type
)
9651 mono_loader_lock ();
9652 klass
->exception_type
= ex_type
;
9654 mono_image_property_insert (klass
->image
, klass
, MONO_CLASS_PROP_EXCEPTION_DATA
, ex_data
);
9655 mono_loader_unlock ();
9661 * mono_class_get_exception_data:
9663 * Return the exception_data property of KLASS.
9665 * LOCKING: Acquires the loader lock.
9668 mono_class_get_exception_data (MonoClass
*klass
)
9670 return mono_image_property_lookup (klass
->image
, klass
, MONO_CLASS_PROP_EXCEPTION_DATA
);
9674 * mono_classes_init:
9676 * Initialize the resources used by this module.
9679 mono_classes_init (void)
9681 mono_mutex_init (&classes_mutex
);
9683 mono_counters_register ("Inflated methods size",
9684 MONO_COUNTER_GENERICS
| MONO_COUNTER_INT
, &inflated_methods_size
);
9685 mono_counters_register ("Inflated classes",
9686 MONO_COUNTER_GENERICS
| MONO_COUNTER_INT
, &inflated_classes
);
9687 mono_counters_register ("Inflated classes size",
9688 MONO_COUNTER_GENERICS
| MONO_COUNTER_INT
, &inflated_classes_size
);
9689 mono_counters_register ("MonoClass size",
9690 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &classes_size
);
9691 mono_counters_register ("MonoClassExt size",
9692 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_ext_size
);
9696 * mono_classes_cleanup:
9698 * Free the resources used by this module.
9701 mono_classes_cleanup (void)
9703 if (global_interface_bitset
)
9704 mono_bitset_free (global_interface_bitset
);
9705 global_interface_bitset
= NULL
;
9706 mono_mutex_destroy (&classes_mutex
);
9710 * mono_class_get_exception_for_failure:
9711 * @klass: class in which the failure was detected
9713 * Return a constructed MonoException than the caller can then throw
9714 * using mono_raise_exception - or NULL if no failure is present (or
9715 * doesn't result in an exception).
9718 mono_class_get_exception_for_failure (MonoClass
*klass
)
9720 gpointer exception_data
= mono_class_get_exception_data (klass
);
9722 switch (klass
->exception_type
) {
9723 #ifndef DISABLE_SECURITY
9724 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND
: {
9725 MonoDomain
*domain
= mono_domain_get ();
9726 MonoSecurityManager
* secman
= mono_security_manager_get_methods ();
9727 MonoMethod
*method
= exception_data
;
9728 guint32 error
= (method
) ? MONO_METADATA_INHERITANCEDEMAND_METHOD
: MONO_METADATA_INHERITANCEDEMAND_CLASS
;
9729 MonoObject
*exc
= NULL
;
9733 args
[1] = mono_assembly_get_object (domain
, mono_image_get_assembly (klass
->image
));
9734 args
[2] = mono_type_get_object (domain
, &klass
->byval_arg
);
9735 args
[3] = (method
) ? mono_method_get_object (domain
, method
, NULL
) : NULL
;
9737 mono_runtime_invoke (secman
->inheritsecurityexception
, NULL
, args
, &exc
);
9738 return (MonoException
*) exc
;
9741 case MONO_EXCEPTION_TYPE_LOAD
: {
9744 char *str
= mono_type_get_full_name (klass
);
9745 char *astr
= klass
->image
->assembly
? mono_stringify_assembly_name (&klass
->image
->assembly
->aname
): NULL
;
9746 name
= mono_string_new (mono_domain_get (), str
);
9748 ex
= mono_get_exception_type_load (name
, astr
);
9752 case MONO_EXCEPTION_MISSING_METHOD
: {
9753 char *class_name
= exception_data
;
9754 char *assembly_name
= class_name
+ strlen (class_name
) + 1;
9756 return mono_get_exception_missing_method (class_name
, assembly_name
);
9758 case MONO_EXCEPTION_MISSING_FIELD
: {
9759 char *class_name
= exception_data
;
9760 char *member_name
= class_name
+ strlen (class_name
) + 1;
9762 return mono_get_exception_missing_field (class_name
, member_name
);
9764 case MONO_EXCEPTION_FILE_NOT_FOUND
: {
9765 char *msg_format
= exception_data
;
9766 char *assembly_name
= msg_format
+ strlen (msg_format
) + 1;
9767 char *msg
= g_strdup_printf (msg_format
, assembly_name
);
9770 ex
= mono_get_exception_file_not_found2 (msg
, mono_string_new (mono_domain_get (), assembly_name
));
9776 case MONO_EXCEPTION_BAD_IMAGE
: {
9777 return mono_get_exception_bad_image_format (exception_data
);
9780 MonoLoaderError
*error
;
9783 error
= mono_loader_get_last_error ();
9785 ex
= mono_loader_error_prepare_exception (error
);
9789 /* TODO - handle other class related failures */
9796 is_nesting_type (MonoClass
*outer_klass
, MonoClass
*inner_klass
)
9798 outer_klass
= mono_class_get_generic_type_definition (outer_klass
);
9799 inner_klass
= mono_class_get_generic_type_definition (inner_klass
);
9801 if (outer_klass
== inner_klass
)
9803 inner_klass
= inner_klass
->nested_in
;
9804 } while (inner_klass
);
9809 mono_class_get_generic_type_definition (MonoClass
*klass
)
9811 return klass
->generic_class
? klass
->generic_class
->container_class
: klass
;
9815 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9817 * Generic instantiations are ignored for all super types of @klass.
9819 * Visibility checks ignoring generic instantiations.
9822 mono_class_has_parent_and_ignore_generics (MonoClass
*klass
, MonoClass
*parent
)
9825 klass
= mono_class_get_generic_type_definition (klass
);
9826 parent
= mono_class_get_generic_type_definition (parent
);
9827 mono_class_setup_supertypes (klass
);
9829 for (i
= 0; i
< klass
->idepth
; ++i
) {
9830 if (parent
== mono_class_get_generic_type_definition (klass
->supertypes
[i
]))
9836 * Subtype can only access parent members with family protection if the site object
9837 * is subclass of Subtype. For example:
9838 * class A { protected int x; }
9840 * void valid_access () {
9844 * void invalid_access () {
9851 is_valid_family_access (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
*context_klass
)
9853 if (!mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
))
9856 if (context_klass
== NULL
)
9858 /*if access_klass is not member_klass context_klass must be type compat*/
9859 if (access_klass
!= member_klass
&& !mono_class_has_parent_and_ignore_generics (context_klass
, access_klass
))
9865 can_access_internals (MonoAssembly
*accessing
, MonoAssembly
* accessed
)
9868 if (accessing
== accessed
)
9870 if (!accessed
|| !accessing
)
9873 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9874 * anywhere so untrusted friends are not safe to access platform's code internals */
9875 if (mono_security_core_clr_enabled ()) {
9876 if (!mono_security_core_clr_can_access_internals (accessing
->image
, accessed
->image
))
9880 mono_assembly_load_friends (accessed
);
9881 for (tmp
= accessed
->friend_assembly_names
; tmp
; tmp
= tmp
->next
) {
9882 MonoAssemblyName
*friend = tmp
->data
;
9883 /* Be conservative with checks */
9886 if (strcmp (accessing
->aname
.name
, friend->name
))
9888 if (friend->public_key_token
[0]) {
9889 if (!accessing
->aname
.public_key_token
[0])
9891 if (!mono_public_tokens_are_equal (friend->public_key_token
, accessing
->aname
.public_key_token
))
9900 * If klass is a generic type or if it is derived from a generic type, return the
9901 * MonoClass of the generic definition
9902 * Returns NULL if not found
9905 get_generic_definition_class (MonoClass
*klass
)
9908 if (klass
->generic_class
&& klass
->generic_class
->container_class
)
9909 return klass
->generic_class
->container_class
;
9910 klass
= klass
->parent
;
9916 can_access_instantiation (MonoClass
*access_klass
, MonoGenericInst
*ginst
)
9919 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
9920 MonoType
*type
= ginst
->type_argv
[i
];
9921 switch (type
->type
) {
9922 case MONO_TYPE_SZARRAY
:
9923 if (!can_access_type (access_klass
, type
->data
.klass
))
9926 case MONO_TYPE_ARRAY
:
9927 if (!can_access_type (access_klass
, type
->data
.array
->eklass
))
9931 if (!can_access_type (access_klass
, mono_class_from_mono_type (type
->data
.type
)))
9934 case MONO_TYPE_CLASS
:
9935 case MONO_TYPE_VALUETYPE
:
9936 case MONO_TYPE_GENERICINST
:
9937 if (!can_access_type (access_klass
, mono_class_from_mono_type (type
)))
9945 can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
)
9949 if (access_klass
->image
->assembly
&& access_klass
->image
->assembly
->corlib_internal
)
9952 if (access_klass
->element_class
&& !access_klass
->enumtype
)
9953 access_klass
= access_klass
->element_class
;
9955 if (member_klass
->element_class
&& !member_klass
->enumtype
)
9956 member_klass
= member_klass
->element_class
;
9958 access_level
= member_klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
9960 if (member_klass
->byval_arg
.type
== MONO_TYPE_VAR
|| member_klass
->byval_arg
.type
== MONO_TYPE_MVAR
)
9963 if (member_klass
->generic_class
&& !can_access_instantiation (access_klass
, member_klass
->generic_class
->context
.class_inst
))
9966 if (is_nesting_type (access_klass
, member_klass
) || (access_klass
->nested_in
&& is_nesting_type (access_klass
->nested_in
, member_klass
)))
9969 if (member_klass
->nested_in
&& !can_access_type (access_klass
, member_klass
->nested_in
))
9972 /*Non nested type with nested visibility. We just fail it.*/
9973 if (access_level
>= TYPE_ATTRIBUTE_NESTED_PRIVATE
&& access_level
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
&& member_klass
->nested_in
== NULL
)
9976 switch (access_level
) {
9977 case TYPE_ATTRIBUTE_NOT_PUBLIC
:
9978 return can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
);
9980 case TYPE_ATTRIBUTE_PUBLIC
:
9983 case TYPE_ATTRIBUTE_NESTED_PUBLIC
:
9986 case TYPE_ATTRIBUTE_NESTED_PRIVATE
:
9987 return is_nesting_type (member_klass
, access_klass
);
9989 case TYPE_ATTRIBUTE_NESTED_FAMILY
:
9990 return mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
->nested_in
);
9992 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY
:
9993 return can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
);
9995 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM
:
9996 return can_access_internals (access_klass
->image
->assembly
, member_klass
->nested_in
->image
->assembly
) &&
9997 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
->nested_in
);
9999 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
:
10000 return can_access_internals (access_klass
->image
->assembly
, member_klass
->nested_in
->image
->assembly
) ||
10001 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
->nested_in
);
10006 /* FIXME: check visibility of type, too */
10008 can_access_member (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
* context_klass
, int access_level
)
10010 MonoClass
*member_generic_def
;
10011 if (access_klass
->image
->assembly
&& access_klass
->image
->assembly
->corlib_internal
)
10014 if (((access_klass
->generic_class
&& access_klass
->generic_class
->container_class
) ||
10015 access_klass
->generic_container
) &&
10016 (member_generic_def
= get_generic_definition_class (member_klass
))) {
10017 MonoClass
*access_container
;
10019 if (access_klass
->generic_container
)
10020 access_container
= access_klass
;
10022 access_container
= access_klass
->generic_class
->container_class
;
10024 if (can_access_member (access_container
, member_generic_def
, context_klass
, access_level
))
10028 /* Partition I 8.5.3.2 */
10029 /* the access level values are the same for fields and methods */
10030 switch (access_level
) {
10031 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED
:
10032 /* same compilation unit */
10033 return access_klass
->image
== member_klass
->image
;
10034 case FIELD_ATTRIBUTE_PRIVATE
:
10035 return access_klass
== member_klass
;
10036 case FIELD_ATTRIBUTE_FAM_AND_ASSEM
:
10037 if (is_valid_family_access (access_klass
, member_klass
, context_klass
) &&
10038 can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
))
10041 case FIELD_ATTRIBUTE_ASSEMBLY
:
10042 return can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
);
10043 case FIELD_ATTRIBUTE_FAMILY
:
10044 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
10047 case FIELD_ATTRIBUTE_FAM_OR_ASSEM
:
10048 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
10050 return can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
);
10051 case FIELD_ATTRIBUTE_PUBLIC
:
10058 mono_method_can_access_field (MonoMethod
*method
, MonoClassField
*field
)
10060 /* FIXME: check all overlapping fields */
10061 int can
= can_access_member (method
->klass
, field
->parent
, NULL
, mono_field_get_type (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
10063 MonoClass
*nested
= method
->klass
->nested_in
;
10065 can
= can_access_member (nested
, field
->parent
, NULL
, mono_field_get_type (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
10068 nested
= nested
->nested_in
;
10075 mono_method_can_access_method (MonoMethod
*method
, MonoMethod
*called
)
10077 int can
= can_access_member (method
->klass
, called
->klass
, NULL
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
10079 MonoClass
*nested
= method
->klass
->nested_in
;
10081 can
= can_access_member (nested
, called
->klass
, NULL
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
10084 nested
= nested
->nested_in
;
10089 * with generics calls to explicit interface implementations can be expressed
10090 * directly: the method is private, but we must allow it. This may be opening
10091 * a hole or the generics code should handle this differently.
10092 * Maybe just ensure the interface type is public.
10094 if ((called
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) && (called
->flags
& METHOD_ATTRIBUTE_FINAL
))
10100 * mono_method_can_access_method_full:
10101 * @method: The caller method
10102 * @called: The called method
10103 * @context_klass: The static type on stack of the owner @called object used
10105 * This function must be used with instance calls, as they have more strict family accessibility.
10106 * It can be used with static methods, but context_klass should be NULL.
10108 * Returns: TRUE if caller have proper visibility and acessibility to @called
10111 mono_method_can_access_method_full (MonoMethod
*method
, MonoMethod
*called
, MonoClass
*context_klass
)
10113 MonoClass
*access_class
= method
->klass
;
10114 MonoClass
*member_class
= called
->klass
;
10115 int can
= can_access_member (access_class
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
10117 MonoClass
*nested
= access_class
->nested_in
;
10119 can
= can_access_member (nested
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
10122 nested
= nested
->nested_in
;
10129 can
= can_access_type (access_class
, member_class
);
10131 MonoClass
*nested
= access_class
->nested_in
;
10133 can
= can_access_type (nested
, member_class
);
10136 nested
= nested
->nested_in
;
10143 if (called
->is_inflated
) {
10144 MonoMethodInflated
* infl
= (MonoMethodInflated
*)called
;
10145 if (infl
->context
.method_inst
&& !can_access_instantiation (access_class
, infl
->context
.method_inst
))
10154 * mono_method_can_access_field_full:
10155 * @method: The caller method
10156 * @field: The accessed field
10157 * @context_klass: The static type on stack of the owner @field object used
10159 * This function must be used with instance fields, as they have more strict family accessibility.
10160 * It can be used with static fields, but context_klass should be NULL.
10162 * Returns: TRUE if caller have proper visibility and acessibility to @field
10165 mono_method_can_access_field_full (MonoMethod
*method
, MonoClassField
*field
, MonoClass
*context_klass
)
10167 MonoClass
*access_class
= method
->klass
;
10168 MonoClass
*member_class
= field
->parent
;
10169 /* FIXME: check all overlapping fields */
10170 int can
= can_access_member (access_class
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
10172 MonoClass
*nested
= access_class
->nested_in
;
10174 can
= can_access_member (nested
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
10177 nested
= nested
->nested_in
;
10184 can
= can_access_type (access_class
, member_class
);
10186 MonoClass
*nested
= access_class
->nested_in
;
10188 can
= can_access_type (nested
, member_class
);
10191 nested
= nested
->nested_in
;
10201 * mono_class_can_access_class:
10202 * @source_class: The source class
10203 * @target_class: The accessed class
10205 * This function returns is @target_class is visible to @source_class
10207 * Returns: TRUE if source have proper visibility and acessibility to target
10210 mono_class_can_access_class (MonoClass
*source_class
, MonoClass
*target_class
)
10212 return can_access_type (source_class
, target_class
);
10216 * mono_type_is_valid_enum_basetype:
10217 * @type: The MonoType to check
10219 * Returns: TRUE if the type can be used as the basetype of an enum
10221 gboolean
mono_type_is_valid_enum_basetype (MonoType
* type
) {
10222 switch (type
->type
) {
10225 case MONO_TYPE_BOOLEAN
:
10228 case MONO_TYPE_CHAR
:
10241 * mono_class_is_valid_enum:
10242 * @klass: An enum class to be validated
10244 * This method verify the required properties an enum should have.
10246 * Returns: TRUE if the informed enum class is valid
10248 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10249 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10250 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10252 gboolean
mono_class_is_valid_enum (MonoClass
*klass
) {
10253 MonoClassField
* field
;
10254 gpointer iter
= NULL
;
10255 gboolean found_base_field
= FALSE
;
10257 g_assert (klass
->enumtype
);
10258 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10259 if (!klass
->parent
|| strcmp (klass
->parent
->name
, "Enum") || strcmp (klass
->parent
->name_space
, "System") ) {
10263 if ((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) != TYPE_ATTRIBUTE_AUTO_LAYOUT
)
10266 while ((field
= mono_class_get_fields (klass
, &iter
))) {
10267 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
10268 if (found_base_field
)
10270 found_base_field
= TRUE
;
10271 if (!mono_type_is_valid_enum_basetype (field
->type
))
10276 if (!found_base_field
)
10279 if (klass
->method
.count
> 0)
10286 mono_generic_class_is_generic_type_definition (MonoGenericClass
*gklass
)
10288 return gklass
->context
.class_inst
== gklass
->container_class
->generic_container
->context
.class_inst
;
10292 * mono_class_setup_interface_id:
10294 * Initializes MonoClass::interface_id if required.
10296 * LOCKING: Acquires the loader lock.
10299 mono_class_setup_interface_id (MonoClass
*class)
10301 mono_loader_lock ();
10302 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id
)
10303 class->interface_id
= mono_get_unique_iid (class);
10304 mono_loader_unlock ();
10308 * mono_class_alloc_ext:
10310 * Allocate klass->ext if not already done.
10313 mono_class_alloc_ext (MonoClass
*klass
)
10320 ext
= mono_class_alloc0 (klass
, sizeof (MonoClassExt
));
10321 mono_image_lock (klass
->image
);
10322 mono_memory_barrier ();
10325 class_ext_size
+= sizeof (MonoClassExt
);
10326 mono_image_unlock (klass
->image
);
10330 * mono_class_setup_interfaces:
10332 * Initialize class->interfaces/interfaces_count.
10333 * LOCKING: Acquires the loader lock.
10334 * This function can fail the type.
10337 mono_class_setup_interfaces (MonoClass
*klass
, MonoError
*error
)
10339 int i
, interface_count
;
10340 MonoClass
**interfaces
;
10342 mono_error_init (error
);
10344 if (klass
->interfaces_inited
)
10347 if (klass
->rank
== 1 && klass
->byval_arg
.type
!= MONO_TYPE_ARRAY
) {
10348 MonoType
*args
[1];
10350 /* generic IList, ICollection, IEnumerable */
10351 interface_count
= mono_defaults
.generic_ireadonlylist_class
? 2 : 1;
10352 interfaces
= mono_image_alloc0 (klass
->image
, sizeof (MonoClass
*) * interface_count
);
10354 args
[0] = &klass
->element_class
->byval_arg
;
10355 interfaces
[0] = mono_class_bind_generic_parameters (
10356 mono_defaults
.generic_ilist_class
, 1, args
, FALSE
);
10357 if (interface_count
> 1)
10358 interfaces
[1] = mono_class_bind_generic_parameters (
10359 mono_defaults
.generic_ireadonlylist_class
, 1, args
, FALSE
);
10360 } else if (klass
->generic_class
) {
10361 MonoClass
*gklass
= klass
->generic_class
->container_class
;
10363 mono_class_setup_interfaces (gklass
, error
);
10364 if (!mono_error_ok (error
)) {
10365 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not setup the interfaces"));
10369 interface_count
= gklass
->interface_count
;
10370 interfaces
= mono_class_new0 (klass
, MonoClass
*, interface_count
);
10371 for (i
= 0; i
< interface_count
; i
++) {
10372 interfaces
[i
] = mono_class_inflate_generic_class_checked (gklass
->interfaces
[i
], mono_generic_class_get_context (klass
->generic_class
), error
);
10373 if (!mono_error_ok (error
)) {
10374 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not setup the interfaces"));
10379 interface_count
= 0;
10383 mono_image_lock (klass
->image
);
10385 if (!klass
->interfaces_inited
) {
10386 klass
->interface_count
= interface_count
;
10387 klass
->interfaces
= interfaces
;
10389 mono_memory_barrier ();
10391 klass
->interfaces_inited
= TRUE
;
10394 mono_image_unlock (klass
->image
);
10398 mono_field_resolve_type (MonoClassField
*field
, MonoError
*error
)
10400 MonoClass
*class = field
->parent
;
10401 MonoImage
*image
= class->image
;
10402 MonoClass
*gtd
= class->generic_class
? mono_class_get_generic_type_definition (class) : NULL
;
10403 int field_idx
= field
- class->fields
;
10405 mono_error_init (error
);
10408 MonoClassField
*gfield
= >d
->fields
[field_idx
];
10409 MonoType
*gtype
= mono_field_get_type_checked (gfield
, error
);
10410 if (!mono_error_ok (error
)) {
10411 char *err_msg
= g_strdup_printf ("Could not load field %d type due to: %s", field_idx
, mono_error_get_message (error
));
10412 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
10416 field
->type
= mono_class_inflate_generic_type_no_copy (image
, gtype
, mono_class_get_context (class), error
);
10417 if (!mono_error_ok (error
)) {
10418 char *err_msg
= g_strdup_printf ("Could not load field %d type due to: %s", field_idx
, mono_error_get_message (error
));
10419 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
10424 guint32 cols
[MONO_FIELD_SIZE
];
10425 MonoGenericContainer
*container
= NULL
;
10426 int idx
= class->field
.first
+ field_idx
;
10428 /*FIXME, in theory we do not lazy load SRE fields*/
10429 g_assert (!image_is_dynamic (image
));
10431 if (class->generic_container
) {
10432 container
= class->generic_container
;
10434 container
= gtd
->generic_container
;
10435 g_assert (container
);
10438 /* class->field.first and idx points into the fieldptr table */
10439 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
10441 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], NULL
)) {
10442 mono_error_set_type_load_class (error
, class, "Could not verify field %s signature", field
->name
);
10443 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
10447 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
10449 mono_metadata_decode_value (sig
, &sig
);
10450 /* FIELD signature == 0x06 */
10451 g_assert (*sig
== 0x06);
10452 field
->type
= mono_metadata_parse_type_full (image
, container
, MONO_PARSE_FIELD
, cols
[MONO_FIELD_FLAGS
], sig
+ 1, &sig
);
10454 mono_class_set_failure_from_loader_error (class, error
, g_strdup_printf ("Could not load field %s type", field
->name
));
10459 mono_field_resolve_flags (MonoClassField
*field
)
10461 MonoClass
*class = field
->parent
;
10462 MonoImage
*image
= class->image
;
10463 MonoClass
*gtd
= class->generic_class
? mono_class_get_generic_type_definition (class) : NULL
;
10464 int field_idx
= field
- class->fields
;
10468 MonoClassField
*gfield
= >d
->fields
[field_idx
];
10469 return mono_field_get_flags (gfield
);
10471 int idx
= class->field
.first
+ field_idx
;
10473 /*FIXME, in theory we do not lazy load SRE fields*/
10474 g_assert (!image_is_dynamic (image
));
10476 return mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_FLAGS
);
10481 * mono_class_setup_basic_field_info:
10482 * @class: The class to initialize
10484 * Initializes the class->fields array of fields.
10485 * Aquires the loader lock.
10488 mono_class_setup_basic_field_info_locking (MonoClass
*class)
10490 mono_loader_lock ();
10491 mono_class_setup_basic_field_info (class);
10492 mono_loader_unlock ();
10496 * mono_class_get_fields_lazy:
10497 * @klass: the MonoClass to act on
10499 * This routine is an iterator routine for retrieving the fields in a class.
10500 * Only minimal information about fields are loaded. Accessors must be used
10501 * for all MonoClassField returned.
10503 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10504 * iterate over all of the elements. When no more values are
10505 * available, the return value is NULL.
10507 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10510 mono_class_get_fields_lazy (MonoClass
* klass
, gpointer
*iter
)
10512 MonoClassField
* field
;
10516 mono_class_setup_basic_field_info_locking (klass
);
10517 if (!klass
->fields
)
10519 /* start from the first */
10520 if (klass
->field
.count
) {
10521 return *iter
= &klass
->fields
[0];
10529 if (field
< &klass
->fields
[klass
->field
.count
]) {
10530 return *iter
= field
;
10536 mono_class_full_name (MonoClass
*klass
)
10538 return mono_type_full_name (&klass
->byval_arg
);