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 /* Function supplied by the runtime to find classes by name using information from the AOT file */
56 static MonoGetClassFromName get_class_from_name
= NULL
;
58 static MonoClass
* mono_class_create_from_typedef (MonoImage
*image
, guint32 type_token
, MonoError
*error
);
59 static gboolean
mono_class_get_cached_class_info (MonoClass
*klass
, MonoCachedClassInfo
*res
);
60 static gboolean
can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
);
61 static MonoMethod
* find_method_in_metadata (MonoClass
*klass
, const char *name
, int param_count
, int flags
);
62 static int generic_array_methods (MonoClass
*class);
63 static void setup_generic_array_ifaces (MonoClass
*class, MonoClass
*iface
, MonoMethod
**methods
, int pos
);
65 static MonoMethod
* mono_class_get_virtual_methods (MonoClass
* klass
, gpointer
*iter
);
66 static char* mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
);
67 static void mono_field_resolve_type (MonoClassField
*field
, MonoError
*error
);
68 static guint32
mono_field_resolve_flags (MonoClassField
*field
);
69 static void mono_class_setup_vtable_full (MonoClass
*class, GList
*in_setup
);
70 static void mono_generic_class_setup_parent (MonoClass
*klass
, MonoClass
*gklass
);
73 void (*mono_debugger_class_init_func
) (MonoClass
*klass
) = NULL
;
77 We use gclass recording to allow recursive system f types to be referenced by a parent.
79 Given the following type hierarchy:
81 class TextBox : TextBoxBase<TextBox> {}
82 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
83 class TextInput<T> : Input<T> where T: TextInput<T> {}
86 The runtime tries to load TextBoxBase<>.
87 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
88 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
89 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
91 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
92 at this point, iow, both are registered in the type map and both and a NULL parent. This means
93 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
95 To fix that what we do is to record all generic instantes created while resolving the parent of
96 any generic type definition and, after resolved, correct the parent field if needed.
99 static int record_gclass_instantiation
;
100 static GSList
*gclass_recorded_list
;
101 typedef gboolean (*gclass_record_func
) (MonoClass
*, void*);
104 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
107 enable_gclass_recording (void)
109 ++record_gclass_instantiation
;
113 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
116 disable_gclass_recording (gclass_record_func func
, void *user_data
)
118 GSList
**head
= &gclass_recorded_list
;
120 g_assert (record_gclass_instantiation
> 0);
121 --record_gclass_instantiation
;
124 GSList
*node
= *head
;
125 if (func ((MonoClass
*)node
->data
, user_data
)) {
127 g_slist_free_1 (node
);
133 /* We automatically discard all recorded gclasses when disabled. */
134 if (!record_gclass_instantiation
&& gclass_recorded_list
) {
135 g_slist_free (gclass_recorded_list
);
136 gclass_recorded_list
= NULL
;
141 * mono_class_from_typeref:
142 * @image: a MonoImage
143 * @type_token: a TypeRef token
145 * Creates the MonoClass* structure representing the type defined by
146 * the typeref token valid inside @image.
147 * Returns: the MonoClass* representing the typeref token, NULL ifcould
151 mono_class_from_typeref (MonoImage
*image
, guint32 type_token
)
154 guint32 cols
[MONO_TYPEREF_SIZE
];
155 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
157 const char *name
, *nspace
;
161 if (!mono_verifier_verify_typeref_row (image
, (type_token
& 0xffffff) - 1, &error
)) {
162 mono_trace_warning (MONO_TRACE_TYPE
, "Failed to resolve typeref from %s due to '%s'", image
->name
, mono_error_get_message (&error
));
166 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
168 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
169 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
171 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLTION_SCOPE_BITS
;
172 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLTION_SCOPE_MASK
) {
173 case MONO_RESOLTION_SCOPE_MODULE
:
175 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
176 This is not the observed behavior of existing implementations.
177 The defacto behavior is that it's just a typedef in disguise.
179 /* a typedef in disguise */
180 return mono_class_from_name (image
, nspace
, name
);
181 case MONO_RESOLTION_SCOPE_MODULEREF
:
182 module
= mono_image_load_module (image
, idx
);
184 return mono_class_from_name (module
, nspace
, name
);
186 char *msg
= g_strdup_printf ("%s%s%s", nspace
, nspace
[0] ? "." : "", name
);
189 human_name
= mono_stringify_assembly_name (&image
->assembly
->aname
);
190 mono_loader_set_error_type_load (msg
, human_name
);
196 case MONO_RESOLTION_SCOPE_TYPEREF
: {
197 MonoClass
*enclosing
;
200 if (idx
== mono_metadata_token_index (type_token
)) {
201 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image
->name
, type_token
));
205 enclosing
= mono_class_from_typeref (image
, MONO_TOKEN_TYPE_REF
| idx
);
209 if (enclosing
->nested_classes_inited
&& enclosing
->ext
) {
210 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
211 for (tmp
= enclosing
->ext
->nested_classes
; tmp
; tmp
= tmp
->next
) {
213 if (strcmp (res
->name
, name
) == 0)
217 /* Don't call mono_class_init as we might've been called by it recursively */
218 int i
= mono_metadata_nesting_typedef (enclosing
->image
, enclosing
->type_token
, 1);
220 guint32 class_nested
= mono_metadata_decode_row_col (&enclosing
->image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, MONO_NESTED_CLASS_NESTED
);
221 guint32 string_offset
= mono_metadata_decode_row_col (&enclosing
->image
->tables
[MONO_TABLE_TYPEDEF
], class_nested
- 1, MONO_TYPEDEF_NAME
);
222 const char *nname
= mono_metadata_string_heap (enclosing
->image
, string_offset
);
224 if (strcmp (nname
, name
) == 0) {
225 MonoClass
*res
= mono_class_create_from_typedef (enclosing
->image
, MONO_TOKEN_TYPE_DEF
| class_nested
, &error
);
226 if (!mono_error_ok (&error
)) {
227 mono_loader_set_error_from_mono_error (&error
);
228 mono_error_cleanup (&error
); /*FIXME don't swallow error message.*/
234 i
= mono_metadata_nesting_typedef (enclosing
->image
, enclosing
->type_token
, i
+ 1);
237 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx
, nspace
, name
, image
->name
);
240 case MONO_RESOLTION_SCOPE_ASSEMBLYREF
:
244 if (idx
> image
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
) {
245 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image
->name
, idx
));
249 if (!image
->references
|| !image
->references
[idx
- 1])
250 mono_assembly_load_reference (image
, idx
- 1);
251 g_assert (image
->references
[idx
- 1]);
253 /* If the assembly did not load, register this as a type load exception */
254 if (image
->references
[idx
- 1] == REFERENCE_MISSING
){
255 MonoAssemblyName aname
;
258 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
259 human_name
= mono_stringify_assembly_name (&aname
);
260 mono_loader_set_error_assembly_load (human_name
, image
->assembly
? image
->assembly
->ref_only
: FALSE
);
266 return mono_class_from_name (image
->references
[idx
- 1]->image
, nspace
, name
);
271 mono_image_memdup (MonoImage
*image
, void *data
, guint size
)
273 void *res
= mono_image_alloc (image
, size
);
274 memcpy (res
, data
, size
);
278 /* Copy everything mono_metadata_free_array free. */
280 mono_dup_array_type (MonoImage
*image
, MonoArrayType
*a
)
283 a
= mono_image_memdup (image
, a
, sizeof (MonoArrayType
));
285 a
->sizes
= mono_image_memdup (image
, a
->sizes
, a
->numsizes
* sizeof (int));
287 a
->lobounds
= mono_image_memdup (image
, a
->lobounds
, a
->numlobounds
* sizeof (int));
289 a
= g_memdup (a
, sizeof (MonoArrayType
));
291 a
->sizes
= g_memdup (a
->sizes
, a
->numsizes
* sizeof (int));
293 a
->lobounds
= g_memdup (a
->lobounds
, a
->numlobounds
* sizeof (int));
298 /* Copy everything mono_metadata_free_method_signature free. */
300 mono_metadata_signature_deep_dup (MonoImage
*image
, MonoMethodSignature
*sig
)
304 sig
= mono_metadata_signature_dup_full (image
, sig
);
306 sig
->ret
= mono_metadata_type_dup (image
, sig
->ret
);
307 for (i
= 0; i
< sig
->param_count
; ++i
)
308 sig
->params
[i
] = mono_metadata_type_dup (image
, sig
->params
[i
]);
314 _mono_type_get_assembly_name (MonoClass
*klass
, GString
*str
)
316 MonoAssembly
*ta
= klass
->image
->assembly
;
319 name
= mono_stringify_assembly_name (&ta
->aname
);
320 g_string_append_printf (str
, ", %s", name
);
325 mono_type_name_check_byref (MonoType
*type
, GString
*str
)
328 g_string_append_c (str
, '&');
332 mono_type_get_name_recurse (MonoType
*type
, GString
*str
, gboolean is_recursed
,
333 MonoTypeNameFormat format
)
337 switch (type
->type
) {
338 case MONO_TYPE_ARRAY
: {
339 int i
, rank
= type
->data
.array
->rank
;
340 MonoTypeNameFormat nested_format
;
342 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
343 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
345 mono_type_get_name_recurse (
346 &type
->data
.array
->eklass
->byval_arg
, str
, FALSE
, nested_format
);
347 g_string_append_c (str
, '[');
349 g_string_append_c (str
, '*');
350 for (i
= 1; i
< rank
; i
++)
351 g_string_append_c (str
, ',');
352 g_string_append_c (str
, ']');
354 mono_type_name_check_byref (type
, str
);
356 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
357 _mono_type_get_assembly_name (type
->data
.array
->eklass
, str
);
360 case MONO_TYPE_SZARRAY
: {
361 MonoTypeNameFormat nested_format
;
363 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
364 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
366 mono_type_get_name_recurse (
367 &type
->data
.klass
->byval_arg
, str
, FALSE
, nested_format
);
368 g_string_append (str
, "[]");
370 mono_type_name_check_byref (type
, str
);
372 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
373 _mono_type_get_assembly_name (type
->data
.klass
, str
);
376 case MONO_TYPE_PTR
: {
377 MonoTypeNameFormat nested_format
;
379 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
380 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
382 mono_type_get_name_recurse (
383 type
->data
.type
, str
, FALSE
, nested_format
);
384 g_string_append_c (str
, '*');
386 mono_type_name_check_byref (type
, str
);
388 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
389 _mono_type_get_assembly_name (mono_class_from_mono_type (type
->data
.type
), str
);
394 if (!mono_generic_param_info (type
->data
.generic_param
))
395 g_string_append_printf (str
, "%s%d", type
->type
== MONO_TYPE_VAR
? "!" : "!!", type
->data
.generic_param
->num
);
397 g_string_append (str
, mono_generic_param_info (type
->data
.generic_param
)->name
);
399 mono_type_name_check_byref (type
, str
);
403 klass
= mono_class_from_mono_type (type
);
404 if (klass
->nested_in
) {
405 mono_type_get_name_recurse (
406 &klass
->nested_in
->byval_arg
, str
, TRUE
, format
);
407 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
408 g_string_append_c (str
, '.');
410 g_string_append_c (str
, '+');
411 } else if (*klass
->name_space
) {
412 g_string_append (str
, klass
->name_space
);
413 g_string_append_c (str
, '.');
415 if (format
== MONO_TYPE_NAME_FORMAT_IL
) {
416 char *s
= strchr (klass
->name
, '`');
417 int len
= s
? s
- klass
->name
: strlen (klass
->name
);
419 g_string_append_len (str
, klass
->name
, len
);
421 g_string_append (str
, klass
->name
);
424 if (klass
->generic_class
) {
425 MonoGenericClass
*gclass
= klass
->generic_class
;
426 MonoGenericInst
*inst
= gclass
->context
.class_inst
;
427 MonoTypeNameFormat nested_format
;
430 nested_format
= format
== MONO_TYPE_NAME_FORMAT_FULL_NAME
?
431 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
: format
;
433 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
434 g_string_append_c (str
, '<');
436 g_string_append_c (str
, '[');
437 for (i
= 0; i
< inst
->type_argc
; i
++) {
438 MonoType
*t
= inst
->type_argv
[i
];
441 g_string_append_c (str
, ',');
442 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
443 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
444 g_string_append_c (str
, '[');
445 mono_type_get_name_recurse (inst
->type_argv
[i
], str
, FALSE
, nested_format
);
446 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
447 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
448 g_string_append_c (str
, ']');
450 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
451 g_string_append_c (str
, '>');
453 g_string_append_c (str
, ']');
454 } else if (klass
->generic_container
&&
455 (format
!= MONO_TYPE_NAME_FORMAT_FULL_NAME
) &&
456 (format
!= MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)) {
459 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
460 g_string_append_c (str
, '<');
462 g_string_append_c (str
, '[');
463 for (i
= 0; i
< klass
->generic_container
->type_argc
; i
++) {
465 g_string_append_c (str
, ',');
466 g_string_append (str
, mono_generic_container_get_param_info (klass
->generic_container
, i
)->name
);
468 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
469 g_string_append_c (str
, '>');
471 g_string_append_c (str
, ']');
474 mono_type_name_check_byref (type
, str
);
476 if ((format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
477 (type
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
478 _mono_type_get_assembly_name (klass
, str
);
484 * mono_type_get_name_full:
486 * @format: the format for the return string.
489 * Returns: the string representation in a number of formats:
491 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
492 * returned in the formatrequired by System.Reflection, this is the
493 * inverse of mono_reflection_parse_type ().
495 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
496 * be used by the IL assembler.
498 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
500 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
503 mono_type_get_name_full (MonoType
*type
, MonoTypeNameFormat format
)
507 result
= g_string_new ("");
509 mono_type_get_name_recurse (type
, result
, FALSE
, format
);
511 return g_string_free (result
, FALSE
);
515 * mono_type_get_full_name:
518 * Returns: the string representation for type as required by System.Reflection.
519 * The inverse of mono_reflection_parse_type ().
522 mono_type_get_full_name (MonoClass
*class)
524 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION
);
528 * mono_type_get_name:
531 * Returns: the string representation for type as it would be represented in IL code.
534 mono_type_get_name (MonoType
*type
)
536 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_IL
);
540 * mono_type_get_underlying_type:
543 * Returns: the MonoType for the underlying integer type if @type
544 * is an enum and byref is false, otherwise the type itself.
547 mono_type_get_underlying_type (MonoType
*type
)
549 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
&& !type
->byref
)
550 return mono_class_enum_basetype (type
->data
.klass
);
551 if (type
->type
== MONO_TYPE_GENERICINST
&& type
->data
.generic_class
->container_class
->enumtype
&& !type
->byref
)
552 return mono_class_enum_basetype (type
->data
.generic_class
->container_class
);
557 * mono_class_is_open_constructed_type:
560 * Returns TRUE if type represents a generics open constructed type.
561 * IOW, not all type parameters required for the instantiation have
562 * been provided or it's a generic type definition.
564 * An open constructed type means it's a non realizable type. Not to
565 * be mixed up with an abstract type - we can't cast or dispatch to
566 * an open type, for example.
569 mono_class_is_open_constructed_type (MonoType
*t
)
575 case MONO_TYPE_SZARRAY
:
576 return mono_class_is_open_constructed_type (&t
->data
.klass
->byval_arg
);
577 case MONO_TYPE_ARRAY
:
578 return mono_class_is_open_constructed_type (&t
->data
.array
->eklass
->byval_arg
);
580 return mono_class_is_open_constructed_type (t
->data
.type
);
581 case MONO_TYPE_GENERICINST
:
582 return t
->data
.generic_class
->context
.class_inst
->is_open
;
583 case MONO_TYPE_CLASS
:
584 case MONO_TYPE_VALUETYPE
:
585 return t
->data
.klass
->generic_container
!= NULL
;
592 This is a simple function to catch the most common bad instances of generic types.
593 Specially those that might lead to further failures in the runtime.
596 is_valid_generic_argument (MonoType
*type
)
598 switch (type
->type
) {
600 //case MONO_TYPE_TYPEDBYREF:
607 inflate_generic_type (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
609 mono_error_init (error
);
611 switch (type
->type
) {
612 case MONO_TYPE_MVAR
: {
614 int num
= mono_type_get_generic_param_num (type
);
615 MonoGenericInst
*inst
= context
->method_inst
;
616 if (!inst
|| !inst
->type_argv
)
618 if (num
>= inst
->type_argc
) {
619 MonoGenericParamInfo
*info
= mono_generic_param_info (type
->data
.generic_param
);
620 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
621 num
, info
? info
->name
: "", inst
->type_argc
);
625 if (!is_valid_generic_argument (inst
->type_argv
[num
])) {
626 MonoGenericParamInfo
*info
= mono_generic_param_info (type
->data
.generic_param
);
627 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded with type 0x%x",
628 num
, info
? info
->name
: "", inst
->type_argv
[num
]->type
);
632 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
633 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
634 * ->byref and ->attrs from @type are propagated to the returned type.
636 nt
= mono_metadata_type_dup (image
, inst
->type_argv
[num
]);
637 nt
->byref
= type
->byref
;
638 nt
->attrs
= type
->attrs
;
641 case MONO_TYPE_VAR
: {
643 int num
= mono_type_get_generic_param_num (type
);
644 MonoGenericInst
*inst
= context
->class_inst
;
647 if (num
>= inst
->type_argc
) {
648 MonoGenericParamInfo
*info
= mono_generic_param_info (type
->data
.generic_param
);
649 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
650 num
, info
? info
->name
: "", inst
->type_argc
);
653 if (!is_valid_generic_argument (inst
->type_argv
[num
])) {
654 MonoGenericParamInfo
*info
= mono_generic_param_info (type
->data
.generic_param
);
655 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded with type 0x%x",
656 num
, info
? info
->name
: "", inst
->type_argv
[num
]->type
);
659 nt
= mono_metadata_type_dup (image
, inst
->type_argv
[num
]);
660 nt
->byref
= type
->byref
;
661 nt
->attrs
= type
->attrs
;
664 case MONO_TYPE_SZARRAY
: {
665 MonoClass
*eclass
= type
->data
.klass
;
666 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, &eclass
->byval_arg
, context
, error
);
667 if (!inflated
|| !mono_error_ok (error
))
669 nt
= mono_metadata_type_dup (image
, type
);
670 nt
->data
.klass
= mono_class_from_mono_type (inflated
);
671 mono_metadata_free_type (inflated
);
674 case MONO_TYPE_ARRAY
: {
675 MonoClass
*eclass
= type
->data
.array
->eklass
;
676 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, &eclass
->byval_arg
, context
, error
);
677 if (!inflated
|| !mono_error_ok (error
))
679 nt
= mono_metadata_type_dup (image
, type
);
680 nt
->data
.array
->eklass
= mono_class_from_mono_type (inflated
);
681 mono_metadata_free_type (inflated
);
684 case MONO_TYPE_GENERICINST
: {
685 MonoGenericClass
*gclass
= type
->data
.generic_class
;
686 MonoGenericInst
*inst
;
688 if (!gclass
->context
.class_inst
->is_open
)
691 inst
= mono_metadata_inflate_generic_inst (gclass
->context
.class_inst
, context
, error
);
692 if (!mono_error_ok (error
))
694 if (inst
!= gclass
->context
.class_inst
)
695 gclass
= mono_metadata_lookup_generic_class (gclass
->container_class
, inst
, gclass
->is_dynamic
);
697 if (gclass
== type
->data
.generic_class
)
700 nt
= mono_metadata_type_dup (image
, type
);
701 nt
->data
.generic_class
= gclass
;
704 case MONO_TYPE_CLASS
:
705 case MONO_TYPE_VALUETYPE
: {
706 MonoClass
*klass
= type
->data
.klass
;
707 MonoGenericContainer
*container
= klass
->generic_container
;
708 MonoGenericInst
*inst
;
709 MonoGenericClass
*gclass
= NULL
;
715 /* We can't use context->class_inst directly, since it can have more elements */
716 inst
= mono_metadata_inflate_generic_inst (container
->context
.class_inst
, context
, error
);
717 if (!mono_error_ok (error
))
719 if (inst
== container
->context
.class_inst
)
722 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, klass
->image
->dynamic
);
724 nt
= mono_metadata_type_dup (image
, type
);
725 nt
->type
= MONO_TYPE_GENERICINST
;
726 nt
->data
.generic_class
= gclass
;
736 mono_generic_class_get_context (MonoGenericClass
*gclass
)
738 return &gclass
->context
;
742 mono_class_get_context (MonoClass
*class)
744 return class->generic_class
? mono_generic_class_get_context (class->generic_class
) : NULL
;
748 * mono_class_get_generic_container:
750 * Return the generic container of KLASS which should be a generic type definition.
752 MonoGenericContainer
*
753 mono_class_get_generic_container (MonoClass
*klass
)
755 g_assert (klass
->is_generic
);
757 return klass
->generic_container
;
761 * mono_class_get_generic_class:
763 * Return the MonoGenericClass of KLASS, which should be a generic instance.
766 mono_class_get_generic_class (MonoClass
*klass
)
768 g_assert (klass
->is_inflated
);
770 return klass
->generic_class
;
774 * mono_class_inflate_generic_type_with_mempool:
775 * @mempool: a mempool
777 * @context: a generics context
778 * @error: error context
780 * The same as mono_class_inflate_generic_type, but allocates the MonoType
781 * from mempool if it is non-NULL. If it is NULL, the MonoType is
782 * allocated on the heap and is owned by the caller.
783 * The returned type can potentially be the same as TYPE, so it should not be
784 * modified by the caller, and it should be freed using mono_metadata_free_type ().
787 mono_class_inflate_generic_type_with_mempool (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
789 MonoType
*inflated
= NULL
;
790 mono_error_init (error
);
793 inflated
= inflate_generic_type (image
, type
, context
, error
);
794 if (!mono_error_ok (error
))
798 MonoType
*shared
= mono_metadata_get_shared_type (type
);
803 return mono_metadata_type_dup (image
, type
);
807 mono_stats
.inflated_type_count
++;
812 * mono_class_inflate_generic_type:
814 * @context: a generics context
816 * If @type is a generic type and @context is not NULL, instantiate it using the
817 * generics context @context.
819 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
820 * on the heap and is owned by the caller. Returns NULL on error.
822 * @deprecated Please use mono_class_inflate_generic_type_checked instead
825 mono_class_inflate_generic_type (MonoType
*type
, MonoGenericContext
*context
)
829 result
= mono_class_inflate_generic_type_checked (type
, context
, &error
);
831 if (!mono_error_ok (&error
)) {
832 mono_error_cleanup (&error
);
839 * mono_class_inflate_generic_type:
841 * @context: a generics context
842 * @error: error context to use
844 * If @type is a generic type and @context is not NULL, instantiate it using the
845 * generics context @context.
847 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
848 * on the heap and is owned by the caller.
851 mono_class_inflate_generic_type_checked (MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
853 return mono_class_inflate_generic_type_with_mempool (NULL
, type
, context
, error
);
857 * mono_class_inflate_generic_type_no_copy:
859 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
863 mono_class_inflate_generic_type_no_copy (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
865 MonoType
*inflated
= NULL
;
867 mono_error_init (error
);
869 inflated
= inflate_generic_type (image
, type
, context
, error
);
870 if (!mono_error_ok (error
))
877 mono_stats
.inflated_type_count
++;
882 mono_class_inflate_generic_class_checked (MonoClass
*gklass
, MonoGenericContext
*context
, MonoError
*error
)
887 inflated
= mono_class_inflate_generic_type_checked (&gklass
->byval_arg
, context
, error
);
888 if (!mono_error_ok (error
))
891 res
= mono_class_from_mono_type (inflated
);
892 mono_metadata_free_type (inflated
);
897 * mono_class_inflate_generic_class:
899 * Inflate the class GKLASS with CONTEXT.
902 mono_class_inflate_generic_class (MonoClass
*gklass
, MonoGenericContext
*context
)
907 res
= mono_class_inflate_generic_class_checked (gklass
, context
, &error
);
908 g_assert (mono_error_ok (&error
)); /*FIXME proper error handling*/
915 static MonoGenericContext
916 inflate_generic_context (MonoGenericContext
*context
, MonoGenericContext
*inflate_with
, MonoError
*error
)
918 MonoGenericInst
*class_inst
= NULL
;
919 MonoGenericInst
*method_inst
= NULL
;
920 MonoGenericContext res
= { NULL
, NULL
};
922 mono_error_init (error
);
924 if (context
->class_inst
) {
925 class_inst
= mono_metadata_inflate_generic_inst (context
->class_inst
, inflate_with
, error
);
926 if (!mono_error_ok (error
))
930 if (context
->method_inst
) {
931 method_inst
= mono_metadata_inflate_generic_inst (context
->method_inst
, inflate_with
, error
);
932 if (!mono_error_ok (error
))
936 res
.class_inst
= class_inst
;
937 res
.method_inst
= method_inst
;
943 * mono_class_inflate_generic_method:
944 * @method: a generic method
945 * @context: a generics context
947 * Instantiate the generic method @method using the generics context @context.
949 * Returns: the new instantiated method
952 mono_class_inflate_generic_method (MonoMethod
*method
, MonoGenericContext
*context
)
954 return mono_class_inflate_generic_method_full (method
, NULL
, context
);
958 * mono_class_inflate_generic_method_full:
960 * Instantiate method @method with the generic context @context.
961 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
962 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
965 mono_class_inflate_generic_method_full (MonoMethod
*method
, MonoClass
*klass_hint
, MonoGenericContext
*context
)
968 MonoMethod
*res
= mono_class_inflate_generic_method_full_checked (method
, klass_hint
, context
, &error
);
969 if (!mono_error_ok (&error
))
970 /*FIXME do proper error handling - on this case, kill this function. */
971 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error
));
977 * mono_class_inflate_generic_method_full_checked:
978 * Same as mono_class_inflate_generic_method_full but return failure using @error.
981 mono_class_inflate_generic_method_full_checked (MonoMethod
*method
, MonoClass
*klass_hint
, MonoGenericContext
*context
, MonoError
*error
)
984 MonoMethodInflated
*iresult
, *cached
;
985 MonoMethodSignature
*sig
;
986 MonoGenericContext tmp_context
;
987 gboolean is_mb_open
= FALSE
;
989 mono_error_init (error
);
991 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
992 while (method
->is_inflated
) {
993 MonoGenericContext
*method_context
= mono_method_get_context (method
);
994 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
996 tmp_context
= inflate_generic_context (method_context
, context
, error
);
997 if (!mono_error_ok (error
))
999 context
= &tmp_context
;
1001 if (mono_metadata_generic_context_equal (method_context
, context
))
1004 method
= imethod
->declaring
;
1008 * A method only needs to be inflated if the context has argument for which it is
1011 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1012 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1015 if (!((method
->is_generic
&& context
->method_inst
) ||
1016 (method
->klass
->generic_container
&& context
->class_inst
)))
1020 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1021 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1022 * This is opposite to the way non-SRE MethodInfos behave.
1024 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1026 * void Example<T> () {
1030 * In Example, the method token must be encoded as: "void Example<!!0>()"
1032 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1033 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1035 * On the other hand, inflating a non-SRE generic method with its own arguments should
1036 * return itself. For example:
1038 * MethodInfo m = ... //m is a generic method definition
1039 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1042 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1043 * what happens with regular methods.
1045 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1046 * everything should behave like a regular type or method.
1049 is_mb_open
= method
->is_generic
&&
1050 method
->klass
->image
->dynamic
&& !method
->klass
->wastypebuilder
&& /* that is a MethodBuilder from an unfinished TypeBuilder */
1051 context
->method_inst
== mono_method_get_generic_container (method
)->context
.method_inst
; /* and it's been instantiated with its own arguments. */
1053 iresult
= g_new0 (MonoMethodInflated
, 1);
1054 iresult
->context
= *context
;
1055 iresult
->declaring
= method
;
1056 iresult
->method
.method
.is_mb_open
= is_mb_open
;
1058 if (!context
->method_inst
&& method
->is_generic
)
1059 iresult
->context
.method_inst
= mono_method_get_generic_container (method
)->context
.method_inst
;
1061 if (!context
->class_inst
) {
1062 g_assert (!iresult
->declaring
->klass
->generic_class
);
1063 if (iresult
->declaring
->klass
->generic_container
)
1064 iresult
->context
.class_inst
= iresult
->declaring
->klass
->generic_container
->context
.class_inst
;
1065 else if (iresult
->declaring
->klass
->generic_class
)
1066 iresult
->context
.class_inst
= iresult
->declaring
->klass
->generic_class
->context
.class_inst
;
1069 mono_loader_lock ();
1070 cached
= mono_method_inflated_lookup (iresult
, FALSE
);
1072 mono_loader_unlock ();
1074 return (MonoMethod
*)cached
;
1077 mono_stats
.inflated_method_count
++;
1079 inflated_methods_size
+= sizeof (MonoMethodInflated
);
1081 sig
= mono_method_signature (method
);
1083 char *name
= mono_type_get_full_name (method
->klass
);
1084 mono_error_set_bad_image (error
, method
->klass
->image
, "Could not resolve signature of method %s:%s", name
, method
->name
);
1090 memcpy (&iresult
->method
.pinvoke
, method
, sizeof (MonoMethodPInvoke
));
1092 memcpy (&iresult
->method
.method
, method
, sizeof (MonoMethod
));
1095 result
= (MonoMethod
*) iresult
;
1096 result
->is_inflated
= TRUE
;
1097 result
->is_generic
= FALSE
;
1098 result
->sre_method
= FALSE
;
1099 result
->signature
= NULL
;
1100 result
->is_mb_open
= is_mb_open
;
1102 if (!context
->method_inst
) {
1103 /* Set the generic_container of the result to the generic_container of method */
1104 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
1106 if (generic_container
) {
1107 result
->is_generic
= 1;
1108 mono_method_set_generic_container (result
, generic_container
);
1112 if (!klass_hint
|| !klass_hint
->generic_class
||
1113 klass_hint
->generic_class
->container_class
!= method
->klass
||
1114 klass_hint
->generic_class
->context
.class_inst
!= context
->class_inst
)
1117 if (method
->klass
->generic_container
)
1118 result
->klass
= klass_hint
;
1120 if (!result
->klass
) {
1121 MonoType
*inflated
= inflate_generic_type (NULL
, &method
->klass
->byval_arg
, context
, error
);
1122 if (!mono_error_ok (error
))
1125 result
->klass
= inflated
? mono_class_from_mono_type (inflated
) : method
->klass
;
1127 mono_metadata_free_type (inflated
);
1131 * FIXME: This should hold, but it doesn't:
1133 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1134 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1135 * g_assert (result->is_generic);
1138 * Fixing this here causes other things to break, hence a very
1139 * ugly hack in mini-trampolines.c - see
1140 * is_generic_method_definition().
1143 mono_method_inflated_lookup (iresult
, TRUE
);
1144 mono_loader_unlock ();
1148 mono_loader_unlock ();
1154 * mono_get_inflated_method:
1156 * Obsolete. We keep it around since it's mentioned in the public API.
1159 mono_get_inflated_method (MonoMethod
*method
)
1165 * mono_method_get_context_general:
1167 * @uninflated: handle uninflated methods?
1169 * Returns the generic context of a method or NULL if it doesn't have
1170 * one. For an inflated method that's the context stored in the
1171 * method. Otherwise it's in the method's generic container or in the
1172 * generic container of the method's class.
1175 mono_method_get_context_general (MonoMethod
*method
, gboolean uninflated
)
1177 if (method
->is_inflated
) {
1178 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1179 return &imethod
->context
;
1183 if (method
->is_generic
)
1184 return &(mono_method_get_generic_container (method
)->context
);
1185 if (method
->klass
->generic_container
)
1186 return &method
->klass
->generic_container
->context
;
1191 * mono_method_get_context:
1194 * Returns the generic context for method if it's inflated, otherwise
1198 mono_method_get_context (MonoMethod
*method
)
1200 return mono_method_get_context_general (method
, FALSE
);
1204 * mono_method_get_generic_container:
1206 * Returns the generic container of METHOD, which should be a generic method definition.
1207 * Returns NULL if METHOD is not a generic method definition.
1208 * LOCKING: Acquires the loader lock.
1210 MonoGenericContainer
*
1211 mono_method_get_generic_container (MonoMethod
*method
)
1213 MonoGenericContainer
*container
;
1215 if (!method
->is_generic
)
1218 container
= mono_image_property_lookup (method
->klass
->image
, method
, MONO_METHOD_PROP_GENERIC_CONTAINER
);
1219 g_assert (container
);
1225 * mono_method_set_generic_container:
1227 * Sets the generic container of METHOD to CONTAINER.
1228 * LOCKING: Acquires the loader lock.
1231 mono_method_set_generic_container (MonoMethod
*method
, MonoGenericContainer
* container
)
1233 g_assert (method
->is_generic
);
1235 mono_image_property_insert (method
->klass
->image
, method
, MONO_METHOD_PROP_GENERIC_CONTAINER
, container
);
1239 * mono_class_find_enum_basetype:
1240 * @class: The enum class
1242 * Determine the basetype of an enum by iterating through its fields. We do this
1243 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1246 mono_class_find_enum_basetype (MonoClass
*class)
1248 MonoGenericContainer
*container
= NULL
;
1249 MonoImage
*m
= class->image
;
1250 const int top
= class->field
.count
;
1253 g_assert (class->enumtype
);
1255 if (class->generic_container
)
1256 container
= class->generic_container
;
1257 else if (class->generic_class
) {
1258 MonoClass
*gklass
= class->generic_class
->container_class
;
1260 container
= gklass
->generic_container
;
1261 g_assert (container
);
1265 * Fetch all the field information.
1267 for (i
= 0; i
< top
; i
++){
1269 guint32 cols
[MONO_FIELD_SIZE
];
1270 int idx
= class->field
.first
+ i
;
1273 /* class->field.first and idx points into the fieldptr table */
1274 mono_metadata_decode_table_row (m
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
1276 if (cols
[MONO_FIELD_FLAGS
] & FIELD_ATTRIBUTE_STATIC
) //no need to decode static fields
1279 if (!mono_verifier_verify_field_signature (class->image
, cols
[MONO_FIELD_SIGNATURE
], NULL
))
1282 sig
= mono_metadata_blob_heap (m
, cols
[MONO_FIELD_SIGNATURE
]);
1283 mono_metadata_decode_value (sig
, &sig
);
1284 /* FIELD signature == 0x06 */
1288 ftype
= mono_metadata_parse_type_full (m
, container
, MONO_PARSE_FIELD
, cols
[MONO_FIELD_FLAGS
], sig
+ 1, &sig
);
1291 if (class->generic_class
) {
1292 //FIXME do we leak here?
1293 ftype
= mono_class_inflate_generic_type (ftype
, mono_class_get_context (class));
1294 ftype
->attrs
= cols
[MONO_FIELD_FLAGS
];
1304 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1307 mono_type_has_exceptions (MonoType
*type
)
1309 switch (type
->type
) {
1310 case MONO_TYPE_CLASS
:
1311 case MONO_TYPE_VALUETYPE
:
1312 case MONO_TYPE_SZARRAY
:
1313 return type
->data
.klass
->exception_type
;
1314 case MONO_TYPE_ARRAY
:
1315 return type
->data
.array
->eklass
->exception_type
;
1316 case MONO_TYPE_GENERICINST
:
1317 return mono_generic_class_get_class (type
->data
.generic_class
)->exception_type
;
1325 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1329 mono_class_alloc (MonoClass
*class, int size
)
1331 if (class->generic_class
)
1332 return mono_image_set_alloc (class->generic_class
->owner
, size
);
1334 return mono_image_alloc (class->image
, size
);
1338 mono_class_alloc0 (MonoClass
*class, int size
)
1342 res
= mono_class_alloc (class, size
);
1343 memset (res
, 0, size
);
1347 #define mono_class_new0(class,struct_type, n_structs) \
1348 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1351 * mono_class_setup_basic_field_info:
1352 * @class: The class to initialize
1354 * Initializes the class->fields.
1355 * LOCKING: Assumes the loader lock is held.
1358 mono_class_setup_basic_field_info (MonoClass
*class)
1360 MonoClassField
*field
;
1368 gtd
= class->generic_class
? mono_class_get_generic_type_definition (class) : NULL
;
1369 image
= class->image
;
1370 top
= class->field
.count
;
1372 if (class->generic_class
&& class->generic_class
->container_class
->image
->dynamic
&& !class->generic_class
->container_class
->wastypebuilder
) {
1374 * This happens when a generic instance of an unfinished generic typebuilder
1375 * is used as an element type for creating an array type. We can't initialize
1376 * the fields of this class using the fields of gklass, since gklass is not
1377 * finished yet, fields could be added to it later.
1383 mono_class_setup_basic_field_info (gtd
);
1385 top
= gtd
->field
.count
;
1386 class->field
.first
= gtd
->field
.first
;
1387 class->field
.count
= gtd
->field
.count
;
1390 class->fields
= mono_class_alloc0 (class, sizeof (MonoClassField
) * top
);
1393 * Fetch all the field information.
1395 for (i
= 0; i
< top
; i
++){
1396 field
= &class->fields
[i
];
1397 field
->parent
= class;
1400 field
->name
= mono_field_get_name (>d
->fields
[i
]);
1402 int idx
= class->field
.first
+ i
;
1403 /* class->field.first and idx points into the fieldptr table */
1404 guint32 name_idx
= mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_NAME
);
1405 /* The name is needed for fieldrefs */
1406 field
->name
= mono_metadata_string_heap (image
, name_idx
);
1412 * mono_class_setup_fields:
1413 * @class: The class to initialize
1415 * Initializes the class->fields.
1416 * LOCKING: Assumes the loader lock is held.
1419 mono_class_setup_fields (MonoClass
*class)
1422 MonoImage
*m
= class->image
;
1424 guint32 layout
= class->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
;
1425 int i
, blittable
= TRUE
;
1426 guint32 real_size
= 0;
1427 guint32 packing_size
= 0;
1428 gboolean explicit_size
;
1429 MonoClassField
*field
;
1430 MonoGenericContainer
*container
= NULL
;
1431 MonoClass
*gtd
= class->generic_class
? mono_class_get_generic_type_definition (class) : NULL
;
1434 * FIXME: We have a race condition here. It's possible that this function returns
1435 * to its caller with `instance_size` set to `0` instead of the actual size. This
1436 * is not a problem when the function is called recursively on the same class,
1437 * because the size will be initialized by the outer invocation. What follows is a
1438 * description of how it can occur in other cases, too. There it is a problem,
1439 * because it can lead to the GC being asked to allocate an object of size `0`,
1440 * which SGen chokes on. The race condition is triggered infrequently by
1441 * `tests/sgen-suspend.cs`.
1443 * This function is called for a class whenever one of its subclasses is inited.
1444 * For example, it's called for every subclass of Object. What it does is this:
1446 * if (class->setup_fields_called)
1449 * class->instance_size = 0;
1451 * class->setup_fields_called = 1;
1452 * ... critical point
1453 * class->instance_size = actual_instance_size;
1455 * The last two steps are sometimes reversed, but that only changes the way in which
1456 * the race condition works.
1458 * Assume thread A goes through this function and makes it to the critical point.
1459 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1460 * immediately, but `instance_size` is incorrect.
1462 * The other case looks like this:
1464 * if (class->setup_fields_called)
1466 * ... critical point X
1467 * class->instance_size = 0;
1468 * ... critical point Y
1469 * class->instance_size = actual_instance_size;
1471 * class->setup_fields_called = 1;
1473 * Assume thread A goes through the function and makes it to critical point X. Now
1474 * thread B runs through the whole of the function, returning, assuming
1475 * `instance_size` is set. At that point thread A gets to run and makes it to
1476 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1479 if (class->setup_fields_called
)
1482 if (class->generic_class
&& class->generic_class
->container_class
->image
->dynamic
&& !class->generic_class
->container_class
->wastypebuilder
) {
1484 * This happens when a generic instance of an unfinished generic typebuilder
1485 * is used as an element type for creating an array type. We can't initialize
1486 * the fields of this class using the fields of gklass, since gklass is not
1487 * finished yet, fields could be added to it later.
1492 mono_class_setup_basic_field_info (class);
1493 top
= class->field
.count
;
1496 mono_class_setup_fields (gtd
);
1497 if (gtd
->exception_type
) {
1498 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1503 class->instance_size
= 0;
1505 class->sizes
.class_size
= 0;
1507 if (class->parent
) {
1508 /* For generic instances, class->parent might not have been initialized */
1509 mono_class_init (class->parent
);
1510 if (!class->parent
->size_inited
) {
1511 mono_class_setup_fields (class->parent
);
1512 if (class->parent
->exception_type
) {
1513 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1517 class->instance_size
+= class->parent
->instance_size
;
1518 class->min_align
= class->parent
->min_align
;
1519 /* we use |= since it may have been set already */
1520 class->has_references
|= class->parent
->has_references
;
1521 blittable
= class->parent
->blittable
;
1523 class->instance_size
= sizeof (MonoObject
);
1524 class->min_align
= 1;
1527 /* We can't really enable 16 bytes alignment until the GC supports it.
1528 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1529 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1530 Bug #506144 is an example of this issue.
1532 if (class->simd_type)
1533 class->min_align = 16;
1535 /* Get the real size */
1536 explicit_size
= mono_metadata_packing_from_typedef (class->image
, class->type_token
, &packing_size
, &real_size
);
1538 if (explicit_size
) {
1539 if ((packing_size
& 0xfffffff0) != 0) {
1540 char *err_msg
= g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name
, packing_size
);
1541 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
1544 class->packing_size
= packing_size
;
1545 real_size
+= class->instance_size
;
1549 if (explicit_size
&& real_size
) {
1550 class->instance_size
= MAX (real_size
, class->instance_size
);
1552 class->blittable
= blittable
;
1553 mono_memory_barrier ();
1554 class->size_inited
= 1;
1555 class->fields_inited
= 1;
1556 class->setup_fields_called
= 1;
1560 if (layout
== TYPE_ATTRIBUTE_AUTO_LAYOUT
)
1563 /* Prevent infinite loops if the class references itself */
1564 class->setup_fields_called
= 1;
1566 if (class->generic_container
) {
1567 container
= class->generic_container
;
1569 container
= gtd
->generic_container
;
1570 g_assert (container
);
1574 * Fetch all the field information.
1576 for (i
= 0; i
< top
; i
++){
1577 int idx
= class->field
.first
+ i
;
1578 field
= &class->fields
[i
];
1580 field
->parent
= class;
1583 mono_field_resolve_type (field
, &error
);
1584 if (!mono_error_ok (&error
)) {
1585 /*mono_field_resolve_type already failed class*/
1586 mono_error_cleanup (&error
);
1590 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field
->name
);
1591 g_assert (field
->type
);
1594 if (mono_field_is_deleted (field
))
1597 MonoClassField
*gfield
= >d
->fields
[i
];
1598 field
->offset
= gfield
->offset
;
1600 if (layout
== TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) {
1602 mono_metadata_field_info (m
, idx
, &offset
, NULL
, NULL
);
1603 field
->offset
= offset
;
1605 if (field
->offset
== (guint32
)-1 && !(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1606 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Missing field layout info for %s", field
->name
));
1609 if (field
->offset
< -1) { /*-1 is used to encode special static fields */
1610 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Invalid negative field offset %d for %s", field
->offset
, field
->name
));
1616 /* Only do these checks if we still think this type is blittable */
1617 if (blittable
&& !(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1618 if (field
->type
->byref
|| MONO_TYPE_IS_REFERENCE (field
->type
)) {
1621 MonoClass
*field_class
= mono_class_from_mono_type (field
->type
);
1623 mono_class_setup_fields (field_class
);
1624 if (field_class
->exception_type
) {
1625 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1629 if (!field_class
|| !field_class
->blittable
)
1634 if (class->enumtype
&& !(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1635 class->cast_class
= class->element_class
= mono_class_from_mono_type (field
->type
);
1636 blittable
= class->element_class
->blittable
;
1639 if (mono_type_has_exceptions (field
->type
)) {
1640 char *class_name
= mono_type_get_full_name (class);
1641 char *type_name
= mono_type_full_name (field
->type
);
1643 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1644 g_warning ("Invalid type %s for instance field %s:%s", type_name
, class_name
, field
->name
);
1645 g_free (class_name
);
1649 /* The def_value of fields is compute lazily during vtable creation */
1652 if (class == mono_defaults
.string_class
)
1655 class->blittable
= blittable
;
1657 if (class->enumtype
&& !mono_class_enum_basetype (class)) {
1658 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1661 if (explicit_size
&& real_size
) {
1662 class->instance_size
= MAX (real_size
, class->instance_size
);
1665 if (class->exception_type
)
1667 mono_class_layout_fields (class);
1669 /*valuetypes can't be neither bigger than 1Mb or empty. */
1670 if (class->valuetype
&& (class->instance_size
<= 0 || class->instance_size
> (0x100000 + sizeof (MonoObject
))))
1671 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1673 mono_memory_barrier ();
1674 class->fields_inited
= 1;
1678 * mono_class_setup_fields_locking:
1679 * @class: The class to initialize
1681 * Initializes the class->fields array of fields.
1682 * Aquires the loader lock.
1685 mono_class_setup_fields_locking (MonoClass
*class)
1687 /* This can be checked without locks */
1688 if (class->fields_inited
)
1690 mono_loader_lock ();
1691 mono_class_setup_fields (class);
1692 mono_loader_unlock ();
1696 * mono_class_has_references:
1698 * Returns whenever @klass->has_references is set, initializing it if needed.
1699 * Aquires the loader lock.
1702 mono_class_has_references (MonoClass
*klass
)
1704 if (klass
->init_pending
) {
1705 /* Be conservative */
1708 mono_class_init (klass
);
1710 return klass
->has_references
;
1715 * mono_type_get_basic_type_from_generic:
1718 * Returns a closed type corresponding to the possibly open type
1722 mono_type_get_basic_type_from_generic (MonoType
*type
)
1724 /* When we do generic sharing we let type variables stand for reference types. */
1725 if (!type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
))
1726 return &mono_defaults
.object_class
->byval_arg
;
1731 * mono_class_layout_fields:
1734 * Compute the placement of fields inside an object or struct, according to
1735 * the layout rules and set the following fields in @class:
1736 * - has_references (if the class contains instance references firled or structs that contain references)
1737 * - has_static_refs (same, but for static fields)
1738 * - instance_size (size of the object in memory)
1739 * - class_size (size needed for the static fields)
1740 * - size_inited (flag set when the instance_size is set)
1742 * LOCKING: this is supposed to be called with the loader lock held.
1745 mono_class_layout_fields (MonoClass
*class)
1748 const int top
= class->field
.count
;
1749 guint32 layout
= class->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
;
1750 guint32 pass
, passes
, real_size
;
1751 gboolean gc_aware_layout
= FALSE
;
1752 gboolean has_static_fields
= FALSE
;
1753 MonoClassField
*field
;
1756 * When we do generic sharing we need to have layout
1757 * information for open generic classes (either with a generic
1758 * context containing type variables or with a generic
1759 * container), so we don't return in that case anymore.
1763 * Enable GC aware auto layout: in this mode, reference
1764 * fields are grouped together inside objects, increasing collector
1766 * Requires that all classes whose layout is known to native code be annotated
1767 * with [StructLayout (LayoutKind.Sequential)]
1768 * Value types have gc_aware_layout disabled by default, as per
1769 * what the default is for other runtimes.
1771 /* corlib is missing [StructLayout] directives in many places */
1772 if (layout
== TYPE_ATTRIBUTE_AUTO_LAYOUT
) {
1773 if (!class->valuetype
)
1774 gc_aware_layout
= TRUE
;
1777 /* Compute klass->has_references */
1779 * Process non-static fields first, since static fields might recursively
1780 * refer to the class itself.
1782 for (i
= 0; i
< top
; i
++) {
1785 field
= &class->fields
[i
];
1787 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
1788 ftype
= mono_type_get_underlying_type (field
->type
);
1789 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1790 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
)))))
1791 class->has_references
= TRUE
;
1795 for (i
= 0; i
< top
; i
++) {
1798 field
= &class->fields
[i
];
1800 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
1801 ftype
= mono_type_get_underlying_type (field
->type
);
1802 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1803 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
)))))
1804 class->has_static_refs
= TRUE
;
1808 for (i
= 0; i
< top
; i
++) {
1811 field
= &class->fields
[i
];
1813 ftype
= mono_type_get_underlying_type (field
->type
);
1814 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1815 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
))))) {
1816 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1817 class->has_static_refs
= TRUE
;
1819 class->has_references
= TRUE
;
1824 * Compute field layout and total size (not considering static fields)
1828 case TYPE_ATTRIBUTE_AUTO_LAYOUT
:
1829 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT
:
1831 if (gc_aware_layout
)
1836 if (layout
!= TYPE_ATTRIBUTE_AUTO_LAYOUT
)
1839 if (class->parent
) {
1840 mono_class_setup_fields (class->parent
);
1841 if (class->parent
->exception_type
) {
1842 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1845 real_size
= class->parent
->instance_size
;
1847 real_size
= sizeof (MonoObject
);
1850 for (pass
= 0; pass
< passes
; ++pass
) {
1851 for (i
= 0; i
< top
; i
++){
1856 field
= &class->fields
[i
];
1858 if (mono_field_is_deleted (field
))
1860 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1863 ftype
= mono_type_get_underlying_type (field
->type
);
1864 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1865 if (gc_aware_layout
) {
1866 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
))))) {
1875 if ((top
== 1) && (class->instance_size
== sizeof (MonoObject
)) &&
1876 (strcmp (mono_field_get_name (field
), "$PRIVATE$") == 0)) {
1877 /* This field is a hack inserted by MCS to empty structures */
1881 size
= mono_type_size (field
->type
, &align
);
1883 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1884 align
= class->packing_size
? MIN (class->packing_size
, align
): align
;
1885 /* if the field has managed references, we need to force-align it
1888 if (MONO_TYPE_IS_REFERENCE (ftype
) || IS_GC_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
)))))
1889 align
= MAX (align
, sizeof (gpointer
));
1891 class->min_align
= MAX (align
, class->min_align
);
1892 field
->offset
= real_size
;
1894 field
->offset
+= align
- 1;
1895 field
->offset
&= ~(align
- 1);
1897 /*TypeBuilders produce all sort of weird things*/
1898 g_assert (class->image
->dynamic
|| field
->offset
> 0);
1899 real_size
= field
->offset
+ size
;
1902 class->instance_size
= MAX (real_size
, class->instance_size
);
1904 if (class->instance_size
& (class->min_align
- 1)) {
1905 class->instance_size
+= class->min_align
- 1;
1906 class->instance_size
&= ~(class->min_align
- 1);
1910 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
:
1912 for (i
= 0; i
< top
; i
++) {
1917 field
= &class->fields
[i
];
1920 * There must be info about all the fields in a type if it
1921 * uses explicit layout.
1924 if (mono_field_is_deleted (field
))
1926 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1929 size
= mono_type_size (field
->type
, &align
);
1930 align
= class->packing_size
? MIN (class->packing_size
, align
): align
;
1931 class->min_align
= MAX (align
, class->min_align
);
1934 * When we get here, field->offset is already set by the
1935 * loader (for either runtime fields or fields loaded from metadata).
1936 * The offset is from the start of the object: this works for both
1937 * classes and valuetypes.
1939 field
->offset
+= sizeof (MonoObject
);
1940 ftype
= mono_type_get_underlying_type (field
->type
);
1941 ftype
= mono_type_get_basic_type_from_generic (ftype
);
1942 if (MONO_TYPE_IS_REFERENCE (ftype
) || ((MONO_TYPE_ISSTRUCT (ftype
) && mono_class_has_references (mono_class_from_mono_type (ftype
))))) {
1943 if (field
->offset
% sizeof (gpointer
)) {
1944 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1951 real_size
= MAX (real_size
, size
+ field
->offset
);
1953 class->instance_size
= MAX (real_size
, class->instance_size
);
1954 if (class->instance_size
& (class->min_align
- 1)) {
1955 class->instance_size
+= class->min_align
- 1;
1956 class->instance_size
&= ~(class->min_align
- 1);
1961 if (layout
!= TYPE_ATTRIBUTE_EXPLICIT_LAYOUT
) {
1963 * For small structs, set min_align to at least the struct size to improve
1964 * performance, and since the JIT memset/memcpy code assumes this and generates
1965 * unaligned accesses otherwise. See #78990 for a testcase.
1967 if (class->instance_size
<= sizeof (MonoObject
) + sizeof (gpointer
))
1968 class->min_align
= MAX (class->min_align
, class->instance_size
- sizeof (MonoObject
));
1971 mono_memory_barrier ();
1972 class->size_inited
= 1;
1975 * Compute static field layout and size
1977 for (i
= 0; i
< top
; i
++){
1981 field
= &class->fields
[i
];
1983 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) || field
->type
->attrs
& FIELD_ATTRIBUTE_LITERAL
)
1985 if (mono_field_is_deleted (field
))
1988 if (mono_type_has_exceptions (field
->type
)) {
1989 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
1993 has_static_fields
= TRUE
;
1995 size
= mono_type_size (field
->type
, &align
);
1996 field
->offset
= class->sizes
.class_size
;
1997 /*align is always non-zero here*/
1998 field
->offset
+= align
- 1;
1999 field
->offset
&= ~(align
- 1);
2000 class->sizes
.class_size
= field
->offset
+ size
;
2003 if (has_static_fields
&& class->sizes
.class_size
== 0)
2004 /* Simplify code which depends on class_size != 0 if the class has static fields */
2005 class->sizes
.class_size
= 8;
2009 create_array_method (MonoClass
*class, const char *name
, MonoMethodSignature
*sig
)
2013 method
= (MonoMethod
*) mono_image_alloc0 (class->image
, sizeof (MonoMethodPInvoke
));
2014 method
->klass
= class;
2015 method
->flags
= METHOD_ATTRIBUTE_PUBLIC
;
2016 method
->iflags
= METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
;
2017 method
->signature
= sig
;
2018 method
->name
= name
;
2021 if (name
[0] == '.') {
2022 method
->flags
|= METHOD_ATTRIBUTE_RT_SPECIAL_NAME
| METHOD_ATTRIBUTE_SPECIAL_NAME
;
2024 method
->iflags
|= METHOD_IMPL_ATTRIBUTE_RUNTIME
;
2030 * mono_class_setup_methods:
2033 * Initializes the 'methods' array in the klass.
2034 * Calling this method should be avoided if possible since it allocates a lot
2035 * of long-living MonoMethod structures.
2036 * Methods belonging to an interface are assigned a sequential slot starting
2039 * On failure this function sets class->exception_type
2042 mono_class_setup_methods (MonoClass
*class)
2045 MonoMethod
**methods
;
2050 mono_loader_lock ();
2052 if (class->methods
) {
2053 mono_loader_unlock ();
2057 if (class->generic_class
) {
2059 MonoClass
*gklass
= class->generic_class
->container_class
;
2061 mono_class_init (gklass
);
2062 if (!gklass
->exception_type
)
2063 mono_class_setup_methods (gklass
);
2064 if (gklass
->exception_type
) {
2065 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2066 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Generic type definition failed to load"));
2067 mono_loader_unlock ();
2071 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2072 class->method
.count
= gklass
->method
.count
;
2073 methods
= mono_class_alloc0 (class, sizeof (MonoMethod
*) * (class->method
.count
+ 1));
2075 for (i
= 0; i
< class->method
.count
; i
++) {
2076 methods
[i
] = mono_class_inflate_generic_method_full_checked (
2077 gklass
->methods
[i
], class, mono_class_get_context (class), &error
);
2078 if (!mono_error_ok (&error
)) {
2079 char *method
= mono_method_full_name (gklass
->methods
[i
], TRUE
);
2080 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
)));
2083 mono_error_cleanup (&error
);
2084 mono_loader_unlock ();
2088 } else if (class->rank
) {
2090 MonoMethod
*amethod
;
2091 MonoMethodSignature
*sig
;
2092 int count_generic
= 0, first_generic
= 0;
2095 class->method
.count
= 3 + (class->rank
> 1? 2: 1);
2097 mono_class_setup_interfaces (class, &error
);
2098 g_assert (mono_error_ok (&error
)); /*FIXME can this fail for array types?*/
2100 if (class->interface_count
) {
2101 count_generic
= generic_array_methods (class);
2102 first_generic
= class->method
.count
;
2103 class->method
.count
+= class->interface_count
* count_generic
;
2106 methods
= mono_class_alloc0 (class, sizeof (MonoMethod
*) * class->method
.count
);
2108 sig
= mono_metadata_signature_alloc (class->image
, class->rank
);
2109 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
2110 sig
->pinvoke
= TRUE
;
2111 sig
->hasthis
= TRUE
;
2112 for (i
= 0; i
< class->rank
; ++i
)
2113 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2115 amethod
= create_array_method (class, ".ctor", sig
);
2116 methods
[method_num
++] = amethod
;
2117 if (class->rank
> 1) {
2118 sig
= mono_metadata_signature_alloc (class->image
, class->rank
* 2);
2119 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
2120 sig
->pinvoke
= TRUE
;
2121 sig
->hasthis
= TRUE
;
2122 for (i
= 0; i
< class->rank
* 2; ++i
)
2123 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2125 amethod
= create_array_method (class, ".ctor", sig
);
2126 methods
[method_num
++] = amethod
;
2128 /* element Get (idx11, [idx2, ...]) */
2129 sig
= mono_metadata_signature_alloc (class->image
, class->rank
);
2130 sig
->ret
= &class->element_class
->byval_arg
;
2131 sig
->pinvoke
= TRUE
;
2132 sig
->hasthis
= TRUE
;
2133 for (i
= 0; i
< class->rank
; ++i
)
2134 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2135 amethod
= create_array_method (class, "Get", sig
);
2136 methods
[method_num
++] = amethod
;
2137 /* element& Address (idx11, [idx2, ...]) */
2138 sig
= mono_metadata_signature_alloc (class->image
, class->rank
);
2139 sig
->ret
= &class->element_class
->this_arg
;
2140 sig
->pinvoke
= TRUE
;
2141 sig
->hasthis
= TRUE
;
2142 for (i
= 0; i
< class->rank
; ++i
)
2143 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2144 amethod
= create_array_method (class, "Address", sig
);
2145 methods
[method_num
++] = amethod
;
2146 /* void Set (idx11, [idx2, ...], element) */
2147 sig
= mono_metadata_signature_alloc (class->image
, class->rank
+ 1);
2148 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
2149 sig
->pinvoke
= TRUE
;
2150 sig
->hasthis
= TRUE
;
2151 for (i
= 0; i
< class->rank
; ++i
)
2152 sig
->params
[i
] = &mono_defaults
.int32_class
->byval_arg
;
2153 sig
->params
[i
] = &class->element_class
->byval_arg
;
2154 amethod
= create_array_method (class, "Set", sig
);
2155 methods
[method_num
++] = amethod
;
2157 for (i
= 0; i
< class->interface_count
; i
++)
2158 setup_generic_array_ifaces (class, class->interfaces
[i
], methods
, first_generic
+ i
* count_generic
);
2160 methods
= mono_class_alloc (class, sizeof (MonoMethod
*) * class->method
.count
);
2161 for (i
= 0; i
< class->method
.count
; ++i
) {
2162 int idx
= mono_metadata_translate_token_index (class->image
, MONO_TABLE_METHOD
, class->method
.first
+ i
+ 1);
2163 methods
[i
] = mono_get_method (class->image
, MONO_TOKEN_METHOD_DEF
| idx
, class);
2167 if (MONO_CLASS_IS_INTERFACE (class)) {
2169 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2170 for (i
= 0; i
< class->method
.count
; ++i
) {
2171 if (methods
[i
]->flags
& METHOD_ATTRIBUTE_VIRTUAL
)
2172 methods
[i
]->slot
= slot
++;
2176 /* Needed because of the double-checking locking pattern */
2177 mono_memory_barrier ();
2179 class->methods
= methods
;
2181 mono_loader_unlock ();
2185 * mono_class_get_method_by_index:
2187 * Returns class->methods [index], initializing class->methods if neccesary.
2189 * LOCKING: Acquires the loader lock.
2192 mono_class_get_method_by_index (MonoClass
*class, int index
)
2194 /* Avoid calling setup_methods () if possible */
2195 if (class->generic_class
&& !class->methods
) {
2196 MonoClass
*gklass
= class->generic_class
->container_class
;
2199 m
= mono_class_inflate_generic_method_full (
2200 gklass
->methods
[index
], class, mono_class_get_context (class));
2202 * If setup_methods () is called later for this class, no duplicates are created,
2203 * since inflate_generic_method guarantees that only one instance of a method
2204 * is created for each context.
2207 mono_class_setup_methods (class);
2208 g_assert (m == class->methods [index]);
2212 mono_class_setup_methods (class);
2213 if (class->exception_type
) /*FIXME do proper error handling*/
2215 g_assert (index
>= 0 && index
< class->method
.count
);
2216 return class->methods
[index
];
2221 * mono_class_get_inflated_method:
2223 * Given an inflated class CLASS and a method METHOD which should be a method of
2224 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2227 mono_class_get_inflated_method (MonoClass
*class, MonoMethod
*method
)
2229 MonoClass
*gklass
= class->generic_class
->container_class
;
2232 g_assert (method
->klass
== gklass
);
2234 mono_class_setup_methods (gklass
);
2235 g_assert (!gklass
->exception_type
); /*FIXME do proper error handling*/
2237 for (i
= 0; i
< gklass
->method
.count
; ++i
) {
2238 if (gklass
->methods
[i
] == method
) {
2240 return class->methods
[i
];
2242 return mono_class_inflate_generic_method_full (gklass
->methods
[i
], class, mono_class_get_context (class));
2250 * mono_class_get_vtable_entry:
2252 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2253 * LOCKING: Acquires the loader lock.
2256 mono_class_get_vtable_entry (MonoClass
*class, int offset
)
2260 if (class->rank
== 1) {
2262 * szarrays do not overwrite any methods of Array, so we can avoid
2263 * initializing their vtables in some cases.
2265 mono_class_setup_vtable (class->parent
);
2266 if (offset
< class->parent
->vtable_size
)
2267 return class->parent
->vtable
[offset
];
2270 if (class->generic_class
) {
2271 MonoClass
*gklass
= class->generic_class
->container_class
;
2272 mono_class_setup_vtable (gklass
);
2273 m
= gklass
->vtable
[offset
];
2275 m
= mono_class_inflate_generic_method_full (m
, class, mono_class_get_context (class));
2277 mono_class_setup_vtable (class);
2278 if (class->exception_type
)
2280 m
= class->vtable
[offset
];
2287 * mono_class_get_vtable_size:
2289 * Return the vtable size for KLASS.
2292 mono_class_get_vtable_size (MonoClass
*klass
)
2294 mono_class_setup_vtable (klass
);
2296 return klass
->vtable_size
;
2299 /*This method can fail the class.*/
2301 mono_class_setup_properties (MonoClass
*class)
2303 guint startm
, endm
, i
, j
;
2304 guint32 cols
[MONO_PROPERTY_SIZE
];
2305 MonoTableInfo
*msemt
= &class->image
->tables
[MONO_TABLE_METHODSEMANTICS
];
2306 MonoProperty
*properties
;
2309 if (class->ext
&& class->ext
->properties
)
2312 mono_loader_lock ();
2314 if (class->ext
&& class->ext
->properties
) {
2315 mono_loader_unlock ();
2319 mono_class_alloc_ext (class);
2321 if (class->generic_class
) {
2322 MonoClass
*gklass
= class->generic_class
->container_class
;
2324 mono_class_init (gklass
);
2325 mono_class_setup_properties (gklass
);
2326 if (gklass
->exception_type
) {
2327 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Generic type definition failed to load"));
2328 mono_loader_unlock ();
2332 class->ext
->property
= gklass
->ext
->property
;
2334 properties
= mono_class_new0 (class, MonoProperty
, class->ext
->property
.count
+ 1);
2336 for (i
= 0; i
< class->ext
->property
.count
; i
++) {
2337 MonoProperty
*prop
= &properties
[i
];
2339 *prop
= gklass
->ext
->properties
[i
];
2342 prop
->get
= mono_class_inflate_generic_method_full (
2343 prop
->get
, class, mono_class_get_context (class));
2345 prop
->set
= mono_class_inflate_generic_method_full (
2346 prop
->set
, class, mono_class_get_context (class));
2348 prop
->parent
= class;
2351 int first
= mono_metadata_properties_from_typedef (class->image
, mono_metadata_token_index (class->type_token
) - 1, &last
);
2352 int count
= last
- first
;
2355 mono_class_setup_methods (class);
2356 if (class->exception_type
) {
2357 mono_loader_unlock ();
2362 class->ext
->property
.first
= first
;
2363 class->ext
->property
.count
= count
;
2364 properties
= mono_class_alloc0 (class, sizeof (MonoProperty
) * count
);
2365 for (i
= first
; i
< last
; ++i
) {
2366 mono_metadata_decode_table_row (class->image
, MONO_TABLE_PROPERTY
, i
, cols
, MONO_PROPERTY_SIZE
);
2367 properties
[i
- first
].parent
= class;
2368 properties
[i
- first
].attrs
= cols
[MONO_PROPERTY_FLAGS
];
2369 properties
[i
- first
].name
= mono_metadata_string_heap (class->image
, cols
[MONO_PROPERTY_NAME
]);
2371 startm
= mono_metadata_methods_from_property (class->image
, i
, &endm
);
2372 for (j
= startm
; j
< endm
; ++j
) {
2375 mono_metadata_decode_row (msemt
, j
, cols
, MONO_METHOD_SEMA_SIZE
);
2377 if (class->image
->uncompressed_metadata
)
2378 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2379 method
= mono_get_method (class->image
, MONO_TOKEN_METHOD_DEF
| cols
[MONO_METHOD_SEMA_METHOD
], class);
2381 method
= class->methods
[cols
[MONO_METHOD_SEMA_METHOD
] - 1 - class->method
.first
];
2383 switch (cols
[MONO_METHOD_SEMA_SEMANTICS
]) {
2384 case METHOD_SEMANTIC_SETTER
:
2385 properties
[i
- first
].set
= method
;
2387 case METHOD_SEMANTIC_GETTER
:
2388 properties
[i
- first
].get
= method
;
2396 /*Flush any pending writes as we do double checked locking on class->properties */
2397 mono_memory_barrier ();
2399 /* Leave this assignment as the last op in the function */
2400 class->ext
->properties
= properties
;
2402 mono_loader_unlock ();
2406 inflate_method_listz (MonoMethod
**methods
, MonoClass
*class, MonoGenericContext
*context
)
2408 MonoMethod
**om
, **retval
;
2411 for (om
= methods
, count
= 0; *om
; ++om
, ++count
)
2414 retval
= g_new0 (MonoMethod
*, count
+ 1);
2416 for (om
= methods
, count
= 0; *om
; ++om
, ++count
)
2417 retval
[count
] = mono_class_inflate_generic_method_full (*om
, class, context
);
2422 /*This method can fail the class.*/
2424 mono_class_setup_events (MonoClass
*class)
2427 guint startm
, endm
, i
, j
;
2428 guint32 cols
[MONO_EVENT_SIZE
];
2429 MonoTableInfo
*msemt
= &class->image
->tables
[MONO_TABLE_METHODSEMANTICS
];
2433 if (class->ext
&& class->ext
->events
)
2436 mono_loader_lock ();
2438 if (class->ext
&& class->ext
->events
) {
2439 mono_loader_unlock ();
2443 mono_class_alloc_ext (class);
2445 if (class->generic_class
) {
2446 MonoClass
*gklass
= class->generic_class
->container_class
;
2447 MonoGenericContext
*context
;
2449 mono_class_setup_events (gklass
);
2450 if (gklass
->exception_type
) {
2451 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Generic type definition failed to load"));
2452 mono_loader_unlock ();
2456 class->ext
->event
= gklass
->ext
->event
;
2457 class->ext
->events
= mono_class_new0 (class, MonoEvent
, class->ext
->event
.count
);
2459 if (class->ext
->event
.count
)
2460 context
= mono_class_get_context (class);
2462 for (i
= 0; i
< class->ext
->event
.count
; i
++) {
2463 MonoEvent
*event
= &class->ext
->events
[i
];
2464 MonoEvent
*gevent
= &gklass
->ext
->events
[i
];
2466 event
->parent
= class;
2467 event
->name
= gevent
->name
;
2468 event
->add
= gevent
->add
? mono_class_inflate_generic_method_full (gevent
->add
, class, context
) : NULL
;
2469 event
->remove
= gevent
->remove
? mono_class_inflate_generic_method_full (gevent
->remove
, class, context
) : NULL
;
2470 event
->raise
= gevent
->raise
? mono_class_inflate_generic_method_full (gevent
->raise
, class, context
) : NULL
;
2471 #ifndef MONO_SMALL_CONFIG
2472 event
->other
= gevent
->other
? inflate_method_listz (gevent
->other
, class, context
) : NULL
;
2474 event
->attrs
= gevent
->attrs
;
2477 mono_loader_unlock ();
2481 first
= mono_metadata_events_from_typedef (class->image
, mono_metadata_token_index (class->type_token
) - 1, &last
);
2482 count
= last
- first
;
2485 mono_class_setup_methods (class);
2486 if (class->exception_type
) {
2487 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Generic type definition failed to load"));
2488 mono_loader_unlock ();
2492 class->ext
->event
.first
= first
;
2493 class->ext
->event
.count
= count
;
2494 events
= mono_class_alloc0 (class, sizeof (MonoEvent
) * class->ext
->event
.count
);
2495 for (i
= first
; i
< last
; ++i
) {
2496 MonoEvent
*event
= &events
[i
- first
];
2498 mono_metadata_decode_table_row (class->image
, MONO_TABLE_EVENT
, i
, cols
, MONO_EVENT_SIZE
);
2499 event
->parent
= class;
2500 event
->attrs
= cols
[MONO_EVENT_FLAGS
];
2501 event
->name
= mono_metadata_string_heap (class->image
, cols
[MONO_EVENT_NAME
]);
2503 startm
= mono_metadata_methods_from_event (class->image
, i
, &endm
);
2504 for (j
= startm
; j
< endm
; ++j
) {
2507 mono_metadata_decode_row (msemt
, j
, cols
, MONO_METHOD_SEMA_SIZE
);
2509 if (class->image
->uncompressed_metadata
)
2510 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2511 method
= mono_get_method (class->image
, MONO_TOKEN_METHOD_DEF
| cols
[MONO_METHOD_SEMA_METHOD
], class);
2513 method
= class->methods
[cols
[MONO_METHOD_SEMA_METHOD
] - 1 - class->method
.first
];
2515 switch (cols
[MONO_METHOD_SEMA_SEMANTICS
]) {
2516 case METHOD_SEMANTIC_ADD_ON
:
2517 event
->add
= method
;
2519 case METHOD_SEMANTIC_REMOVE_ON
:
2520 event
->remove
= method
;
2522 case METHOD_SEMANTIC_FIRE
:
2523 event
->raise
= method
;
2525 case METHOD_SEMANTIC_OTHER
: {
2526 #ifndef MONO_SMALL_CONFIG
2529 if (event
->other
== NULL
) {
2530 event
->other
= g_new0 (MonoMethod
*, 2);
2532 while (event
->other
[n
])
2534 event
->other
= g_realloc (event
->other
, (n
+ 2) * sizeof (MonoMethod
*));
2536 event
->other
[n
] = method
;
2537 /* NULL terminated */
2538 event
->other
[n
+ 1] = NULL
;
2547 /*Flush any pending writes as we do double checked locking on class->properties */
2548 mono_memory_barrier ();
2550 /* Leave this assignment as the last op in the function */
2551 class->ext
->events
= events
;
2553 mono_loader_unlock ();
2557 * Global pool of interface IDs, represented as a bitset.
2558 * LOCKING: this is supposed to be accessed with the loader lock held.
2560 static MonoBitSet
*global_interface_bitset
= NULL
;
2563 * mono_unload_interface_ids:
2564 * @bitset: bit set of interface IDs
2566 * When an image is unloaded, the interface IDs associated with
2567 * the image are put back in the global pool of IDs so the numbers
2571 mono_unload_interface_ids (MonoBitSet
*bitset
)
2573 mono_loader_lock ();
2574 mono_bitset_sub (global_interface_bitset
, bitset
);
2575 mono_loader_unlock ();
2579 mono_unload_interface_id (MonoClass
*class)
2581 if (global_interface_bitset
&& class->interface_id
) {
2582 mono_loader_lock ();
2583 mono_bitset_clear (global_interface_bitset
, class->interface_id
);
2584 mono_loader_unlock ();
2589 * mono_get_unique_iid:
2592 * Assign a unique integer ID to the interface represented by @class.
2593 * The ID will positive and as small as possible.
2594 * LOCKING: this is supposed to be called with the loader lock held.
2595 * Returns: the new ID.
2598 mono_get_unique_iid (MonoClass
*class)
2602 g_assert (MONO_CLASS_IS_INTERFACE (class));
2604 if (!global_interface_bitset
) {
2605 global_interface_bitset
= mono_bitset_new (128, 0);
2608 iid
= mono_bitset_find_first_unset (global_interface_bitset
, -1);
2610 int old_size
= mono_bitset_size (global_interface_bitset
);
2611 MonoBitSet
*new_set
= mono_bitset_clone (global_interface_bitset
, old_size
* 2);
2612 mono_bitset_free (global_interface_bitset
);
2613 global_interface_bitset
= new_set
;
2616 mono_bitset_set (global_interface_bitset
, iid
);
2617 /* set the bit also in the per-image set */
2618 if (!class->generic_class
) {
2619 if (class->image
->interface_bitset
) {
2620 if (iid
>= mono_bitset_size (class->image
->interface_bitset
)) {
2621 MonoBitSet
*new_set
= mono_bitset_clone (class->image
->interface_bitset
, iid
+ 1);
2622 mono_bitset_free (class->image
->interface_bitset
);
2623 class->image
->interface_bitset
= new_set
;
2626 class->image
->interface_bitset
= mono_bitset_new (iid
+ 1, 0);
2628 mono_bitset_set (class->image
->interface_bitset
, iid
);
2631 #ifndef MONO_SMALL_CONFIG
2632 if (mono_print_vtable
) {
2634 char *type_name
= mono_type_full_name (&class->byval_arg
);
2635 if (class->generic_class
&& !class->generic_class
->context
.class_inst
->is_open
) {
2636 generic_id
= class->generic_class
->context
.class_inst
->id
;
2637 g_assert (generic_id
!= 0);
2641 printf ("Interface: assigned id %d to %s|%s|%d\n", iid
, class->image
->name
, type_name
, generic_id
);
2646 g_assert (iid
<= 65535);
2651 collect_implemented_interfaces_aux (MonoClass
*klass
, GPtrArray
**res
, MonoError
*error
)
2656 mono_class_setup_interfaces (klass
, error
);
2657 if (!mono_error_ok (error
))
2660 for (i
= 0; i
< klass
->interface_count
; i
++) {
2661 ic
= klass
->interfaces
[i
];
2664 *res
= g_ptr_array_new ();
2665 g_ptr_array_add (*res
, ic
);
2666 mono_class_init (ic
);
2667 if (ic
->exception_type
) {
2668 mono_error_set_type_load_class (error
, ic
, "Error Loading class");
2672 collect_implemented_interfaces_aux (ic
, res
, error
);
2673 if (!mono_error_ok (error
))
2679 mono_class_get_implemented_interfaces (MonoClass
*klass
, MonoError
*error
)
2681 GPtrArray
*res
= NULL
;
2683 collect_implemented_interfaces_aux (klass
, &res
, error
);
2684 if (!mono_error_ok (error
)) {
2686 g_ptr_array_free (res
, TRUE
);
2693 compare_interface_ids (const void *p_key
, const void *p_element
) {
2694 const MonoClass
*key
= p_key
;
2695 const MonoClass
*element
= *(MonoClass
**) p_element
;
2697 return (key
->interface_id
- element
->interface_id
);
2700 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2702 mono_class_interface_offset (MonoClass
*klass
, MonoClass
*itf
) {
2703 MonoClass
**result
= mono_binary_search (
2705 klass
->interfaces_packed
,
2706 klass
->interface_offsets_count
,
2707 sizeof (MonoClass
*),
2708 compare_interface_ids
);
2710 return klass
->interface_offsets_packed
[result
- (klass
->interfaces_packed
)];
2717 * mono_class_interface_offset_with_variance:
2719 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2720 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2722 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2724 * FIXME figure out MS disambiguation rules and fix this function.
2727 mono_class_interface_offset_with_variance (MonoClass
*klass
, MonoClass
*itf
, gboolean
*non_exact_match
) {
2728 int i
= mono_class_interface_offset (klass
, itf
);
2729 *non_exact_match
= FALSE
;
2733 if (!mono_class_has_variant_generic_params (itf
))
2736 for (i
= 0; i
< klass
->interface_offsets_count
; i
++) {
2737 if (mono_class_is_variant_compatible (itf
, klass
->interfaces_packed
[i
], FALSE
)) {
2738 *non_exact_match
= TRUE
;
2739 return klass
->interface_offsets_packed
[i
];
2747 print_implemented_interfaces (MonoClass
*klass
) {
2750 GPtrArray
*ifaces
= NULL
;
2752 int ancestor_level
= 0;
2754 name
= mono_type_get_full_name (klass
);
2755 printf ("Packed interface table for class %s has size %d\n", name
, klass
->interface_offsets_count
);
2758 for (i
= 0; i
< klass
->interface_offsets_count
; i
++)
2759 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i
,
2760 klass
->interfaces_packed
[i
]->interface_id
,
2761 klass
->interface_offsets_packed
[i
],
2762 klass
->interfaces_packed
[i
]->method
.count
,
2763 klass
->interfaces_packed
[i
]->name_space
,
2764 klass
->interfaces_packed
[i
]->name
);
2765 printf ("Interface flags: ");
2766 for (i
= 0; i
<= klass
->max_interface_id
; i
++)
2767 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass
, i
))
2768 printf ("(%d,T)", i
);
2770 printf ("(%d,F)", i
);
2772 printf ("Dump interface flags:");
2773 #ifdef COMPRESSED_INTERFACE_BITMAP
2775 const uint8_t* p
= klass
->interface_bitmap
;
2776 i
= klass
->max_interface_id
;
2778 printf (" %d x 00 %02X", p
[0], p
[1]);
2784 for (i
= 0; i
< ((((klass
->max_interface_id
+ 1) >> 3)) + (((klass
->max_interface_id
+ 1) & 7)? 1 :0)); i
++)
2785 printf (" %02X", klass
->interface_bitmap
[i
]);
2788 while (klass
!= NULL
) {
2789 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level
, klass
->name
);
2790 ifaces
= mono_class_get_implemented_interfaces (klass
, &error
);
2791 if (!mono_error_ok (&error
)) {
2792 printf (" Type failed due to %s\n", mono_error_get_message (&error
));
2793 mono_error_cleanup (&error
);
2794 } else if (ifaces
) {
2795 for (i
= 0; i
< ifaces
->len
; i
++) {
2796 MonoClass
*ic
= g_ptr_array_index (ifaces
, i
);
2797 printf (" [UIID %d] interface %s\n", ic
->interface_id
, ic
->name
);
2798 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i
,
2800 mono_class_interface_offset (klass
, ic
),
2805 g_ptr_array_free (ifaces
, TRUE
);
2808 klass
= klass
->parent
;
2813 inflate_class_one_arg (MonoClass
*gtype
, MonoClass
*arg0
)
2816 args
[0] = &arg0
->byval_arg
;
2818 return mono_class_bind_generic_parameters (gtype
, 1, args
, FALSE
);
2822 array_class_get_if_rank (MonoClass
*class, guint rank
)
2824 return rank
? mono_array_class_get (class, rank
) : class;
2828 fill_valuetype_array_derived_types (MonoClass
**valuetype_types
, MonoClass
*eclass
, int rank
)
2830 valuetype_types
[0] = eclass
;
2831 if (eclass
== mono_defaults
.int16_class
)
2832 valuetype_types
[1] = mono_defaults
.uint16_class
;
2833 else if (eclass
== mono_defaults
.uint16_class
)
2834 valuetype_types
[1] = mono_defaults
.int16_class
;
2835 else if (eclass
== mono_defaults
.int32_class
)
2836 valuetype_types
[1] = mono_defaults
.uint32_class
;
2837 else if (eclass
== mono_defaults
.uint32_class
)
2838 valuetype_types
[1] = mono_defaults
.int32_class
;
2839 else if (eclass
== mono_defaults
.int64_class
)
2840 valuetype_types
[1] = mono_defaults
.uint64_class
;
2841 else if (eclass
== mono_defaults
.uint64_class
)
2842 valuetype_types
[1] = mono_defaults
.int64_class
;
2843 else if (eclass
== mono_defaults
.byte_class
)
2844 valuetype_types
[1] = mono_defaults
.sbyte_class
;
2845 else if (eclass
== mono_defaults
.sbyte_class
)
2846 valuetype_types
[1] = mono_defaults
.byte_class
;
2847 else if (eclass
->enumtype
&& mono_class_enum_basetype (eclass
))
2848 valuetype_types
[1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass
));
2851 /* this won't be needed once bug #325495 is completely fixed
2852 * though we'll need something similar to know which interfaces to allow
2853 * in arrays when they'll be lazyly created
2855 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2856 * MS returns diferrent types based on which instance is called. For example:
2857 * object obj = new byte[10][];
2858 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2859 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2862 * Fixing this should kill quite some code, save some bits and improve compatibility.
2865 get_implicit_generic_array_interfaces (MonoClass
*class, int *num
, int *is_enumerator
)
2867 MonoClass
*eclass
= class->element_class
;
2868 static MonoClass
* generic_icollection_class
= NULL
;
2869 static MonoClass
* generic_ienumerable_class
= NULL
;
2870 static MonoClass
* generic_ienumerator_class
= NULL
;
2871 static MonoClass
* generic_ireadonlylist_class
= NULL
;
2872 static MonoClass
* generic_ireadonlycollection_class
= NULL
;
2873 MonoClass
*valuetype_types
[2] = { NULL
, NULL
};
2874 MonoClass
**interfaces
= NULL
;
2875 int i
, nifaces
, interface_count
, real_count
, original_rank
;
2877 gboolean internal_enumerator
;
2878 gboolean eclass_is_valuetype
;
2880 if (!mono_defaults
.generic_ilist_class
) {
2884 internal_enumerator
= FALSE
;
2885 eclass_is_valuetype
= FALSE
;
2886 original_rank
= eclass
->rank
;
2887 if (class->byval_arg
.type
!= MONO_TYPE_SZARRAY
) {
2888 if (class->generic_class
&& class->nested_in
== mono_defaults
.array_class
&& strcmp (class->name
, "InternalEnumerator`1") == 0) {
2890 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2892 eclass
= mono_class_from_mono_type (class->generic_class
->context
.class_inst
->type_argv
[0]);
2893 original_rank
= eclass
->rank
;
2895 eclass
= eclass
->element_class
;
2896 internal_enumerator
= TRUE
;
2897 *is_enumerator
= TRUE
;
2905 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2906 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2908 all_interfaces
= eclass
->rank
&& eclass
->element_class
->rank
? FALSE
: TRUE
;
2910 if (!generic_icollection_class
) {
2911 generic_icollection_class
= mono_class_from_name (mono_defaults
.corlib
,
2912 "System.Collections.Generic", "ICollection`1");
2913 generic_ienumerable_class
= mono_class_from_name (mono_defaults
.corlib
,
2914 "System.Collections.Generic", "IEnumerable`1");
2915 generic_ienumerator_class
= mono_class_from_name (mono_defaults
.corlib
,
2916 "System.Collections.Generic", "IEnumerator`1");
2917 generic_ireadonlylist_class
= mono_class_from_name (mono_defaults
.corlib
,
2918 "System.Collections.Generic", "IReadOnlyList`1");
2919 generic_ireadonlycollection_class
= mono_class_from_name (mono_defaults
.corlib
,
2920 "System.Collections.Generic", "IReadOnlyCollection`1");
2923 mono_class_init (eclass
);
2926 * Arrays in 2.0 need to implement a number of generic interfaces
2927 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2928 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2929 * We collect the types needed to build the
2930 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2931 * the generic interfaces needed to implement.
2933 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2934 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2936 if (eclass
->valuetype
) {
2937 nifaces
= generic_ireadonlylist_class
? 5 : 3;
2938 fill_valuetype_array_derived_types (valuetype_types
, eclass
, original_rank
);
2940 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2941 real_count
= interface_count
= valuetype_types
[1] ? (nifaces
* 2) : nifaces
;
2942 if (internal_enumerator
) {
2944 if (valuetype_types
[1])
2948 interfaces
= g_malloc0 (sizeof (MonoClass
*) * real_count
);
2949 interfaces
[0] = valuetype_types
[0];
2950 if (valuetype_types
[1])
2951 interfaces
[nifaces
] = valuetype_types
[1];
2953 eclass_is_valuetype
= TRUE
;
2956 int idepth
= eclass
->idepth
;
2957 if (!internal_enumerator
)
2959 nifaces
= generic_ireadonlylist_class
? 2 : 3;
2961 // FIXME: This doesn't seem to work/required for generic params
2962 if (!(eclass
->this_arg
.type
== MONO_TYPE_VAR
|| eclass
->this_arg
.type
== MONO_TYPE_MVAR
|| (eclass
->image
->dynamic
&& !eclass
->wastypebuilder
)))
2963 mono_class_setup_interface_offsets (eclass
);
2965 interface_count
= all_interfaces
? eclass
->interface_offsets_count
: eclass
->interface_count
;
2966 /* we add object for interfaces and the supertypes for the other
2967 * types. The last of the supertypes is the element class itself which we
2968 * already created the explicit interfaces for (so we include it for IEnumerator
2969 * and exclude it for arrays).
2971 if (MONO_CLASS_IS_INTERFACE (eclass
))
2974 interface_count
+= idepth
;
2975 if (eclass
->rank
&& eclass
->element_class
->valuetype
) {
2976 fill_valuetype_array_derived_types (valuetype_types
, eclass
->element_class
, original_rank
);
2977 if (valuetype_types
[1])
2980 /* IList, ICollection, IEnumerable, IReadOnlyList */
2981 interface_count
*= nifaces
;
2982 real_count
= interface_count
;
2983 if (internal_enumerator
) {
2984 real_count
+= (MONO_CLASS_IS_INTERFACE (eclass
) ? 1 : idepth
) + eclass
->interface_offsets_count
;
2985 if (valuetype_types
[1])
2988 interfaces
= g_malloc0 (sizeof (MonoClass
*) * real_count
);
2989 if (MONO_CLASS_IS_INTERFACE (eclass
)) {
2990 interfaces
[0] = mono_defaults
.object_class
;
2994 for (i
= 0; i
< idepth
; i
++) {
2995 mono_class_init (eclass
->supertypes
[i
]);
2996 interfaces
[j
] = eclass
->supertypes
[i
];
3000 if (all_interfaces
) {
3001 for (i
= 0; i
< eclass
->interface_offsets_count
; i
++) {
3002 interfaces
[j
] = eclass
->interfaces_packed
[i
];
3006 for (i
= 0; i
< eclass
->interface_count
; i
++) {
3007 interfaces
[j
] = eclass
->interfaces
[i
];
3011 if (valuetype_types
[1]) {
3012 interfaces
[j
] = array_class_get_if_rank (valuetype_types
[1], original_rank
);
3017 /* instantiate the generic interfaces */
3018 for (i
= 0; i
< interface_count
; i
+= nifaces
) {
3019 MonoClass
*iface
= interfaces
[i
];
3021 interfaces
[i
+ 0] = inflate_class_one_arg (mono_defaults
.generic_ilist_class
, iface
);
3022 interfaces
[i
+ 1] = inflate_class_one_arg (generic_icollection_class
, iface
);
3024 if (eclass
->valuetype
) {
3025 interfaces
[i
+ 2] = inflate_class_one_arg (generic_ienumerable_class
, iface
);
3026 if (generic_ireadonlylist_class
) {
3027 interfaces
[i
+ 3] = inflate_class_one_arg (generic_ireadonlylist_class
, iface
);
3028 interfaces
[i
+ 4] = inflate_class_one_arg (generic_ireadonlycollection_class
, iface
);
3031 if (!generic_ireadonlylist_class
)
3032 interfaces
[i
+ 2] = inflate_class_one_arg (generic_ienumerable_class
, iface
);
3035 if (internal_enumerator
) {
3037 /* instantiate IEnumerator<iface> */
3038 for (i
= 0; i
< interface_count
; i
++) {
3039 interfaces
[i
] = inflate_class_one_arg (generic_ienumerator_class
, interfaces
[i
]);
3041 j
= interface_count
;
3042 if (!eclass_is_valuetype
) {
3043 if (MONO_CLASS_IS_INTERFACE (eclass
)) {
3044 interfaces
[j
] = inflate_class_one_arg (generic_ienumerator_class
, mono_defaults
.object_class
);
3047 for (i
= 0; i
< eclass
->idepth
; i
++) {
3048 interfaces
[j
] = inflate_class_one_arg (generic_ienumerator_class
, eclass
->supertypes
[i
]);
3052 for (i
= 0; i
< eclass
->interface_offsets_count
; i
++) {
3053 interfaces
[j
] = inflate_class_one_arg (generic_ienumerator_class
, eclass
->interfaces_packed
[i
]);
3057 interfaces
[j
++] = inflate_class_one_arg (generic_ienumerator_class
, array_class_get_if_rank (valuetype_types
[0], original_rank
));
3059 if (valuetype_types
[1])
3060 interfaces
[j
] = inflate_class_one_arg (generic_ienumerator_class
, array_class_get_if_rank (valuetype_types
[1], original_rank
));
3064 char *type_name
= mono_type_get_name_full (&class->byval_arg
, 0);
3065 for (i
= 0; i
< real_count
; ++i
) {
3066 char *name
= mono_type_get_name_full (&interfaces
[i
]->byval_arg
, 0);
3067 g_print ("%s implements %s\n", type_name
, name
);
3078 find_array_interface (MonoClass
*klass
, const char *name
)
3081 for (i
= 0; i
< klass
->interface_count
; ++i
) {
3082 if (strcmp (klass
->interfaces
[i
]->name
, name
) == 0)
3089 * Return the number of virtual methods.
3090 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3091 * Return -1 on failure.
3092 * FIXME It would be nice if this information could be cached somewhere.
3095 count_virtual_methods (MonoClass
*class)
3099 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3101 if (class->methods
|| !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3102 mono_class_setup_methods (class);
3103 if (class->exception_type
)
3106 for (i
= 0; i
< class->method
.count
; ++i
) {
3107 flags
= class->methods
[i
]->flags
;
3108 if (flags
& METHOD_ATTRIBUTE_VIRTUAL
)
3112 for (i
= 0; i
< class->method
.count
; ++i
) {
3113 flags
= mono_metadata_decode_table_row_col (class->image
, MONO_TABLE_METHOD
, class->method
.first
+ i
, MONO_METHOD_FLAGS
);
3115 if (flags
& METHOD_ATTRIBUTE_VIRTUAL
)
3123 find_interface (int num_ifaces
, MonoClass
**interfaces_full
, MonoClass
*ic
)
3131 m
= (l
+ num_ifaces
) / 2;
3132 if (interfaces_full
[m
] == ic
)
3134 if (l
== num_ifaces
)
3136 if (!interfaces_full
[m
] || interfaces_full
[m
]->interface_id
> ic
->interface_id
) {
3145 find_interface_offset (int num_ifaces
, MonoClass
**interfaces_full
, int *interface_offsets_full
, MonoClass
*ic
)
3147 int i
= find_interface (num_ifaces
, interfaces_full
, ic
);
3149 return interface_offsets_full
[i
];
3154 set_interface_and_offset (int num_ifaces
, MonoClass
**interfaces_full
, int *interface_offsets_full
, MonoClass
*ic
, int offset
, mono_bool force_set
)
3156 int i
= find_interface (num_ifaces
, interfaces_full
, ic
);
3160 interface_offsets_full
[i
] = offset
;
3163 for (i
= 0; i
< num_ifaces
; ++i
) {
3164 if (interfaces_full
[i
]) {
3166 if (interfaces_full
[i
]->interface_id
< ic
->interface_id
)
3169 while (end
< num_ifaces
&& interfaces_full
[end
]) end
++;
3170 memmove (interfaces_full
+ i
+ 1, interfaces_full
+ i
, sizeof (MonoClass
*) * (end
- i
));
3171 memmove (interface_offsets_full
+ i
+ 1, interface_offsets_full
+ i
, sizeof (int) * (end
- i
));
3173 interfaces_full
[i
] = ic
;
3174 interface_offsets_full
[i
] = offset
;
3180 #ifdef COMPRESSED_INTERFACE_BITMAP
3183 * Compressed interface bitmap design.
3185 * Interface bitmaps take a large amount of memory, because their size is
3186 * linear with the maximum interface id assigned in the process (each interface
3187 * is assigned a unique id as it is loaded). The number of interface classes
3188 * is high because of the many implicit interfaces implemented by arrays (we'll
3189 * need to lazy-load them in the future).
3190 * Most classes implement a very small number of interfaces, so the bitmap is
3191 * sparse. This bitmap needs to be checked by interface casts, so access to the
3192 * needed bit must be fast and doable with few jit instructions.
3194 * The current compression format is as follows:
3195 * *) it is a sequence of one or more two-byte elements
3196 * *) the first byte in the element is the count of empty bitmap bytes
3197 * at the current bitmap position
3198 * *) the second byte in the element is an actual bitmap byte at the current
3201 * As an example, the following compressed bitmap bytes:
3202 * 0x07 0x01 0x00 0x7
3203 * correspond to the following bitmap:
3204 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3206 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3207 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3208 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3212 * mono_compress_bitmap:
3213 * @dest: destination buffer
3214 * @bitmap: bitmap buffer
3215 * @size: size of @bitmap in bytes
3217 * This is a mono internal function.
3218 * The @bitmap data is compressed into a format that is small but
3219 * still searchable in few instructions by the JIT and runtime.
3220 * The compressed data is stored in the buffer pointed to by the
3221 * @dest array. Passing a #NULL value for @dest allows to just compute
3222 * the size of the buffer.
3223 * This compression algorithm assumes the bits set in the bitmap are
3224 * few and far between, like in interface bitmaps.
3225 * Returns: the size of the compressed bitmap in bytes.
3228 mono_compress_bitmap (uint8_t *dest
, const uint8_t *bitmap
, int size
)
3232 const uint8_t *end
= bitmap
+ size
;
3233 while (bitmap
< end
) {
3234 if (*bitmap
|| numz
== 255) {
3258 * mono_class_interface_match:
3259 * @bitmap: a compressed bitmap buffer
3260 * @id: the index to check in the bitmap
3262 * This is a mono internal function.
3263 * Checks if a bit is set in a compressed interface bitmap. @id must
3264 * be already checked for being smaller than the maximum id encoded in the
3267 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3271 mono_class_interface_match (const uint8_t *bitmap
, int id
)
3274 id
-= bitmap
[0] * 8;
3278 return bitmap
[1] & (1 << id
);
3287 * LOCKING: this is supposed to be called with the loader lock held.
3288 * Return -1 on failure and set exception_type
3291 setup_interface_offsets (MonoClass
*class, int cur_slot
, gboolean overwrite
)
3295 int i
, j
, max_iid
, num_ifaces
;
3296 MonoClass
**interfaces_full
= NULL
;
3297 int *interface_offsets_full
= NULL
;
3299 GPtrArray
**ifaces_array
= NULL
;
3300 int interface_offsets_count
;
3301 MonoClass
**array_interfaces
= NULL
;
3302 int num_array_interfaces
;
3303 int is_enumerator
= FALSE
;
3305 mono_class_setup_supertypes (class);
3307 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3308 * implicit interfaces have the property that they are assigned the same slot in the
3309 * vtables for compatible interfaces
3311 array_interfaces
= get_implicit_generic_array_interfaces (class, &num_array_interfaces
, &is_enumerator
);
3313 /* compute maximum number of slots and maximum interface id */
3315 num_ifaces
= num_array_interfaces
; /* this can include duplicated ones */
3316 ifaces_array
= g_new0 (GPtrArray
*, class->idepth
);
3317 for (j
= 0; j
< class->idepth
; j
++) {
3318 k
= class->supertypes
[j
];
3319 num_ifaces
+= k
->interface_count
;
3320 for (i
= 0; i
< k
->interface_count
; i
++) {
3321 ic
= k
->interfaces
[i
];
3324 mono_class_init (ic
);
3326 if (max_iid
< ic
->interface_id
)
3327 max_iid
= ic
->interface_id
;
3329 ifaces
= mono_class_get_implemented_interfaces (k
, &error
);
3330 if (!mono_error_ok (&error
)) {
3331 char *name
= mono_type_get_full_name (k
);
3332 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
)));
3334 mono_error_cleanup (&error
);
3339 num_ifaces
+= ifaces
->len
;
3340 for (i
= 0; i
< ifaces
->len
; ++i
) {
3341 ic
= g_ptr_array_index (ifaces
, i
);
3342 if (max_iid
< ic
->interface_id
)
3343 max_iid
= ic
->interface_id
;
3345 ifaces_array
[j
] = ifaces
;
3349 for (i
= 0; i
< num_array_interfaces
; ++i
) {
3350 ic
= array_interfaces
[i
];
3351 mono_class_init (ic
);
3352 if (max_iid
< ic
->interface_id
)
3353 max_iid
= ic
->interface_id
;
3356 if (MONO_CLASS_IS_INTERFACE (class)) {
3358 if (max_iid
< class->interface_id
)
3359 max_iid
= class->interface_id
;
3361 class->max_interface_id
= max_iid
;
3362 /* compute vtable offset for interfaces */
3363 interfaces_full
= g_malloc0 (sizeof (MonoClass
*) * num_ifaces
);
3364 interface_offsets_full
= g_malloc (sizeof (int) * num_ifaces
);
3366 for (i
= 0; i
< num_ifaces
; i
++) {
3367 interface_offsets_full
[i
] = -1;
3370 /* skip the current class */
3371 for (j
= 0; j
< class->idepth
- 1; j
++) {
3372 k
= class->supertypes
[j
];
3373 ifaces
= ifaces_array
[j
];
3376 for (i
= 0; i
< ifaces
->len
; ++i
) {
3378 ic
= g_ptr_array_index (ifaces
, i
);
3380 /*Force the sharing of interface offsets between parent and subtypes.*/
3381 io
= mono_class_interface_offset (k
, ic
);
3383 set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ic
, io
, TRUE
);
3388 g_assert (class == class->supertypes
[class->idepth
- 1]);
3389 ifaces
= ifaces_array
[class->idepth
- 1];
3391 for (i
= 0; i
< ifaces
->len
; ++i
) {
3393 ic
= g_ptr_array_index (ifaces
, i
);
3394 if (set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ic
, cur_slot
, FALSE
))
3396 count
= count_virtual_methods (ic
);
3398 char *name
= mono_type_get_full_name (ic
);
3399 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Error calculating interface offset of %s", name
));
3408 if (MONO_CLASS_IS_INTERFACE (class))
3409 set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, class, cur_slot
, TRUE
);
3411 if (num_array_interfaces
) {
3412 if (is_enumerator
) {
3413 int ienumerator_idx
= find_array_interface (class, "IEnumerator`1");
3414 int ienumerator_offset
= find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, class->interfaces
[ienumerator_idx
]);
3415 g_assert (ienumerator_offset
>= 0);
3416 for (i
= 0; i
< num_array_interfaces
; ++i
) {
3417 ic
= array_interfaces
[i
];
3418 if (strcmp (ic
->name
, "IEnumerator`1") == 0)
3419 set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ic
, ienumerator_offset
, TRUE
);
3421 g_assert_not_reached ();
3422 /*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);*/
3425 int ilist_offset
, icollection_offset
, ienumerable_offset
, ireadonlylist_offset
, ireadonlycollection_offset
;
3426 int ilist_iface_idx
= find_array_interface (class, "IList`1");
3427 MonoClass
* ilist_class
= class->interfaces
[ilist_iface_idx
];
3428 int ireadonlylist_iface_idx
= find_array_interface (class, "IReadOnlyList`1");
3429 MonoClass
* ireadonlylist_class
= ireadonlylist_iface_idx
!= -1 ? class->interfaces
[ireadonlylist_iface_idx
] : NULL
;
3430 int icollection_iface_idx
= find_array_interface (ilist_class
, "ICollection`1");
3431 int ienumerable_iface_idx
= find_array_interface (ilist_class
, "IEnumerable`1");
3432 int ireadonlycollection_iface_idx
= ireadonlylist_iface_idx
!= -1 ? find_array_interface (ireadonlylist_class
, "IReadOnlyCollection`1") : -1;
3433 ilist_offset
= find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, class->interfaces
[ilist_iface_idx
]);
3434 icollection_offset
= find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ilist_class
->interfaces
[icollection_iface_idx
]);
3435 ienumerable_offset
= find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ilist_class
->interfaces
[ienumerable_iface_idx
]);
3436 ireadonlylist_offset
= ireadonlylist_iface_idx
!= -1 ? find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, class->interfaces
[ireadonlylist_iface_idx
]) : -1;
3437 ireadonlycollection_offset
= ireadonlycollection_iface_idx
!= -1 ? find_interface_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ireadonlylist_class
->interfaces
[ireadonlycollection_iface_idx
]) : -1;
3438 g_assert (ilist_offset
>= 0 && icollection_offset
>= 0 && ienumerable_offset
>= 0);
3439 for (i
= 0; i
< num_array_interfaces
; ++i
) {
3441 ic
= array_interfaces
[i
];
3442 if (ic
->generic_class
->container_class
== mono_defaults
.generic_ilist_class
)
3443 offset
= ilist_offset
;
3444 else if (strcmp (ic
->name
, "ICollection`1") == 0)
3445 offset
= icollection_offset
;
3446 else if (strcmp (ic
->name
, "IEnumerable`1") == 0)
3447 offset
= ienumerable_offset
;
3448 else if (strcmp (ic
->name
, "IReadOnlyList`1") == 0)
3449 offset
= ireadonlylist_offset
;
3450 else if (strcmp (ic
->name
, "IReadOnlyCollection`1") == 0)
3451 offset
= ireadonlycollection_offset
;
3453 g_assert_not_reached ();
3454 set_interface_and_offset (num_ifaces
, interfaces_full
, interface_offsets_full
, ic
, offset
, TRUE
);
3455 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3460 for (interface_offsets_count
= 0, i
= 0; i
< num_ifaces
; i
++) {
3461 if (interface_offsets_full
[i
] != -1) {
3462 interface_offsets_count
++;
3467 * We might get called multiple times:
3468 * - mono_class_init ()
3469 * - mono_class_setup_vtable ().
3470 * - mono_class_setup_interface_offsets ().
3471 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3472 * means we have to overwrite those when called from other places (#4440).
3474 if (class->interfaces_packed
&& !overwrite
) {
3475 g_assert (class->interface_offsets_count
== interface_offsets_count
);
3479 class->interface_offsets_count
= interface_offsets_count
;
3480 class->interfaces_packed
= mono_class_alloc (class, sizeof (MonoClass
*) * interface_offsets_count
);
3481 class->interface_offsets_packed
= mono_class_alloc (class, sizeof (guint16
) * interface_offsets_count
);
3482 bsize
= (sizeof (guint8
) * ((max_iid
+ 1) >> 3)) + (((max_iid
+ 1) & 7)? 1 :0);
3483 #ifdef COMPRESSED_INTERFACE_BITMAP
3484 bitmap
= g_malloc0 (bsize
);
3486 bitmap
= mono_class_alloc0 (class, bsize
);
3488 for (i
= 0; i
< interface_offsets_count
; i
++) {
3489 int id
= interfaces_full
[i
]->interface_id
;
3490 bitmap
[id
>> 3] |= (1 << (id
& 7));
3491 class->interfaces_packed
[i
] = interfaces_full
[i
];
3492 class->interface_offsets_packed
[i
] = interface_offsets_full
[i
];
3493 /*if (num_array_interfaces)
3494 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]);*/
3496 #ifdef COMPRESSED_INTERFACE_BITMAP
3497 i
= mono_compress_bitmap (NULL
, bitmap
, bsize
);
3498 class->interface_bitmap
= mono_class_alloc0 (class, i
);
3499 mono_compress_bitmap (class->interface_bitmap
, bitmap
, bsize
);
3502 class->interface_bitmap
= bitmap
;
3507 g_free (interfaces_full
);
3508 g_free (interface_offsets_full
);
3509 g_free (array_interfaces
);
3510 for (i
= 0; i
< class->idepth
; i
++) {
3511 ifaces
= ifaces_array
[i
];
3513 g_ptr_array_free (ifaces
, TRUE
);
3515 g_free (ifaces_array
);
3517 //printf ("JUST DONE: ");
3518 //print_implemented_interfaces (class);
3524 * Setup interface offsets for interfaces.
3526 * - class->max_interface_id
3527 * - class->interface_offsets_count
3528 * - class->interfaces_packed
3529 * - class->interface_offsets_packed
3530 * - class->interface_bitmap
3532 * This function can fail @class.
3535 mono_class_setup_interface_offsets (MonoClass
*class)
3537 mono_loader_lock ();
3539 setup_interface_offsets (class, 0, FALSE
);
3541 mono_loader_unlock ();
3544 /*Checks if @klass has @parent as one of it's parents type gtd
3548 * Bar<T> : Foo<Bar<Bar<T>>>
3552 mono_class_has_gtd_parent (MonoClass
*klass
, MonoClass
*parent
)
3554 klass
= mono_class_get_generic_type_definition (klass
);
3555 parent
= mono_class_get_generic_type_definition (parent
);
3556 mono_class_setup_supertypes (klass
);
3557 mono_class_setup_supertypes (parent
);
3559 return klass
->idepth
>= parent
->idepth
&&
3560 mono_class_get_generic_type_definition (klass
->supertypes
[parent
->idepth
- 1]) == parent
;
3564 mono_class_check_vtable_constraints (MonoClass
*class, GList
*in_setup
)
3566 MonoGenericInst
*ginst
;
3568 if (!class->generic_class
) {
3569 mono_class_setup_vtable_full (class, in_setup
);
3570 return class->exception_type
== 0;
3573 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup
);
3574 if (class->generic_class
->container_class
->exception_type
) {
3575 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Failed to load generic definition vtable"));
3579 ginst
= class->generic_class
->context
.class_inst
;
3580 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
3582 if (ginst
->type_argv
[i
]->type
!= MONO_TYPE_GENERICINST
)
3584 arg
= mono_class_from_mono_type (ginst
->type_argv
[i
]);
3585 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3586 if (mono_class_has_gtd_parent (class, arg
) || mono_class_has_gtd_parent (arg
, class))
3588 if (!mono_class_check_vtable_constraints (arg
, in_setup
)) {
3589 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Failed to load generic parameter %d", i
));
3597 * mono_class_setup_vtable:
3599 * Creates the generic vtable of CLASS.
3600 * Initializes the following fields in MonoClass:
3603 * Plus all the fields initialized by setup_interface_offsets ().
3604 * If there is an error during vtable construction, class->exception_type is set.
3606 * LOCKING: Acquires the loader lock.
3609 mono_class_setup_vtable (MonoClass
*class)
3611 mono_class_setup_vtable_full (class, NULL
);
3615 mono_class_setup_vtable_full (MonoClass
*class, GList
*in_setup
)
3617 MonoMethod
**overrides
;
3618 MonoGenericContext
*context
;
3626 if (MONO_CLASS_IS_INTERFACE (class)) {
3627 /* This sets method->slot for all methods if this is an interface */
3628 mono_class_setup_methods (class);
3632 if (class->exception_type
)
3635 if (g_list_find (in_setup
, class))
3638 mono_loader_lock ();
3640 if (class->vtable
) {
3641 mono_loader_unlock ();
3645 mono_stats
.generic_vtable_count
++;
3646 in_setup
= g_list_prepend (in_setup
, class);
3648 if (class->generic_class
) {
3649 if (!mono_class_check_vtable_constraints (class, in_setup
)) {
3650 mono_loader_unlock ();
3651 g_list_remove (in_setup
, class);
3655 context
= mono_class_get_context (class);
3656 type_token
= class->generic_class
->container_class
->type_token
;
3658 context
= (MonoGenericContext
*) class->generic_container
;
3659 type_token
= class->type_token
;
3662 if (class->image
->dynamic
) {
3663 /* Generic instances can have zero method overrides without causing any harm.
3664 * This is true since we don't do layout all over again for them, we simply inflate
3665 * the layout of the parent.
3667 mono_reflection_get_dynamic_overrides (class, &overrides
, &onum
);
3669 /* The following call fails if there are missing methods in the type */
3670 /* FIXME it's probably a good idea to avoid this for generic instances. */
3671 ok
= mono_class_get_overrides_full (class->image
, type_token
, &overrides
, &onum
, context
);
3675 mono_class_setup_vtable_general (class, overrides
, onum
, in_setup
);
3677 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not load list of method overrides"));
3681 mono_loader_unlock ();
3682 g_list_remove (in_setup
, class);
3687 #define DEBUG_INTERFACE_VTABLE_CODE 0
3688 #define TRACE_INTERFACE_VTABLE_CODE 0
3689 #define VERIFY_INTERFACE_VTABLE_CODE 0
3690 #define VTABLE_SELECTOR (1)
3692 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3693 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3694 if (!(VTABLE_SELECTOR)) break; \
3698 #define DEBUG_INTERFACE_VTABLE(stmt)
3701 #if TRACE_INTERFACE_VTABLE_CODE
3702 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3703 if (!(VTABLE_SELECTOR)) break; \
3707 #define TRACE_INTERFACE_VTABLE(stmt)
3710 #if VERIFY_INTERFACE_VTABLE_CODE
3711 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3712 if (!(VTABLE_SELECTOR)) break; \
3716 #define VERIFY_INTERFACE_VTABLE(stmt)
3720 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3722 mono_signature_get_full_desc (MonoMethodSignature
*sig
, gboolean include_namespace
)
3726 GString
*res
= g_string_new ("");
3728 g_string_append_c (res
, '(');
3729 for (i
= 0; i
< sig
->param_count
; ++i
) {
3731 g_string_append_c (res
, ',');
3732 mono_type_get_desc (res
, sig
->params
[i
], include_namespace
);
3734 g_string_append (res
, ")=>");
3735 if (sig
->ret
!= NULL
) {
3736 mono_type_get_desc (res
, sig
->ret
, include_namespace
);
3738 g_string_append (res
, "NULL");
3741 g_string_free (res
, FALSE
);
3745 print_method_signatures (MonoMethod
*im
, MonoMethod
*cm
) {
3746 char *im_sig
= mono_signature_get_full_desc (mono_method_signature (im
), TRUE
);
3747 char *cm_sig
= mono_signature_get_full_desc (mono_method_signature (cm
), TRUE
);
3748 printf ("(IM \"%s\", CM \"%s\")", im_sig
, cm_sig
);
3756 is_wcf_hack_disabled (void)
3758 static gboolean disabled
;
3759 static gboolean inited
= FALSE
;
3761 disabled
= g_getenv ("MONO_DISABLE_WCF_HACK") != NULL
;
3768 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
) {
3769 MonoMethodSignature
*cmsig
, *imsig
;
3770 if (strcmp (im
->name
, cm
->name
) == 0) {
3771 if (! (cm
->flags
& METHOD_ATTRIBUTE_PUBLIC
)) {
3772 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3775 if (! slot_is_empty
) {
3776 if (require_newslot
) {
3777 if (! interface_is_explicitly_implemented_by_class
) {
3778 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3781 if (! (cm
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)) {
3782 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3786 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3789 cmsig
= mono_method_signature (cm
);
3790 imsig
= mono_method_signature (im
);
3791 if (!cmsig
|| !imsig
) {
3792 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not resolve the signature of a virtual method"));
3796 if (! mono_metadata_signature_equal (cmsig
, imsig
)) {
3797 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3798 TRACE_INTERFACE_VTABLE (print_method_signatures (im
, cm
));
3799 TRACE_INTERFACE_VTABLE (printf ("]"));
3802 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3803 /* CAS - SecurityAction.InheritanceDemand on interface */
3804 if (security_enabled
&& (im
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
)) {
3805 mono_secman_inheritancedemand_method (cm
, im
);
3808 if (mono_security_core_clr_enabled ())
3809 mono_security_core_clr_check_override (class, cm
, im
);
3811 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3812 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm
, im
, NULL
)) {
3813 char *body_name
= mono_method_full_name (cm
, TRUE
);
3814 char *decl_name
= mono_method_full_name (im
, TRUE
);
3815 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
));
3823 MonoClass
*ic
= im
->klass
;
3824 const char *ic_name_space
= ic
->name_space
;
3825 const char *ic_name
= ic
->name
;
3828 if (! require_newslot
) {
3829 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3832 if (cm
->klass
->rank
== 0) {
3833 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3836 cmsig
= mono_method_signature (cm
);
3837 imsig
= mono_method_signature (im
);
3838 if (!cmsig
|| !imsig
) {
3839 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not resolve the signature of a virtual method"));
3843 if (! mono_metadata_signature_equal (cmsig
, imsig
)) {
3844 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3845 TRACE_INTERFACE_VTABLE (print_method_signatures (im
, cm
));
3846 TRACE_INTERFACE_VTABLE (printf ("]"));
3849 if (mono_class_get_image (ic
) != mono_defaults
.corlib
) {
3850 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3853 if ((ic_name_space
== NULL
) || (strcmp (ic_name_space
, "System.Collections.Generic") != 0)) {
3854 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3857 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))) {
3858 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3862 subname
= strstr (cm
->name
, ic_name_space
);
3863 if (subname
!= cm
->name
) {
3864 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3867 subname
+= strlen (ic_name_space
);
3868 if (subname
[0] != '.') {
3869 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3873 if (strstr (subname
, ic_name
) != subname
) {
3874 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3877 subname
+= strlen (ic_name
);
3878 if (subname
[0] != '.') {
3879 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3883 if (strcmp (subname
, im
->name
) != 0) {
3884 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3888 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3889 /* CAS - SecurityAction.InheritanceDemand on interface */
3890 if (security_enabled
&& (im
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
)) {
3891 mono_secman_inheritancedemand_method (cm
, im
);
3894 if (mono_security_core_clr_enabled ())
3895 mono_security_core_clr_check_override (class, cm
, im
);
3897 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3898 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm
, im
, NULL
)) {
3899 char *body_name
= mono_method_full_name (cm
, TRUE
);
3900 char *decl_name
= mono_method_full_name (im
, TRUE
);
3901 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
));
3911 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3913 foreach_override (gpointer key
, gpointer value
, gpointer user_data
) {
3914 MonoMethod
*method
= key
;
3915 MonoMethod
*override
= value
;
3916 MonoClass
*method_class
= mono_method_get_class (method
);
3917 MonoClass
*override_class
= mono_method_get_class (override
);
3919 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3920 mono_class_get_namespace (method_class
), mono_class_get_name (method_class
), mono_method_get_name (method
),
3921 mono_class_get_namespace (override_class
), mono_class_get_name (override_class
), mono_method_get_name (override
));
3924 print_overrides (GHashTable
*override_map
, const char *message
) {
3926 printf ("Override map \"%s\" START:\n", message
);
3927 g_hash_table_foreach (override_map
, foreach_override
, NULL
);
3928 printf ("Override map \"%s\" END.\n", message
);
3930 printf ("Override map \"%s\" EMPTY.\n", message
);
3934 print_vtable_full (MonoClass
*class, MonoMethod
** vtable
, int size
, int first_non_interface_slot
, const char *message
, gboolean print_interfaces
) {
3935 char *full_name
= mono_type_full_name (&class->byval_arg
);
3939 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name
, message
, size
);
3941 if (print_interfaces
) {
3942 print_implemented_interfaces (class);
3943 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name
, size
);
3946 if (class->parent
) {
3947 parent_size
= class->parent
->vtable_size
;
3951 for (i
= 0; i
< size
; ++i
) {
3952 MonoMethod
*cm
= vtable
[i
];
3953 char *cm_name
= cm
? mono_method_full_name (cm
, TRUE
) : g_strdup ("nil");
3954 char newness
= (i
< parent_size
) ? 'O' : ((i
< first_non_interface_slot
) ? 'I' : 'N');
3956 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness
, i
, cm
? cm
->slot
: - 1, cm_name
, cm
);
3964 #if VERIFY_INTERFACE_VTABLE_CODE
3966 mono_method_try_get_vtable_index (MonoMethod
*method
)
3968 if (method
->is_inflated
&& (method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
3969 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
3970 if (imethod
->declaring
->is_generic
)
3971 return imethod
->declaring
->slot
;
3973 return method
->slot
;
3977 mono_class_verify_vtable (MonoClass
*class)
3980 char *full_name
= mono_type_full_name (&class->byval_arg
);
3982 printf ("*** Verifying VTable of class '%s' \n", full_name
);
3986 if (!class->methods
)
3989 for (i
= 0; i
< class->method
.count
; ++i
) {
3990 MonoMethod
*cm
= class->methods
[i
];
3993 if (!(cm
->flags
& METHOD_ATTRIBUTE_VIRTUAL
))
3997 full_name
= mono_method_full_name (cm
, TRUE
);
3999 slot
= mono_method_try_get_vtable_index (cm
);
4001 if (slot
>= class->vtable_size
) {
4002 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name
, slot
, class->vtable_size
);
4006 if (slot
>= 0 && class->vtable
[slot
] != cm
&& (class->vtable
[slot
])) {
4007 char *other_name
= class->vtable
[slot
] ? mono_method_full_name (class->vtable
[slot
], TRUE
) : g_strdup ("[null value]");
4008 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name
, slot
, other_name
);
4009 g_free (other_name
);
4012 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name
);
4019 print_unimplemented_interface_method_info (MonoClass
*class, MonoClass
*ic
, MonoMethod
*im
, int im_slot
, MonoMethod
**overrides
, int onum
) {
4021 char *method_signature
;
4024 for (index
= 0; index
< onum
; ++index
) {
4025 mono_trace_warning (MONO_TRACE_TYPE
, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot
, overrides
[index
*2+1]->name
,
4026 overrides
[index
*2+1]->slot
, overrides
[index
*2]->name
, overrides
[index
*2]->slot
);
4028 method_signature
= mono_signature_get_desc (mono_method_signature (im
), FALSE
);
4029 type_name
= mono_type_full_name (&class->byval_arg
);
4030 mono_trace_warning (MONO_TRACE_TYPE
, "no implementation for interface method %s::%s(%s) in class %s\n",
4031 mono_type_get_name (&ic
->byval_arg
), im
->name
, method_signature
, type_name
);
4032 g_free (method_signature
);
4034 mono_class_setup_methods (class);
4035 if (class->exception_type
) {
4036 char *name
= mono_type_get_full_name (class);
4037 mono_trace_warning (MONO_TRACE_TYPE
, "CLASS %s failed to resolve methods\n", name
);
4041 for (index
= 0; index
< class->method
.count
; ++index
) {
4042 MonoMethod
*cm
= class->methods
[index
];
4043 method_signature
= mono_signature_get_desc (mono_method_signature (cm
), TRUE
);
4045 mono_trace_warning (MONO_TRACE_TYPE
, "METHOD %s(%s)\n", cm
->name
, method_signature
);
4046 g_free (method_signature
);
4051 mono_method_get_method_definition (MonoMethod
*method
)
4053 while (method
->is_inflated
)
4054 method
= ((MonoMethodInflated
*)method
)->declaring
;
4059 verify_class_overrides (MonoClass
*class, MonoMethod
**overrides
, int onum
)
4063 for (i
= 0; i
< onum
; ++i
) {
4064 MonoMethod
*decl
= overrides
[i
* 2];
4065 MonoMethod
*body
= overrides
[i
* 2 + 1];
4067 if (mono_class_get_generic_type_definition (body
->klass
) != mono_class_get_generic_type_definition (class)) {
4068 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Method belongs to a different class than the declared one"));
4072 if (!(body
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) || (body
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
4073 if (body
->flags
& METHOD_ATTRIBUTE_STATIC
)
4074 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Method must not be static to override a base type"));
4076 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Method must be virtual to override a base type"));
4080 if (!(decl
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) || (decl
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
4081 if (body
->flags
& METHOD_ATTRIBUTE_STATIC
)
4082 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Cannot override a static method in a base type"));
4084 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Cannot override a non virtual method in a base type"));
4088 if (!mono_class_is_assignable_from_slow (decl
->klass
, class)) {
4089 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4093 body
= mono_method_get_method_definition (body
);
4094 decl
= mono_method_get_method_definition (decl
);
4096 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body
, decl
, NULL
)) {
4097 char *body_name
= mono_method_full_name (body
, TRUE
);
4098 char *decl_name
= mono_method_full_name (decl
, TRUE
);
4099 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
));
4109 mono_class_need_stelemref_method (MonoClass
*class)
4111 return class->rank
== 1 && MONO_TYPE_IS_REFERENCE (&class->element_class
->byval_arg
);
4115 * LOCKING: this is supposed to be called with the loader lock held.
4118 mono_class_setup_vtable_general (MonoClass
*class, MonoMethod
**overrides
, int onum
, GList
*in_setup
)
4122 MonoMethod
**vtable
;
4123 int i
, max_vtsize
= 0, max_iid
, cur_slot
= 0;
4124 GPtrArray
*ifaces
= NULL
;
4125 GHashTable
*override_map
= NULL
;
4126 gboolean security_enabled
= mono_security_enabled ();
4128 gpointer class_iter
;
4129 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4130 int first_non_interface_slot
;
4132 GSList
*virt_methods
= NULL
, *l
;
4133 int stelemref_slot
= 0;
4138 if (overrides
&& !verify_class_overrides (class, overrides
, onum
))
4141 ifaces
= mono_class_get_implemented_interfaces (class, &error
);
4142 if (!mono_error_ok (&error
)) {
4143 char *name
= mono_type_get_full_name (class);
4144 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
)));
4146 mono_error_cleanup (&error
);
4148 } else if (ifaces
) {
4149 for (i
= 0; i
< ifaces
->len
; i
++) {
4150 MonoClass
*ic
= g_ptr_array_index (ifaces
, i
);
4151 max_vtsize
+= ic
->method
.count
;
4153 g_ptr_array_free (ifaces
, TRUE
);
4157 if (class->parent
) {
4158 mono_class_init (class->parent
);
4159 mono_class_setup_vtable_full (class->parent
, in_setup
);
4161 if (class->parent
->exception_type
) {
4162 char *name
= mono_type_get_full_name (class->parent
);
4163 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Parent %s failed to load", name
));
4168 max_vtsize
+= class->parent
->vtable_size
;
4169 cur_slot
= class->parent
->vtable_size
;
4172 max_vtsize
+= class->method
.count
;
4174 /*Array have a slot for stelemref*/
4175 if (mono_class_need_stelemref_method (class)) {
4176 stelemref_slot
= cur_slot
;
4181 vtable
= alloca (sizeof (gpointer
) * max_vtsize
);
4182 memset (vtable
, 0, sizeof (gpointer
) * max_vtsize
);
4184 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4186 cur_slot
= setup_interface_offsets (class, cur_slot
, TRUE
);
4187 if (cur_slot
== -1) /*setup_interface_offsets fails the type.*/
4190 max_iid
= class->max_interface_id
;
4191 DEBUG_INTERFACE_VTABLE (first_non_interface_slot
= cur_slot
);
4193 /* Optimized version for generic instances */
4194 if (class->generic_class
) {
4196 MonoClass
*gklass
= class->generic_class
->container_class
;
4199 mono_class_setup_vtable_full (gklass
, in_setup
);
4200 if (gklass
->exception_type
!= MONO_EXCEPTION_NONE
) {
4201 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
4205 tmp
= mono_class_alloc0 (class, sizeof (gpointer
) * gklass
->vtable_size
);
4206 class->vtable_size
= gklass
->vtable_size
;
4207 for (i
= 0; i
< gklass
->vtable_size
; ++i
)
4208 if (gklass
->vtable
[i
]) {
4209 MonoMethod
*inflated
= mono_class_inflate_generic_method_full_checked (gklass
->vtable
[i
], class, mono_class_get_context (class), &error
);
4210 if (!mono_error_ok (&error
)) {
4211 char *err_msg
= g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error
));
4212 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
4214 mono_error_cleanup (&error
);
4218 tmp
[i
]->slot
= gklass
->vtable
[i
]->slot
;
4220 mono_memory_barrier ();
4221 class->vtable
= tmp
;
4223 /* Have to set method->slot for abstract virtual methods */
4224 if (class->methods
&& gklass
->methods
) {
4225 for (i
= 0; i
< class->method
.count
; ++i
)
4226 if (class->methods
[i
]->slot
== -1)
4227 class->methods
[i
]->slot
= gklass
->methods
[i
]->slot
;
4233 if (class->parent
&& class->parent
->vtable_size
) {
4234 MonoClass
*parent
= class->parent
;
4237 memcpy (vtable
, parent
->vtable
, sizeof (gpointer
) * parent
->vtable_size
);
4239 // Also inherit parent interface vtables, just as a starting point.
4240 // This is needed otherwise bug-77127.exe fails when the property methods
4241 // have different names in the iterface and the class, because for child
4242 // classes the ".override" information is not used anymore.
4243 for (i
= 0; i
< parent
->interface_offsets_count
; i
++) {
4244 MonoClass
*parent_interface
= parent
->interfaces_packed
[i
];
4245 int interface_offset
= mono_class_interface_offset (class, parent_interface
);
4246 /*FIXME this is now dead code as this condition will never hold true.
4247 Since interface offsets are inherited then the offset of an interface implemented
4248 by a parent will never be the out of it's vtable boundary.
4250 if (interface_offset
>= parent
->vtable_size
) {
4251 int parent_interface_offset
= mono_class_interface_offset (parent
, parent_interface
);
4254 mono_class_setup_methods (parent_interface
); /*FIXME Just kill this whole chunk of dead code*/
4255 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface
->name_space
, parent_interface
->name
));
4256 for (j
= 0; j
< parent_interface
->method
.count
&& !class->exception_type
; j
++) {
4257 vtable
[interface_offset
+ j
] = parent
->vtable
[parent_interface_offset
+ j
];
4258 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4259 parent_interface_offset
+ j
, parent_interface_offset
, j
,
4260 interface_offset
+ j
, interface_offset
, j
));
4267 /*Array have a slot for stelemref*/
4268 if (mono_class_need_stelemref_method (class)) {
4269 MonoMethod
*method
= mono_marshal_get_virtual_stelemref (class);
4271 method
->slot
= stelemref_slot
;
4273 g_assert (method
->slot
== stelemref_slot
);
4275 vtable
[stelemref_slot
] = method
;
4278 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable
, cur_slot
, first_non_interface_slot
, "AFTER INHERITING PARENT VTABLE", TRUE
));
4279 /* override interface methods */
4280 for (i
= 0; i
< onum
; i
++) {
4281 MonoMethod
*decl
= overrides
[i
*2];
4282 if (MONO_CLASS_IS_INTERFACE (decl
->klass
)) {
4284 dslot
= mono_method_get_vtable_slot (decl
);
4286 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
4290 dslot
+= mono_class_interface_offset (class, decl
->klass
);
4291 vtable
[dslot
] = overrides
[i
*2 + 1];
4292 vtable
[dslot
]->slot
= dslot
;
4294 override_map
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
4296 g_hash_table_insert (override_map
, overrides
[i
* 2], overrides
[i
* 2 + 1]);
4298 if (mono_security_core_clr_enabled ())
4299 mono_security_core_clr_check_override (class, vtable
[dslot
], decl
);
4302 TRACE_INTERFACE_VTABLE (print_overrides (override_map
, "AFTER OVERRIDING INTERFACE METHODS"));
4303 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable
, cur_slot
, first_non_interface_slot
, "AFTER OVERRIDING INTERFACE METHODS", FALSE
));
4306 * Create a list of virtual methods to avoid calling
4307 * mono_class_get_virtual_methods () which is slow because of the metadata
4311 gpointer iter
= NULL
;
4314 virt_methods
= NULL
;
4315 while ((cm
= mono_class_get_virtual_methods (class, &iter
))) {
4316 virt_methods
= g_slist_prepend (virt_methods
, cm
);
4318 if (class->exception_type
)
4322 // Loop on all implemented interfaces...
4323 for (i
= 0; i
< class->interface_offsets_count
; i
++) {
4324 MonoClass
*parent
= class->parent
;
4326 gboolean interface_is_explicitly_implemented_by_class
;
4329 ic
= class->interfaces_packed
[i
];
4330 ic_offset
= mono_class_interface_offset (class, ic
);
4332 mono_class_setup_methods (ic
);
4333 if (ic
->exception_type
)
4336 // Check if this interface is explicitly implemented (instead of just inherited)
4337 if (parent
!= NULL
) {
4338 int implemented_interfaces_index
;
4339 interface_is_explicitly_implemented_by_class
= FALSE
;
4340 for (implemented_interfaces_index
= 0; implemented_interfaces_index
< class->interface_count
; implemented_interfaces_index
++) {
4341 if (ic
== class->interfaces
[implemented_interfaces_index
]) {
4342 interface_is_explicitly_implemented_by_class
= TRUE
;
4347 interface_is_explicitly_implemented_by_class
= TRUE
;
4350 // Loop on all interface methods...
4351 for (im_index
= 0; im_index
< ic
->method
.count
; im_index
++) {
4352 MonoMethod
*im
= ic
->methods
[im_index
];
4353 int im_slot
= ic_offset
+ im
->slot
;
4354 MonoMethod
*override_im
= (override_map
!= NULL
) ? g_hash_table_lookup (override_map
, im
) : NULL
;
4356 if (im
->flags
& METHOD_ATTRIBUTE_STATIC
)
4359 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im
,1)));
4361 // If there is an explicit implementation, just use it right away,
4362 // otherwise look for a matching method
4363 if (override_im
== NULL
) {
4368 // First look for a suitable method among the class methods
4370 for (l
= virt_methods
; l
; l
= l
->next
) {
4372 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
)));
4373 if (check_interface_method_override (class, im
, cm
, TRUE
, interface_is_explicitly_implemented_by_class
, (vtable
[im_slot
] == NULL
), security_enabled
)) {
4374 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4375 vtable
[im_slot
] = cm
;
4376 /* Why do we need this? */
4381 TRACE_INTERFACE_VTABLE (printf ("\n"));
4382 if (class->exception_type
) /*Might be set by check_interface_method_override*/
4386 // If the slot is still empty, look in all the inherited virtual methods...
4387 if ((vtable
[im_slot
] == NULL
) && class->parent
!= NULL
) {
4388 MonoClass
*parent
= class->parent
;
4389 // Reverse order, so that last added methods are preferred
4390 for (cm_index
= parent
->vtable_size
- 1; cm_index
>= 0; cm_index
--) {
4391 MonoMethod
*cm
= parent
->vtable
[cm_index
];
4393 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
));
4394 if ((cm
!= NULL
) && check_interface_method_override (class, im
, cm
, FALSE
, FALSE
, TRUE
, security_enabled
)) {
4395 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4396 vtable
[im_slot
] = cm
;
4397 /* Why do we need this? */
4403 if (class->exception_type
) /*Might be set by check_interface_method_override*/
4405 TRACE_INTERFACE_VTABLE ((cm
!= NULL
) && printf ("\n"));
4409 g_assert (vtable
[im_slot
] == override_im
);
4414 // If the class is not abstract, check that all its interface slots are full.
4415 // The check is done here and not directly at the end of the loop above because
4416 // it can happen (for injected generic array interfaces) that the same slot is
4417 // processed multiple times (those interfaces have overlapping slots), and it
4418 // will not always be the first pass the one that fills the slot.
4419 if (! (class->flags
& TYPE_ATTRIBUTE_ABSTRACT
)) {
4420 for (i
= 0; i
< class->interface_offsets_count
; i
++) {
4424 ic
= class->interfaces_packed
[i
];
4425 ic_offset
= mono_class_interface_offset (class, ic
);
4427 for (im_index
= 0; im_index
< ic
->method
.count
; im_index
++) {
4428 MonoMethod
*im
= ic
->methods
[im_index
];
4429 int im_slot
= ic_offset
+ im
->slot
;
4431 if (im
->flags
& METHOD_ATTRIBUTE_STATIC
)
4434 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4435 im_slot
, ic
->name_space
, ic
->name
, im
->name
, (vtable
[im_slot
] == NULL
)));
4436 if (vtable
[im_slot
] == NULL
) {
4437 print_unimplemented_interface_method_info (class, ic
, im
, im_slot
, overrides
, onum
);
4444 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable
, cur_slot
, first_non_interface_slot
, "AFTER SETTING UP INTERFACE METHODS", FALSE
));
4446 for (l
= virt_methods
; l
; l
= l
->next
) {
4449 * If the method is REUSE_SLOT, we must check in the
4450 * base class for a method to override.
4452 if (!(cm
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)) {
4454 for (k
= class->parent
; k
; k
= k
->parent
) {
4459 while ((m1
= mono_class_get_virtual_methods (k
, &k_iter
))) {
4460 MonoMethodSignature
*cmsig
, *m1sig
;
4462 cmsig
= mono_method_signature (cm
);
4463 m1sig
= mono_method_signature (m1
);
4465 if (!cmsig
|| !m1sig
) {
4466 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
4470 if (!strcmp(cm
->name
, m1
->name
) &&
4471 mono_metadata_signature_equal (cmsig
, m1sig
)) {
4473 /* CAS - SecurityAction.InheritanceDemand */
4474 if (security_enabled
&& (m1
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
)) {
4475 mono_secman_inheritancedemand_method (cm
, m1
);
4478 if (mono_security_core_clr_enabled ())
4479 mono_security_core_clr_check_override (class, cm
, m1
);
4481 slot
= mono_method_get_vtable_slot (m1
);
4485 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm
, m1
, NULL
)) {
4486 char *body_name
= mono_method_full_name (cm
, TRUE
);
4487 char *decl_name
= mono_method_full_name (m1
, TRUE
);
4488 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
));
4494 g_assert (cm
->slot
< max_vtsize
);
4496 override_map
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
4497 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4498 mono_method_full_name (m1
, 1), m1
,
4499 mono_method_full_name (cm
, 1), cm
));
4500 g_hash_table_insert (override_map
, m1
, cm
);
4504 if (k
->exception_type
)
4514 /*Non final newslot methods must be given a non-interface vtable slot*/
4515 if ((cm
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
) && !(cm
->flags
& METHOD_ATTRIBUTE_FINAL
) && cm
->slot
>= 0)
4519 cm
->slot
= cur_slot
++;
4521 if (!(cm
->flags
& METHOD_ATTRIBUTE_ABSTRACT
))
4522 vtable
[cm
->slot
] = cm
;
4525 /* override non interface methods */
4526 for (i
= 0; i
< onum
; i
++) {
4527 MonoMethod
*decl
= overrides
[i
*2];
4528 if (!MONO_CLASS_IS_INTERFACE (decl
->klass
)) {
4529 g_assert (decl
->slot
!= -1);
4530 vtable
[decl
->slot
] = overrides
[i
*2 + 1];
4531 overrides
[i
* 2 + 1]->slot
= decl
->slot
;
4533 override_map
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
4534 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4535 mono_method_full_name (decl
, 1), decl
,
4536 mono_method_full_name (overrides
[i
* 2 + 1], 1), overrides
[i
* 2 + 1]));
4537 g_hash_table_insert (override_map
, decl
, overrides
[i
* 2 + 1]);
4539 if (mono_security_core_clr_enabled ())
4540 mono_security_core_clr_check_override (class, vtable
[decl
->slot
], decl
);
4545 * If a method occupies more than one place in the vtable, and it is
4546 * overriden, then change the other occurances too.
4551 for (i
= 0; i
< max_vtsize
; ++i
)
4553 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i
, mono_method_full_name (vtable
[i
], 1), vtable
[i
]));
4555 cm
= g_hash_table_lookup (override_map
, vtable
[i
]);
4560 g_hash_table_destroy (override_map
);
4561 override_map
= NULL
;
4564 g_slist_free (virt_methods
);
4565 virt_methods
= NULL
;
4567 /* Ensure that all vtable slots are filled with concrete instance methods */
4568 if (!(class->flags
& TYPE_ATTRIBUTE_ABSTRACT
)) {
4569 for (i
= 0; i
< cur_slot
; ++i
) {
4570 if (vtable
[i
] == NULL
|| (vtable
[i
]->flags
& (METHOD_ATTRIBUTE_ABSTRACT
| METHOD_ATTRIBUTE_STATIC
))) {
4571 char *type_name
= mono_type_get_full_name (class);
4572 char *method_name
= vtable
[i
] ? mono_method_full_name (vtable
[i
], TRUE
) : g_strdup ("none");
4573 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
));
4575 g_free (method_name
);
4581 if (class->generic_class
) {
4582 MonoClass
*gklass
= class->generic_class
->container_class
;
4584 mono_class_init (gklass
);
4586 class->vtable_size
= MAX (gklass
->vtable_size
, cur_slot
);
4588 /* Check that the vtable_size value computed in mono_class_init () is correct */
4589 if (class->vtable_size
)
4590 g_assert (cur_slot
== class->vtable_size
);
4591 class->vtable_size
= cur_slot
;
4594 /* Try to share the vtable with our parent. */
4595 if (class->parent
&& (class->parent
->vtable_size
== class->vtable_size
) && (memcmp (class->parent
->vtable
, vtable
, sizeof (gpointer
) * class->vtable_size
) == 0)) {
4596 mono_memory_barrier ();
4597 class->vtable
= class->parent
->vtable
;
4599 MonoMethod
**tmp
= mono_class_alloc0 (class, sizeof (gpointer
) * class->vtable_size
);
4600 memcpy (tmp
, vtable
, sizeof (gpointer
) * class->vtable_size
);
4601 mono_memory_barrier ();
4602 class->vtable
= tmp
;
4605 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable
, class->vtable_size
, first_non_interface_slot
, "FINALLY", FALSE
));
4606 if (mono_print_vtable
) {
4609 print_implemented_interfaces (class);
4611 for (i
= 0; i
<= max_iid
; i
++)
4612 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i
))
4615 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg
),
4616 class->vtable_size
, icount
);
4618 for (i
= 0; i
< cur_slot
; ++i
) {
4623 printf (" slot assigned: %03d, slot index: %03d %s\n", i
, cm
->slot
,
4624 mono_method_full_name (cm
, TRUE
));
4630 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space
,
4631 class->name
, max_iid
);
4633 for (i
= 0; i
< class->interface_count
; i
++) {
4634 ic
= class->interfaces
[i
];
4635 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4636 mono_class_interface_offset (class, ic
),
4637 count_virtual_methods (ic
), ic
->interface_id
, mono_type_full_name (&ic
->byval_arg
));
4640 for (k
= class->parent
; k
; k
= k
->parent
) {
4641 for (i
= 0; i
< k
->interface_count
; i
++) {
4642 ic
= k
->interfaces
[i
];
4643 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4644 mono_class_interface_offset (class, ic
),
4645 count_virtual_methods (ic
), ic
->interface_id
, mono_type_full_name (&ic
->byval_arg
));
4651 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4656 char *name
= mono_type_get_full_name (class);
4657 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("VTable setup of type %s failed", name
));
4660 g_hash_table_destroy (override_map
);
4662 g_slist_free (virt_methods
);
4667 * mono_method_get_vtable_slot:
4669 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4670 * LOCKING: Acquires the loader lock.
4672 * FIXME Use proper MonoError machinery here.
4675 mono_method_get_vtable_slot (MonoMethod
*method
)
4677 if (method
->slot
== -1) {
4678 mono_class_setup_vtable (method
->klass
);
4679 if (method
->klass
->exception_type
)
4681 if (method
->slot
== -1) {
4685 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4686 g_assert (method
->klass
->generic_class
);
4687 gklass
= method
->klass
->generic_class
->container_class
;
4688 mono_class_setup_methods (method
->klass
);
4689 g_assert (method
->klass
->methods
);
4690 for (i
= 0; i
< method
->klass
->method
.count
; ++i
) {
4691 if (method
->klass
->methods
[i
] == method
)
4694 g_assert (i
< method
->klass
->method
.count
);
4695 g_assert (gklass
->methods
);
4696 method
->slot
= gklass
->methods
[i
]->slot
;
4698 g_assert (method
->slot
!= -1);
4700 return method
->slot
;
4704 * mono_method_get_vtable_index:
4707 * Returns the index into the runtime vtable to access the method or,
4708 * in the case of a virtual generic method, the virtual generic method
4709 * thunk. Returns -1 on failure.
4711 * FIXME Use proper MonoError machinery here.
4714 mono_method_get_vtable_index (MonoMethod
*method
)
4716 if (method
->is_inflated
&& (method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
4717 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
4718 if (imethod
->declaring
->is_generic
)
4719 return mono_method_get_vtable_slot (imethod
->declaring
);
4721 return mono_method_get_vtable_slot (method
);
4724 static MonoMethod
*default_ghc
= NULL
;
4725 static MonoMethod
*default_finalize
= NULL
;
4726 static int finalize_slot
= -1;
4727 static int ghc_slot
= -1;
4730 initialize_object_slots (MonoClass
*class)
4735 if (class == mono_defaults
.object_class
) {
4736 mono_class_setup_vtable (class);
4737 for (i
= 0; i
< class->vtable_size
; ++i
) {
4738 MonoMethod
*cm
= class->vtable
[i
];
4740 if (!strcmp (cm
->name
, "GetHashCode"))
4742 else if (!strcmp (cm
->name
, "Finalize"))
4746 g_assert (ghc_slot
> 0);
4747 default_ghc
= class->vtable
[ghc_slot
];
4749 g_assert (finalize_slot
> 0);
4750 default_finalize
= class->vtable
[finalize_slot
];
4755 MonoMethod
*array_method
;
4757 } GenericArrayMethodInfo
;
4759 static int generic_array_method_num
= 0;
4760 static GenericArrayMethodInfo
*generic_array_method_info
= NULL
;
4763 generic_array_methods (MonoClass
*class)
4765 int i
, count_generic
= 0;
4766 GList
*list
= NULL
, *tmp
;
4767 if (generic_array_method_num
)
4768 return generic_array_method_num
;
4769 mono_class_setup_methods (class->parent
); /*This is setting up System.Array*/
4770 g_assert (!class->parent
->exception_type
); /*So hitting this assert is a huge problem*/
4771 for (i
= 0; i
< class->parent
->method
.count
; i
++) {
4772 MonoMethod
*m
= class->parent
->methods
[i
];
4773 if (!strncmp (m
->name
, "InternalArray__", 15)) {
4775 list
= g_list_prepend (list
, m
);
4778 list
= g_list_reverse (list
);
4779 generic_array_method_info
= mono_image_alloc (mono_defaults
.corlib
, sizeof (GenericArrayMethodInfo
) * count_generic
);
4781 for (tmp
= list
; tmp
; tmp
= tmp
->next
) {
4782 const char *mname
, *iname
;
4784 MonoMethod
*m
= tmp
->data
;
4785 const char *ireadonlylist_prefix
= "InternalArray__IReadOnlyList_";
4786 const char *ireadonlycollection_prefix
= "InternalArray__IReadOnlyCollection_";
4788 generic_array_method_info
[i
].array_method
= m
;
4789 if (!strncmp (m
->name
, "InternalArray__ICollection_", 27)) {
4790 iname
= "System.Collections.Generic.ICollection`1.";
4791 mname
= m
->name
+ 27;
4792 } else if (!strncmp (m
->name
, "InternalArray__IEnumerable_", 27)) {
4793 iname
= "System.Collections.Generic.IEnumerable`1.";
4794 mname
= m
->name
+ 27;
4795 } else if (!strncmp (m
->name
, ireadonlylist_prefix
, strlen (ireadonlylist_prefix
))) {
4796 iname
= "System.Collections.Generic.IReadOnlyList`1.";
4797 mname
= m
->name
+ strlen (ireadonlylist_prefix
);
4798 } else if (!strncmp (m
->name
, ireadonlycollection_prefix
, strlen (ireadonlycollection_prefix
))) {
4799 iname
= "System.Collections.Generic.IReadOnlyCollection`1.";
4800 mname
= m
->name
+ strlen (ireadonlycollection_prefix
);
4801 } else if (!strncmp (m
->name
, "InternalArray__", 15)) {
4802 iname
= "System.Collections.Generic.IList`1.";
4803 mname
= m
->name
+ 15;
4805 g_assert_not_reached ();
4808 name
= mono_image_alloc (mono_defaults
.corlib
, strlen (iname
) + strlen (mname
) + 1);
4809 strcpy (name
, iname
);
4810 strcpy (name
+ strlen (iname
), mname
);
4811 generic_array_method_info
[i
].name
= name
;
4814 /*g_print ("array generic methods: %d\n", count_generic);*/
4816 generic_array_method_num
= count_generic
;
4818 return generic_array_method_num
;
4822 setup_generic_array_ifaces (MonoClass
*class, MonoClass
*iface
, MonoMethod
**methods
, int pos
)
4824 MonoGenericContext tmp_context
;
4827 tmp_context
.class_inst
= NULL
;
4828 tmp_context
.method_inst
= iface
->generic_class
->context
.class_inst
;
4829 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4831 for (i
= 0; i
< generic_array_method_num
; i
++) {
4832 MonoMethod
*m
= generic_array_method_info
[i
].array_method
;
4833 MonoMethod
*inflated
;
4835 inflated
= mono_class_inflate_generic_method (m
, &tmp_context
);
4836 methods
[pos
++] = mono_marshal_get_generic_array_helper (class, iface
, generic_array_method_info
[i
].name
, inflated
);
4841 concat_two_strings_with_zero (MonoImage
*image
, const char *s1
, const char *s2
)
4843 int null_length
= strlen ("(null)");
4844 int len
= (s1
? strlen (s1
) : null_length
) + (s2
? strlen (s2
) : null_length
) + 2;
4845 char *s
= mono_image_alloc (image
, len
);
4848 result
= g_snprintf (s
, len
, "%s%c%s", s1
? s1
: "(null)", '\0', s2
? s2
: "(null)");
4849 g_assert (result
== len
- 1);
4855 set_failure_from_loader_error (MonoClass
*class, MonoLoaderError
*error
)
4857 gpointer exception_data
= NULL
;
4859 switch (error
->exception_type
) {
4860 case MONO_EXCEPTION_TYPE_LOAD
:
4861 exception_data
= concat_two_strings_with_zero (class->image
, error
->class_name
, error
->assembly_name
);
4864 case MONO_EXCEPTION_MISSING_METHOD
:
4865 exception_data
= concat_two_strings_with_zero (class->image
, error
->class_name
, error
->member_name
);
4868 case MONO_EXCEPTION_MISSING_FIELD
: {
4869 const char *name_space
= error
->klass
->name_space
? error
->klass
->name_space
: NULL
;
4870 const char *class_name
;
4873 class_name
= g_strdup_printf ("%s.%s", name_space
, error
->klass
->name
);
4875 class_name
= error
->klass
->name
;
4877 exception_data
= concat_two_strings_with_zero (class->image
, class_name
, error
->member_name
);
4880 g_free ((void*)class_name
);
4884 case MONO_EXCEPTION_FILE_NOT_FOUND
: {
4887 if (error
->ref_only
)
4888 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.";
4890 msg
= "Could not load file or assembly '%s' or one of its dependencies.";
4892 exception_data
= concat_two_strings_with_zero (class->image
, msg
, error
->assembly_name
);
4896 case MONO_EXCEPTION_BAD_IMAGE
:
4897 exception_data
= error
->msg
;
4901 g_assert_not_reached ();
4904 mono_class_set_failure (class, error
->exception_type
, exception_data
);
4909 * @class: the class to initialize
4911 * Compute the instance_size, class_size and other infos that cannot be
4912 * computed at mono_class_get() time. Also compute vtable_size if possible.
4913 * Returns TRUE on success or FALSE if there was a problem in loading
4914 * the type (incorrect assemblies, missing assemblies, methods, etc).
4916 * LOCKING: Acquires the loader lock.
4919 mono_class_init (MonoClass
*class)
4922 MonoCachedClassInfo cached_info
;
4923 gboolean has_cached_info
;
4927 /* Double-checking locking pattern */
4928 if (class->inited
|| class->exception_type
)
4929 return class->exception_type
== MONO_EXCEPTION_NONE
;
4931 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4933 /* We do everything inside the lock to prevent races */
4934 mono_loader_lock ();
4936 if (class->inited
|| class->exception_type
) {
4937 mono_loader_unlock ();
4938 /* Somebody might have gotten in before us */
4939 return class->exception_type
== MONO_EXCEPTION_NONE
;
4942 if (class->init_pending
) {
4943 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Recursive type definition detected"));
4947 class->init_pending
= 1;
4949 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4950 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, concat_two_strings_with_zero (class->image
, class->name
, class->image
->assembly_name
));
4955 if (class->byval_arg
.type
== MONO_TYPE_ARRAY
|| class->byval_arg
.type
== MONO_TYPE_SZARRAY
) {
4956 MonoClass
*element_class
= class->element_class
;
4957 if (!element_class
->inited
)
4958 mono_class_init (element_class
);
4959 if (element_class
->exception_type
!= MONO_EXCEPTION_NONE
) {
4960 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
4965 /* CAS - SecurityAction.InheritanceDemand */
4966 if (mono_security_enabled () && class->parent
&& (class->parent
->flags
& TYPE_ATTRIBUTE_HAS_SECURITY
)) {
4967 mono_secman_inheritancedemand_class (class, class->parent
);
4970 mono_stats
.initialized_class_count
++;
4972 if (class->generic_class
&& !class->generic_class
->is_dynamic
) {
4973 MonoClass
*gklass
= class->generic_class
->container_class
;
4975 mono_stats
.generic_class_count
++;
4977 class->method
= gklass
->method
;
4978 class->field
= gklass
->field
;
4980 mono_class_init (gklass
);
4981 // FIXME: Why is this needed ?
4982 if (!gklass
->exception_type
)
4983 mono_class_setup_methods (gklass
);
4984 if (gklass
->exception_type
) {
4985 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup_printf ("Generic Type Defintion failed to init"));
4989 if (MONO_CLASS_IS_INTERFACE (class))
4990 class->interface_id
= mono_get_unique_iid (class);
4993 if (class->parent
&& !class->parent
->inited
)
4994 mono_class_init (class->parent
);
4996 has_cached_info
= mono_class_get_cached_class_info (class, &cached_info
);
4998 if (class->generic_class
|| class->image
->dynamic
|| !class->type_token
|| (has_cached_info
&& !cached_info
.has_nested_classes
))
4999 class->nested_classes_inited
= TRUE
;
5002 * Computes the size used by the fields, and their locations
5004 if (has_cached_info
) {
5005 class->instance_size
= cached_info
.instance_size
;
5006 class->sizes
.class_size
= cached_info
.class_size
;
5007 class->packing_size
= cached_info
.packing_size
;
5008 class->min_align
= cached_info
.min_align
;
5009 class->blittable
= cached_info
.blittable
;
5010 class->has_references
= cached_info
.has_references
;
5011 class->has_static_refs
= cached_info
.has_static_refs
;
5012 class->no_special_static_fields
= cached_info
.no_special_static_fields
;
5015 if (!class->size_inited
){
5016 mono_class_setup_fields (class);
5017 if (class->exception_type
|| mono_loader_get_last_error ())
5021 /* Initialize arrays */
5023 class->method
.count
= 3 + (class->rank
> 1? 2: 1);
5025 if (class->interface_count
) {
5026 int count_generic
= generic_array_methods (class);
5027 class->method
.count
+= class->interface_count
* count_generic
;
5031 mono_class_setup_supertypes (class);
5034 initialize_object_slots (class);
5037 * Initialize the rest of the data without creating a generic vtable if possible.
5038 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5039 * also avoid computing a generic vtable.
5041 if (has_cached_info
) {
5043 class->vtable_size
= cached_info
.vtable_size
;
5044 class->has_finalize
= cached_info
.has_finalize
;
5045 class->has_finalize_inited
= TRUE
;
5046 class->ghcimpl
= cached_info
.ghcimpl
;
5047 class->has_cctor
= cached_info
.has_cctor
;
5048 } else if (class->rank
== 1 && class->byval_arg
.type
== MONO_TYPE_SZARRAY
) {
5049 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5050 * The first slot if for array with.
5052 static int szarray_vtable_size
[2] = { 0 };
5054 int slot
= MONO_TYPE_IS_REFERENCE (&class->element_class
->byval_arg
) ? 0 : 1;
5057 if (!szarray_vtable_size
[slot
]) {
5058 mono_class_setup_vtable (class);
5059 szarray_vtable_size
[slot
] = class->vtable_size
;
5061 class->vtable_size
= szarray_vtable_size
[slot
];
5063 class->has_finalize_inited
= TRUE
;
5064 } else if (class->generic_class
&& !MONO_CLASS_IS_INTERFACE (class)) {
5065 MonoClass
*gklass
= class->generic_class
->container_class
;
5067 /* Generic instance case */
5068 class->ghcimpl
= gklass
->ghcimpl
;
5069 class->has_finalize
= mono_class_has_finalizer (gklass
);
5070 class->has_finalize_inited
= TRUE
;
5071 class->has_cctor
= gklass
->has_cctor
;
5073 mono_class_setup_vtable (gklass
);
5074 if (gklass
->exception_type
) {
5075 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5079 class->vtable_size
= gklass
->vtable_size
;
5083 /* ghcimpl is not currently used
5085 if (class->parent) {
5086 MonoMethod *cmethod = class->vtable [ghc_slot];
5087 if (cmethod->is_inflated)
5088 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5089 if (cmethod == default_ghc) {
5095 /* C# doesn't allow interfaces to have cctors */
5096 if (!MONO_CLASS_IS_INTERFACE (class) || class->image
!= mono_defaults
.corlib
) {
5097 MonoMethod
*cmethod
= NULL
;
5099 if (class->type_token
) {
5100 cmethod
= find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME
);
5101 /* The find_method function ignores the 'flags' argument */
5102 if (cmethod
&& (cmethod
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
))
5103 class->has_cctor
= 1;
5105 mono_class_setup_methods (class);
5106 if (class->exception_type
)
5109 for (i
= 0; i
< class->method
.count
; ++i
) {
5110 MonoMethod
*method
= class->methods
[i
];
5111 if ((method
->flags
& METHOD_ATTRIBUTE_SPECIAL_NAME
) &&
5112 (strcmp (".cctor", method
->name
) == 0)) {
5113 class->has_cctor
= 1;
5121 if (class->parent
) {
5122 int first_iface_slot
;
5123 /* This will compute class->parent->vtable_size for some classes */
5124 mono_class_init (class->parent
);
5125 if (class->parent
->exception_type
) {
5126 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5129 if (mono_loader_get_last_error ())
5131 if (!class->parent
->vtable_size
) {
5132 /* FIXME: Get rid of this somehow */
5133 mono_class_setup_vtable (class->parent
);
5134 if (class->parent
->exception_type
) {
5135 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5138 if (mono_loader_get_last_error ())
5141 first_iface_slot
= class->parent
->vtable_size
;
5142 if (mono_class_need_stelemref_method (class))
5144 setup_interface_offsets (class, first_iface_slot
, TRUE
);
5146 setup_interface_offsets (class, 0, TRUE
);
5149 if (mono_security_core_clr_enabled ())
5150 mono_security_core_clr_check_inheritance (class);
5152 if (mono_loader_get_last_error ()) {
5153 if (class->exception_type
== MONO_EXCEPTION_NONE
) {
5154 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5156 mono_loader_clear_error ();
5159 if (class->generic_class
&& !mono_verifier_class_is_valid_generic_instantiation (class))
5160 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Invalid generic instantiation"));
5165 /* Because of the double-checking locking pattern */
5166 mono_memory_barrier ();
5168 class->init_pending
= 0;
5170 mono_loader_unlock ();
5172 if (mono_debugger_class_init_func
)
5173 mono_debugger_class_init_func (class);
5175 return class->exception_type
== MONO_EXCEPTION_NONE
;
5179 * mono_class_has_finalizer:
5181 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5185 mono_class_has_finalizer (MonoClass
*klass
)
5187 if (!klass
->has_finalize_inited
) {
5188 MonoClass
*class = klass
;
5190 mono_loader_lock ();
5192 /* Interfaces and valuetypes are not supposed to have finalizers */
5193 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype
)) {
5194 MonoMethod
*cmethod
= NULL
;
5196 if (class->parent
&& class->parent
->has_finalize
) {
5197 class->has_finalize
= 1;
5199 if (class->parent
) {
5201 * Can't search in metadata for a method named Finalize, because that
5202 * ignores overrides.
5204 mono_class_setup_vtable (class);
5205 if (class->exception_type
|| mono_loader_get_last_error ())
5207 cmethod
= class->vtable
[finalize_slot
];
5211 g_assert (class->vtable_size
> finalize_slot
);
5213 class->has_finalize
= 0;
5214 if (class->parent
) {
5215 if (cmethod
->is_inflated
)
5216 cmethod
= ((MonoMethodInflated
*)cmethod
)->declaring
;
5217 if (cmethod
!= default_finalize
) {
5218 class->has_finalize
= 1;
5225 mono_memory_barrier ();
5226 klass
->has_finalize_inited
= TRUE
;
5228 mono_loader_unlock ();
5231 return klass
->has_finalize
;
5234 mono_loader_unlock ();
5239 mono_is_corlib_image (MonoImage
*image
)
5241 /* FIXME: allow the dynamic case for our compilers and with full trust */
5243 return image
->assembly
&& !strcmp (image
->assembly
->aname
.name
, "mscorlib");
5245 return image
== mono_defaults
.corlib
;
5249 * LOCKING: this assumes the loader lock is held
5252 mono_class_setup_mono_type (MonoClass
*class)
5254 const char *name
= class->name
;
5255 const char *nspace
= class->name_space
;
5256 gboolean is_corlib
= mono_is_corlib_image (class->image
);
5258 class->this_arg
.byref
= 1;
5259 class->this_arg
.data
.klass
= class;
5260 class->this_arg
.type
= MONO_TYPE_CLASS
;
5261 class->byval_arg
.data
.klass
= class;
5262 class->byval_arg
.type
= MONO_TYPE_CLASS
;
5264 if (is_corlib
&& !strcmp (nspace
, "System")) {
5265 if (!strcmp (name
, "ValueType")) {
5267 * do not set the valuetype bit for System.ValueType.
5268 * class->valuetype = 1;
5270 class->blittable
= TRUE
;
5271 } else if (!strcmp (name
, "Enum")) {
5273 * do not set the valuetype bit for System.Enum.
5274 * class->valuetype = 1;
5276 class->valuetype
= 0;
5277 class->enumtype
= 0;
5278 } else if (!strcmp (name
, "Object")) {
5279 class->this_arg
.type
= class->byval_arg
.type
= MONO_TYPE_OBJECT
;
5280 } else if (!strcmp (name
, "String")) {
5281 class->this_arg
.type
= class->byval_arg
.type
= MONO_TYPE_STRING
;
5282 } else if (!strcmp (name
, "TypedReference")) {
5283 class->this_arg
.type
= class->byval_arg
.type
= MONO_TYPE_TYPEDBYREF
;
5287 if (class->valuetype
) {
5288 int t
= MONO_TYPE_VALUETYPE
;
5290 if (is_corlib
&& !strcmp (nspace
, "System")) {
5293 if (!strcmp (name
, "Boolean")) {
5294 t
= MONO_TYPE_BOOLEAN
;
5295 } else if (!strcmp(name
, "Byte")) {
5297 class->blittable
= TRUE
;
5301 if (!strcmp (name
, "Char")) {
5306 if (!strcmp (name
, "Double")) {
5308 class->blittable
= TRUE
;
5312 if (!strcmp (name
, "Int32")) {
5314 class->blittable
= TRUE
;
5315 } else if (!strcmp(name
, "Int16")) {
5317 class->blittable
= TRUE
;
5318 } else if (!strcmp(name
, "Int64")) {
5320 class->blittable
= TRUE
;
5321 } else if (!strcmp(name
, "IntPtr")) {
5323 class->blittable
= TRUE
;
5327 if (!strcmp (name
, "Single")) {
5329 class->blittable
= TRUE
;
5330 } else if (!strcmp(name
, "SByte")) {
5332 class->blittable
= TRUE
;
5336 if (!strcmp (name
, "UInt32")) {
5338 class->blittable
= TRUE
;
5339 } else if (!strcmp(name
, "UInt16")) {
5341 class->blittable
= TRUE
;
5342 } else if (!strcmp(name
, "UInt64")) {
5344 class->blittable
= TRUE
;
5345 } else if (!strcmp(name
, "UIntPtr")) {
5347 class->blittable
= TRUE
;
5351 if (!strcmp (name
, "TypedReference")) {
5352 t
= MONO_TYPE_TYPEDBYREF
;
5353 class->blittable
= TRUE
;
5357 if (!strcmp (name
, "Void")) {
5365 class->this_arg
.type
= class->byval_arg
.type
= t
;
5368 if (MONO_CLASS_IS_INTERFACE (class))
5369 class->interface_id
= mono_get_unique_iid (class);
5375 * COM initialization is delayed until needed.
5376 * However when a [ComImport] attribute is present on a type it will trigger
5377 * the initialization. This is not a problem unless the BCL being executed
5378 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5381 init_com_from_comimport (MonoClass
*class)
5383 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5384 if (mono_security_core_clr_enabled ()) {
5385 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5386 if (!mono_security_core_clr_determine_platform_image (class->image
)) {
5387 /* but it can not be made available for application (i.e. user code) since all COM calls
5388 * are considered native calls. In this case we fail with a TypeLoadException (just like
5389 * Silverlight 2 does */
5390 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5395 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5397 #endif /*DISABLE_COM*/
5400 * LOCKING: this assumes the loader lock is held
5403 mono_class_setup_parent (MonoClass
*class, MonoClass
*parent
)
5405 gboolean system_namespace
;
5406 gboolean is_corlib
= mono_is_corlib_image (class->image
);
5408 system_namespace
= !strcmp (class->name_space
, "System") && is_corlib
;
5410 /* if root of the hierarchy */
5411 if (system_namespace
&& !strcmp (class->name
, "Object")) {
5412 class->parent
= NULL
;
5413 class->instance_size
= sizeof (MonoObject
);
5416 if (!strcmp (class->name
, "<Module>")) {
5417 class->parent
= NULL
;
5418 class->instance_size
= 0;
5422 if (!MONO_CLASS_IS_INTERFACE (class)) {
5423 /* Imported COM Objects always derive from __ComObject. */
5425 if (MONO_CLASS_IS_IMPORT (class)) {
5426 init_com_from_comimport (class);
5427 if (parent
== mono_defaults
.object_class
)
5428 parent
= mono_class_get_com_object_class ();
5432 /* set the parent to something useful and safe, but mark the type as broken */
5433 parent
= mono_defaults
.object_class
;
5434 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5437 class->parent
= parent
;
5439 if (parent
->generic_class
&& !parent
->name
) {
5441 * If the parent is a generic instance, we may get
5442 * called before it is fully initialized, especially
5443 * before it has its name.
5448 #ifndef DISABLE_REMOTING
5449 class->marshalbyref
= parent
->marshalbyref
;
5450 class->contextbound
= parent
->contextbound
;
5453 class->delegate
= parent
->delegate
;
5455 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent
))
5456 mono_class_set_is_com_object (class);
5458 if (system_namespace
) {
5459 #ifndef DISABLE_REMOTING
5460 if (*class->name
== 'M' && !strcmp (class->name
, "MarshalByRefObject"))
5461 class->marshalbyref
= 1;
5463 if (*class->name
== 'C' && !strcmp (class->name
, "ContextBoundObject"))
5464 class->contextbound
= 1;
5466 if (*class->name
== 'D' && !strcmp (class->name
, "Delegate"))
5467 class->delegate
= 1;
5470 if (class->parent
->enumtype
|| (mono_is_corlib_image (class->parent
->image
) && (strcmp (class->parent
->name
, "ValueType") == 0) &&
5471 (strcmp (class->parent
->name_space
, "System") == 0)))
5472 class->valuetype
= 1;
5473 if (mono_is_corlib_image (class->parent
->image
) && ((strcmp (class->parent
->name
, "Enum") == 0) && (strcmp (class->parent
->name_space
, "System") == 0))) {
5474 class->valuetype
= class->enumtype
= 1;
5476 /*class->enumtype = class->parent->enumtype; */
5478 /* initialize com types if COM interfaces are present */
5480 if (MONO_CLASS_IS_IMPORT (class))
5481 init_com_from_comimport (class);
5483 class->parent
= NULL
;
5489 * mono_class_setup_supertypes:
5492 * Build the data structure needed to make fast type checks work.
5493 * This currently sets two fields in @class:
5494 * - idepth: distance between @class and System.Object in the type
5496 * - supertypes: array of classes: each element has a class in the hierarchy
5497 * starting from @class up to System.Object
5499 * LOCKING: This function is atomic, in case of contention we waste memory.
5502 mono_class_setup_supertypes (MonoClass
*class)
5505 MonoClass
**supertypes
;
5507 mono_atomic_load_acquire (supertypes
, void*, &class->supertypes
);
5511 if (class->parent
&& !class->parent
->supertypes
)
5512 mono_class_setup_supertypes (class->parent
);
5514 class->idepth
= class->parent
->idepth
+ 1;
5518 ms
= MAX (MONO_DEFAULT_SUPERTABLE_SIZE
, class->idepth
);
5519 supertypes
= mono_class_alloc0 (class, sizeof (MonoClass
*) * ms
);
5521 if (class->parent
) {
5522 supertypes
[class->idepth
- 1] = class;
5523 memcpy (supertypes
, class->parent
->supertypes
, class->parent
->idepth
* sizeof (gpointer
));
5525 supertypes
[0] = class;
5528 mono_atomic_store_release (&class->supertypes
, supertypes
);
5532 fix_gclass_incomplete_instantiation (MonoClass
*gclass
, void *user_data
)
5534 MonoClass
*gtd
= (MonoClass
*)user_data
;
5535 /* Only try to fix generic instances of @gtd */
5536 if (gclass
->generic_class
->container_class
!= gtd
)
5539 /* Check if the generic instance has no parent. */
5540 if (gtd
->parent
&& !gclass
->parent
)
5541 mono_generic_class_setup_parent (gclass
, gtd
);
5547 mono_class_set_failure_and_error (MonoClass
*class, MonoError
*error
, const char *msg
)
5549 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup (msg
));
5550 mono_error_set_type_load_class (error
, class, msg
);
5554 mono_class_set_failure_from_loader_error (MonoClass
*class, MonoError
*error
, char *msg
)
5556 MonoLoaderError
*lerror
= mono_loader_get_last_error ();
5559 set_failure_from_loader_error (class, lerror
);
5560 mono_error_set_from_loader_error (error
);
5564 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, msg
);
5565 mono_error_set_type_load_class (error
, class, msg
);
5570 * mono_class_create_from_typedef:
5571 * @image: image where the token is valid
5572 * @type_token: typedef token
5573 * @error: used to return any error found while creating the type
5575 * Create the MonoClass* representing the specified type token.
5576 * @type_token must be a TypeDef token.
5578 * FIXME: don't return NULL on failure, just the the caller figure it out.
5581 mono_class_create_from_typedef (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
5583 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
5584 MonoClass
*class, *parent
= NULL
;
5585 guint32 cols
[MONO_TYPEDEF_SIZE
];
5586 guint32 cols_next
[MONO_TYPEDEF_SIZE
];
5587 guint tidx
= mono_metadata_token_index (type_token
);
5588 MonoGenericContext
*context
= NULL
;
5589 const char *name
, *nspace
;
5591 MonoClass
**interfaces
;
5592 guint32 field_last
, method_last
;
5593 guint32 nesting_tokeen
;
5595 mono_error_init (error
);
5597 if (mono_metadata_token_table (type_token
) != MONO_TABLE_TYPEDEF
|| tidx
> tt
->rows
) {
5598 mono_error_set_bad_image (error
, image
, "Invalid typedef token %x", type_token
);
5599 g_assert (!mono_loader_get_last_error ());
5603 mono_loader_lock ();
5605 if ((class = mono_internal_hash_table_lookup (&image
->class_cache
, GUINT_TO_POINTER (type_token
)))) {
5606 mono_loader_unlock ();
5607 g_assert (!mono_loader_get_last_error ());
5611 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
5613 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
5614 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
5616 class = mono_image_alloc0 (image
, sizeof (MonoClass
));
5619 class->name_space
= nspace
;
5621 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD
);
5623 class->image
= image
;
5624 class->type_token
= type_token
;
5625 class->flags
= cols
[MONO_TYPEDEF_FLAGS
];
5627 mono_internal_hash_table_insert (&image
->class_cache
, GUINT_TO_POINTER (type_token
), class);
5629 classes_size
+= sizeof (MonoClass
);
5632 * Check whether we're a generic type definition.
5634 class->generic_container
= mono_metadata_load_generic_params (image
, class->type_token
, NULL
);
5635 if (class->generic_container
) {
5636 class->is_generic
= 1;
5637 class->generic_container
->owner
.klass
= class;
5638 context
= &class->generic_container
->context
;
5641 if (class->generic_container
)
5642 enable_gclass_recording ();
5644 if (cols
[MONO_TYPEDEF_EXTENDS
]) {
5646 guint32 parent_token
= mono_metadata_token_from_dor (cols
[MONO_TYPEDEF_EXTENDS
]);
5648 if (mono_metadata_token_table (parent_token
) == MONO_TABLE_TYPESPEC
) {
5649 /*WARNING: this must satisfy mono_metadata_type_hash*/
5650 class->this_arg
.byref
= 1;
5651 class->this_arg
.data
.klass
= class;
5652 class->this_arg
.type
= MONO_TYPE_CLASS
;
5653 class->byval_arg
.data
.klass
= class;
5654 class->byval_arg
.type
= MONO_TYPE_CLASS
;
5656 parent
= mono_class_get_full (image
, parent_token
, context
);
5658 if (parent
== NULL
) {
5659 mono_class_set_failure_from_loader_error (class, error
, g_strdup_printf ("Could not load parent, token is %x", parent_token
));
5660 goto parent_failure
;
5663 for (tmp
= parent
; tmp
; tmp
= tmp
->parent
) {
5665 mono_class_set_failure_and_error (class, error
, "Cycle found while resolving parent");
5666 goto parent_failure
;
5668 if (class->generic_container
&& tmp
->generic_class
&& tmp
->generic_class
->container_class
== class) {
5669 mono_class_set_failure_and_error (class, error
, "Parent extends generic instance of this type");
5670 goto parent_failure
;
5675 mono_class_setup_parent (class, parent
);
5677 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5678 mono_class_setup_mono_type (class);
5680 if (class->generic_container
)
5681 disable_gclass_recording (fix_gclass_incomplete_instantiation
, class);
5684 * This might access class->byval_arg for recursion generated by generic constraints,
5685 * so it has to come after setup_mono_type ().
5687 if ((nesting_tokeen
= mono_metadata_nested_in_typedef (image
, type_token
))) {
5688 class->nested_in
= mono_class_create_from_typedef (image
, nesting_tokeen
, error
);
5689 if (!mono_error_ok (error
)) {
5690 /*FIXME implement a mono_class_set_failure_from_mono_error */
5691 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, g_strdup (mono_error_get_message (error
)));
5692 mono_loader_unlock ();
5693 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5694 g_assert (!mono_loader_get_last_error ());
5699 if ((class->flags
& TYPE_ATTRIBUTE_STRING_FORMAT_MASK
) == TYPE_ATTRIBUTE_UNICODE_CLASS
)
5703 if ((class->flags
& TYPE_ATTRIBUTE_STRING_FORMAT_MASK
) == TYPE_ATTRIBUTE_AUTO_CLASS
)
5707 class->cast_class
= class->element_class
= class;
5709 if (!class->enumtype
) {
5710 if (!mono_metadata_interfaces_from_typedef_full (
5711 image
, type_token
, &interfaces
, &icount
, FALSE
, context
)){
5712 mono_class_set_failure_from_loader_error (class, error
, g_strdup ("Could not load interfaces"));
5713 mono_loader_unlock ();
5714 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5718 class->interfaces
= interfaces
;
5719 class->interface_count
= icount
;
5720 class->interfaces_inited
= 1;
5723 /*g_print ("Load class %s\n", name);*/
5726 * Compute the field and method lists
5728 class->field
.first
= cols
[MONO_TYPEDEF_FIELD_LIST
] - 1;
5729 class->method
.first
= cols
[MONO_TYPEDEF_METHOD_LIST
] - 1;
5731 if (tt
->rows
> tidx
){
5732 mono_metadata_decode_row (tt
, tidx
, cols_next
, MONO_TYPEDEF_SIZE
);
5733 field_last
= cols_next
[MONO_TYPEDEF_FIELD_LIST
] - 1;
5734 method_last
= cols_next
[MONO_TYPEDEF_METHOD_LIST
] - 1;
5736 field_last
= image
->tables
[MONO_TABLE_FIELD
].rows
;
5737 method_last
= image
->tables
[MONO_TABLE_METHOD
].rows
;
5740 if (cols
[MONO_TYPEDEF_FIELD_LIST
] &&
5741 cols
[MONO_TYPEDEF_FIELD_LIST
] <= image
->tables
[MONO_TABLE_FIELD
].rows
)
5742 class->field
.count
= field_last
- class->field
.first
;
5744 class->field
.count
= 0;
5746 if (cols
[MONO_TYPEDEF_METHOD_LIST
] <= image
->tables
[MONO_TABLE_METHOD
].rows
)
5747 class->method
.count
= method_last
- class->method
.first
;
5749 class->method
.count
= 0;
5751 /* reserve space to store vector pointer in arrays */
5752 if (mono_is_corlib_image (image
) && !strcmp (nspace
, "System") && !strcmp (name
, "Array")) {
5753 class->instance_size
+= 2 * sizeof (gpointer
);
5754 g_assert (class->field
.count
== 0);
5757 if (class->enumtype
) {
5758 MonoType
*enum_basetype
= mono_class_find_enum_basetype (class);
5759 if (!enum_basetype
) {
5760 /*set it to a default value as the whole runtime can't handle this to be null*/
5761 class->cast_class
= class->element_class
= mono_defaults
.int32_class
;
5762 mono_class_set_failure_and_error (class, error
, "Could not enum basetype");
5763 mono_loader_unlock ();
5764 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5765 g_assert (!mono_loader_get_last_error ());
5768 class->cast_class
= class->element_class
= mono_class_from_mono_type (enum_basetype
);
5772 * If we're a generic type definition, load the constraints.
5773 * We must do this after the class has been constructed to make certain recursive scenarios
5776 if (class->generic_container
&& !mono_metadata_load_generic_param_constraints_full (image
, type_token
, class->generic_container
)){
5777 mono_class_set_failure_from_loader_error (class, error
, g_strdup ("Could not load generic parameter constraints"));
5778 mono_loader_unlock ();
5779 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5780 g_assert (!mono_loader_get_last_error ());
5784 if (class->image
->assembly_name
&& !strcmp (class->image
->assembly_name
, "Mono.Simd") && !strcmp (nspace
, "Mono.Simd")) {
5785 if (!strncmp (name
, "Vector", 6))
5786 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");
5789 mono_loader_unlock ();
5791 mono_profiler_class_loaded (class, MONO_PROFILE_OK
);
5792 g_assert (!mono_loader_get_last_error ());
5797 mono_class_setup_mono_type (class);
5798 mono_loader_unlock ();
5799 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED
);
5800 g_assert (!mono_loader_get_last_error ());
5804 /** is klass Nullable<T>? */
5806 mono_class_is_nullable (MonoClass
*klass
)
5808 return klass
->generic_class
!= NULL
&&
5809 klass
->generic_class
->container_class
== mono_defaults
.generic_nullable_class
;
5813 /** if klass is T? return T */
5815 mono_class_get_nullable_param (MonoClass
*klass
)
5817 g_assert (mono_class_is_nullable (klass
));
5818 return mono_class_from_mono_type (klass
->generic_class
->context
.class_inst
->type_argv
[0]);
5822 mono_generic_class_setup_parent (MonoClass
*klass
, MonoClass
*gtd
)
5826 MonoGenericClass
*gclass
= klass
->generic_class
;
5828 klass
->parent
= mono_class_inflate_generic_class_checked (gtd
->parent
, mono_generic_class_get_context (gclass
), &error
);
5829 if (!mono_error_ok (&error
)) {
5830 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5831 klass
->parent
= mono_defaults
.object_class
;
5832 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
5833 mono_error_cleanup (&error
);
5837 mono_class_setup_parent (klass
, klass
->parent
);
5839 if (klass
->enumtype
) {
5840 klass
->cast_class
= gtd
->cast_class
;
5841 klass
->element_class
= gtd
->element_class
;
5847 * Create the `MonoClass' for an instantiation of a generic type.
5848 * We only do this if we actually need it.
5851 mono_generic_class_get_class (MonoGenericClass
*gclass
)
5853 MonoClass
*klass
, *gklass
;
5855 if (gclass
->cached_class
)
5856 return gclass
->cached_class
;
5858 mono_loader_lock ();
5859 if (gclass
->cached_class
) {
5860 mono_loader_unlock ();
5861 return gclass
->cached_class
;
5864 klass
= mono_image_set_alloc0 (gclass
->owner
, sizeof (MonoClass
));
5866 gklass
= gclass
->container_class
;
5868 if (record_gclass_instantiation
> 0)
5869 gclass_recorded_list
= g_slist_append (gclass_recorded_list
, klass
);
5871 if (gklass
->nested_in
) {
5872 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5873 klass
->nested_in
= gklass
->nested_in
;
5876 klass
->name
= gklass
->name
;
5877 klass
->name_space
= gklass
->name_space
;
5879 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
5881 klass
->image
= gklass
->image
;
5882 klass
->flags
= gklass
->flags
;
5883 klass
->type_token
= gklass
->type_token
;
5884 klass
->field
.count
= gklass
->field
.count
;
5886 klass
->is_inflated
= 1;
5887 klass
->generic_class
= gclass
;
5889 klass
->this_arg
.type
= klass
->byval_arg
.type
= MONO_TYPE_GENERICINST
;
5890 klass
->this_arg
.data
.generic_class
= klass
->byval_arg
.data
.generic_class
= gclass
;
5891 klass
->this_arg
.byref
= TRUE
;
5892 klass
->enumtype
= gklass
->enumtype
;
5893 klass
->valuetype
= gklass
->valuetype
;
5895 klass
->cast_class
= klass
->element_class
= klass
;
5897 if (mono_class_is_nullable (klass
))
5898 klass
->cast_class
= klass
->element_class
= mono_class_get_nullable_param (klass
);
5901 * We're not interested in the nested classes of a generic instance.
5902 * We use the generic type definition to look for nested classes.
5905 mono_generic_class_setup_parent (klass
, gklass
);
5907 if (gclass
->is_dynamic
) {
5910 mono_class_setup_supertypes (klass
);
5912 if (klass
->enumtype
) {
5914 * For enums, gklass->fields might not been set, but instance_size etc. is
5915 * already set in mono_reflection_create_internal_class (). For non-enums,
5916 * these will be computed normally in mono_class_layout_fields ().
5918 klass
->instance_size
= gklass
->instance_size
;
5919 klass
->sizes
.class_size
= gklass
->sizes
.class_size
;
5920 mono_memory_barrier ();
5921 klass
->size_inited
= 1;
5925 mono_memory_barrier ();
5926 gclass
->cached_class
= klass
;
5928 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
5930 inflated_classes
++;
5931 inflated_classes_size
+= sizeof (MonoClass
);
5933 mono_loader_unlock ();
5939 make_generic_param_class (MonoGenericParam
*param
, MonoImage
*image
, gboolean is_mvar
, MonoGenericParamInfo
*pinfo
)
5941 MonoClass
*klass
, **ptr
;
5943 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
5947 image
= mono_defaults
.corlib
;
5949 klass
= mono_image_alloc0 (image
, sizeof (MonoClass
));
5950 classes_size
+= sizeof (MonoClass
);
5953 klass
->name
= pinfo
->name
;
5955 int n
= mono_generic_param_num (param
);
5956 klass
->name
= mono_image_alloc0 (image
, 16);
5957 sprintf ((char*)klass
->name
, "%d", n
);
5962 MonoMethod
*omethod
= container
->owner
.method
;
5963 klass
->name_space
= (omethod
&& omethod
->klass
) ? omethod
->klass
->name_space
: "";
5965 MonoClass
*oklass
= container
->owner
.klass
;
5966 klass
->name_space
= oklass
? oklass
->name_space
: "";
5969 klass
->name_space
= "";
5972 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
5976 for (ptr
= pinfo
->constraints
; ptr
&& *ptr
; ptr
++, count
++)
5980 if ((count
> 0) && !MONO_CLASS_IS_INTERFACE (pinfo
->constraints
[0])) {
5981 klass
->parent
= pinfo
->constraints
[0];
5983 } else if (pinfo
&& pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
)
5984 klass
->parent
= mono_class_from_name (mono_defaults
.corlib
, "System", "ValueType");
5986 klass
->parent
= mono_defaults
.object_class
;
5989 if (count
- pos
> 0) {
5990 klass
->interface_count
= count
- pos
;
5991 klass
->interfaces
= mono_image_alloc0 (image
, sizeof (MonoClass
*) * (count
- pos
));
5992 klass
->interfaces_inited
= TRUE
;
5993 for (i
= pos
; i
< count
; i
++)
5994 klass
->interfaces
[i
- pos
] = pinfo
->constraints
[i
];
5997 klass
->image
= image
;
5999 klass
->inited
= TRUE
;
6000 klass
->cast_class
= klass
->element_class
= klass
;
6001 klass
->flags
= TYPE_ATTRIBUTE_PUBLIC
;
6003 klass
->this_arg
.type
= klass
->byval_arg
.type
= is_mvar
? MONO_TYPE_MVAR
: MONO_TYPE_VAR
;
6004 klass
->this_arg
.data
.generic_param
= klass
->byval_arg
.data
.generic_param
= param
;
6005 klass
->this_arg
.byref
= TRUE
;
6007 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6008 klass
->sizes
.generic_param_token
= pinfo
? pinfo
->token
: 0;
6010 /*Init these fields to sane values*/
6011 klass
->min_align
= 1;
6012 klass
->instance_size
= sizeof (gpointer
);
6013 mono_memory_barrier ();
6014 klass
->size_inited
= 1;
6016 mono_class_setup_supertypes (klass
);
6018 if (count
- pos
> 0) {
6019 mono_class_setup_vtable (klass
->parent
);
6020 if (klass
->parent
->exception_type
)
6021 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Failed to setup parent interfaces"));
6023 setup_interface_offsets (klass
, klass
->parent
->vtable_size
, TRUE
);
6029 #define FAST_CACHE_SIZE 16
6032 get_anon_gparam_class (MonoGenericParam
*param
, gboolean is_mvar
)
6034 int n
= mono_generic_param_num (param
) | ((guint32
)param
->serial
<< 16);
6035 MonoImage
*image
= param
->image
;
6040 if (n
< FAST_CACHE_SIZE
) {
6042 return image
->mvar_cache_fast
? image
->mvar_cache_fast
[n
] : NULL
;
6044 return image
->var_cache_fast
? image
->var_cache_fast
[n
] : NULL
;
6046 ht
= is_mvar
? image
->mvar_cache_slow
: image
->var_cache_slow
;
6047 return ht
? g_hash_table_lookup (ht
, GINT_TO_POINTER (n
)) : NULL
;
6052 * LOCKING: Acquires the loader lock.
6055 set_anon_gparam_class (MonoGenericParam
*param
, gboolean is_mvar
, MonoClass
*klass
)
6057 int n
= mono_generic_param_num (param
) | ((guint32
)param
->serial
<< 16);
6058 MonoImage
*image
= param
->image
;
6063 if (n
< FAST_CACHE_SIZE
) {
6065 /* No locking needed */
6066 if (!image
->mvar_cache_fast
)
6067 image
->mvar_cache_fast
= mono_image_alloc0 (image
, sizeof (MonoClass
*) * FAST_CACHE_SIZE
);
6068 image
->mvar_cache_fast
[n
] = klass
;
6070 if (!image
->var_cache_fast
)
6071 image
->var_cache_fast
= mono_image_alloc0 (image
, sizeof (MonoClass
*) * FAST_CACHE_SIZE
);
6072 image
->var_cache_fast
[n
] = klass
;
6076 ht
= is_mvar
? image
->mvar_cache_slow
: image
->var_cache_slow
;
6078 mono_loader_lock ();
6079 ht
= is_mvar
? image
->mvar_cache_slow
: image
->var_cache_slow
;
6081 ht
= g_hash_table_new (NULL
, NULL
);
6082 mono_memory_barrier ();
6084 image
->mvar_cache_slow
= ht
;
6086 image
->var_cache_slow
= ht
;
6088 mono_loader_unlock ();
6091 g_hash_table_insert (ht
, GINT_TO_POINTER (n
), klass
);
6095 * LOCKING: Acquires the loader lock.
6098 mono_class_from_generic_parameter (MonoGenericParam
*param
, MonoImage
*image
, gboolean is_mvar
)
6100 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
6101 MonoGenericParamInfo
*pinfo
;
6104 mono_loader_lock ();
6107 pinfo
= mono_generic_param_info (param
);
6108 if (pinfo
->pklass
) {
6109 mono_loader_unlock ();
6110 return pinfo
->pklass
;
6116 klass
= get_anon_gparam_class (param
, is_mvar
);
6118 mono_loader_unlock ();
6123 if (!image
&& container
) {
6125 MonoMethod
*method
= container
->owner
.method
;
6126 image
= (method
&& method
->klass
) ? method
->klass
->image
: NULL
;
6128 MonoClass
*klass
= container
->owner
.klass
;
6129 // FIXME: 'klass' should not be null
6130 // But, monodis creates GenericContainers without associating a owner to it
6131 image
= klass
? klass
->image
: NULL
;
6135 klass
= make_generic_param_class (param
, image
, is_mvar
, pinfo
);
6137 mono_memory_barrier ();
6140 pinfo
->pklass
= klass
;
6142 set_anon_gparam_class (param
, is_mvar
, klass
);
6144 mono_loader_unlock ();
6146 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6147 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
6153 mono_ptr_class_get (MonoType
*type
)
6156 MonoClass
*el_class
;
6160 el_class
= mono_class_from_mono_type (type
);
6161 image
= el_class
->image
;
6163 mono_loader_lock ();
6165 if (!image
->ptr_cache
)
6166 image
->ptr_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
6168 if ((result
= g_hash_table_lookup (image
->ptr_cache
, el_class
))) {
6169 mono_loader_unlock ();
6172 result
= mono_image_alloc0 (image
, sizeof (MonoClass
));
6174 classes_size
+= sizeof (MonoClass
);
6176 result
->parent
= NULL
; /* no parent for PTR types */
6177 result
->name_space
= el_class
->name_space
;
6178 name
= g_strdup_printf ("%s*", el_class
->name
);
6179 result
->name
= mono_image_strdup (image
, name
);
6182 mono_profiler_class_event (result
, MONO_PROFILE_START_LOAD
);
6184 result
->image
= el_class
->image
;
6185 result
->inited
= TRUE
;
6186 result
->flags
= TYPE_ATTRIBUTE_CLASS
| (el_class
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
);
6187 /* Can pointers get boxed? */
6188 result
->instance_size
= sizeof (gpointer
);
6189 result
->cast_class
= result
->element_class
= el_class
;
6190 result
->blittable
= TRUE
;
6192 result
->this_arg
.type
= result
->byval_arg
.type
= MONO_TYPE_PTR
;
6193 result
->this_arg
.data
.type
= result
->byval_arg
.data
.type
= &result
->element_class
->byval_arg
;
6194 result
->this_arg
.byref
= TRUE
;
6196 mono_class_setup_supertypes (result
);
6198 g_hash_table_insert (image
->ptr_cache
, el_class
, result
);
6200 mono_loader_unlock ();
6202 mono_profiler_class_loaded (result
, MONO_PROFILE_OK
);
6208 mono_fnptr_class_get (MonoMethodSignature
*sig
)
6211 static GHashTable
*ptr_hash
= NULL
;
6213 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6215 mono_loader_lock ();
6218 ptr_hash
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
6220 if ((result
= g_hash_table_lookup (ptr_hash
, sig
))) {
6221 mono_loader_unlock ();
6224 result
= g_new0 (MonoClass
, 1);
6226 result
->parent
= NULL
; /* no parent for PTR types */
6227 result
->name_space
= "System";
6228 result
->name
= "MonoFNPtrFakeClass";
6230 mono_profiler_class_event (result
, MONO_PROFILE_START_LOAD
);
6232 result
->image
= mono_defaults
.corlib
; /* need to fix... */
6233 result
->inited
= TRUE
;
6234 result
->flags
= TYPE_ATTRIBUTE_CLASS
; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6235 /* Can pointers get boxed? */
6236 result
->instance_size
= sizeof (gpointer
);
6237 result
->cast_class
= result
->element_class
= result
;
6238 result
->blittable
= TRUE
;
6240 result
->this_arg
.type
= result
->byval_arg
.type
= MONO_TYPE_FNPTR
;
6241 result
->this_arg
.data
.method
= result
->byval_arg
.data
.method
= sig
;
6242 result
->this_arg
.byref
= TRUE
;
6243 result
->blittable
= TRUE
;
6245 mono_class_setup_supertypes (result
);
6247 g_hash_table_insert (ptr_hash
, sig
, result
);
6249 mono_loader_unlock ();
6251 mono_profiler_class_loaded (result
, MONO_PROFILE_OK
);
6257 mono_class_from_mono_type (MonoType
*type
)
6259 switch (type
->type
) {
6260 case MONO_TYPE_OBJECT
:
6261 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.object_class
;
6262 case MONO_TYPE_VOID
:
6263 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.void_class
;
6264 case MONO_TYPE_BOOLEAN
:
6265 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.boolean_class
;
6266 case MONO_TYPE_CHAR
:
6267 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.char_class
;
6269 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.sbyte_class
;
6271 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.byte_class
;
6273 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int16_class
;
6275 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint16_class
;
6277 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int32_class
;
6279 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint32_class
;
6281 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int_class
;
6283 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint_class
;
6285 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int64_class
;
6287 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint64_class
;
6289 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.single_class
;
6291 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.double_class
;
6292 case MONO_TYPE_STRING
:
6293 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.string_class
;
6294 case MONO_TYPE_TYPEDBYREF
:
6295 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.typed_reference_class
;
6296 case MONO_TYPE_ARRAY
:
6297 return mono_bounded_array_class_get (type
->data
.array
->eklass
, type
->data
.array
->rank
, TRUE
);
6299 return mono_ptr_class_get (type
->data
.type
);
6300 case MONO_TYPE_FNPTR
:
6301 return mono_fnptr_class_get (type
->data
.method
);
6302 case MONO_TYPE_SZARRAY
:
6303 return mono_array_class_get (type
->data
.klass
, 1);
6304 case MONO_TYPE_CLASS
:
6305 case MONO_TYPE_VALUETYPE
:
6306 return type
->data
.klass
;
6307 case MONO_TYPE_GENERICINST
:
6308 return mono_generic_class_get_class (type
->data
.generic_class
);
6310 return mono_class_from_generic_parameter (type
->data
.generic_param
, NULL
, FALSE
);
6311 case MONO_TYPE_MVAR
:
6312 return mono_class_from_generic_parameter (type
->data
.generic_param
, NULL
, TRUE
);
6314 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type
->type
);
6315 g_assert_not_reached ();
6322 * mono_type_retrieve_from_typespec
6323 * @image: context where the image is created
6324 * @type_spec: typespec token
6325 * @context: the generic context used to evaluate generic instantiations in
6328 mono_type_retrieve_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, gboolean
*did_inflate
, MonoError
*error
)
6330 MonoType
*t
= mono_type_create_from_typespec (image
, type_spec
);
6332 mono_error_init (error
);
6333 *did_inflate
= FALSE
;
6336 char *name
= mono_class_name_from_token (image
, type_spec
);
6337 char *assembly
= mono_assembly_name_from_token (image
, type_spec
);
6338 mono_error_set_type_load_name (error
, name
, assembly
, "Could not resolve typespec token %08x", type_spec
);
6342 if (context
&& (context
->class_inst
|| context
->method_inst
)) {
6343 MonoType
*inflated
= inflate_generic_type (NULL
, t
, context
, error
);
6345 if (!mono_error_ok (error
))
6350 *did_inflate
= TRUE
;
6357 * mono_class_create_from_typespec
6358 * @image: context where the image is created
6359 * @type_spec: typespec token
6360 * @context: the generic context used to evaluate generic instantiations in
6363 mono_class_create_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, MonoError
*error
)
6366 gboolean inflated
= FALSE
;
6367 MonoType
*t
= mono_type_retrieve_from_typespec (image
, type_spec
, context
, &inflated
, error
);
6368 if (!mono_error_ok (error
))
6370 ret
= mono_class_from_mono_type (t
);
6372 mono_metadata_free_type (t
);
6377 * mono_bounded_array_class_get:
6378 * @element_class: element class
6379 * @rank: the dimension of the array class
6380 * @bounded: whenever the array has non-zero bounds
6382 * Returns: a class object describing the array with element type @element_type and
6386 mono_bounded_array_class_get (MonoClass
*eclass
, guint32 rank
, gboolean bounded
)
6390 MonoClass
*parent
= NULL
;
6391 GSList
*list
, *rootlist
= NULL
;
6394 gboolean corlib_type
= FALSE
;
6396 g_assert (rank
<= 255);
6399 /* bounded only matters for one-dimensional arrays */
6402 image
= eclass
->image
;
6404 if (rank
== 1 && !bounded
) {
6406 * This case is very frequent not just during compilation because of calls
6407 * from mono_class_from_mono_type (), mono_array_new (),
6408 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6410 EnterCriticalSection (&image
->szarray_cache_lock
);
6411 if (!image
->szarray_cache
)
6412 image
->szarray_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
6413 class = g_hash_table_lookup (image
->szarray_cache
, eclass
);
6414 LeaveCriticalSection (&image
->szarray_cache_lock
);
6418 mono_loader_lock ();
6420 mono_loader_lock ();
6422 if (!image
->array_cache
)
6423 image
->array_cache
= g_hash_table_new (mono_aligned_addr_hash
, NULL
);
6425 if ((rootlist
= list
= g_hash_table_lookup (image
->array_cache
, eclass
))) {
6426 for (; list
; list
= list
->next
) {
6428 if ((class->rank
== rank
) && (class->byval_arg
.type
== (((rank
> 1) || bounded
) ? MONO_TYPE_ARRAY
: MONO_TYPE_SZARRAY
))) {
6429 mono_loader_unlock ();
6436 /* for the building corlib use System.Array from it */
6437 if (image
->assembly
&& image
->assembly
->dynamic
&& image
->assembly_name
&& strcmp (image
->assembly_name
, "mscorlib") == 0) {
6438 parent
= mono_class_from_name (image
, "System", "Array");
6441 parent
= mono_defaults
.array_class
;
6442 if (!parent
->inited
)
6443 mono_class_init (parent
);
6446 class = mono_image_alloc0 (image
, sizeof (MonoClass
));
6448 class->image
= image
;
6449 class->name_space
= eclass
->name_space
;
6450 nsize
= strlen (eclass
->name
);
6451 name
= g_malloc (nsize
+ 2 + rank
+ 1);
6452 memcpy (name
, eclass
->name
, nsize
);
6455 memset (name
+ nsize
+ 1, ',', rank
- 1);
6457 name
[nsize
+ rank
] = '*';
6458 name
[nsize
+ rank
+ bounded
] = ']';
6459 name
[nsize
+ rank
+ bounded
+ 1] = 0;
6460 class->name
= mono_image_strdup (image
, name
);
6463 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD
);
6465 classes_size
+= sizeof (MonoClass
);
6467 class->type_token
= 0;
6468 /* all arrays are marked serializable and sealed, bug #42779 */
6469 class->flags
= TYPE_ATTRIBUTE_CLASS
| TYPE_ATTRIBUTE_SERIALIZABLE
| TYPE_ATTRIBUTE_SEALED
| TYPE_ATTRIBUTE_PUBLIC
;
6470 class->parent
= parent
;
6471 class->instance_size
= mono_class_instance_size (class->parent
);
6473 if (eclass
->byval_arg
.type
== MONO_TYPE_TYPEDBYREF
|| eclass
->byval_arg
.type
== MONO_TYPE_VOID
) {
6474 /*Arrays of those two types are invalid.*/
6475 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
6476 } else if (eclass
->enumtype
&& !mono_class_enum_basetype (eclass
)) {
6477 if (!eclass
->ref_info_handle
|| eclass
->wastypebuilder
) {
6478 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6479 g_assert (eclass
->ref_info_handle
&& !eclass
->wastypebuilder
);
6481 /* element_size -1 is ok as this is not an instantitable type*/
6482 class->sizes
.element_size
= -1;
6484 class->sizes
.element_size
= mono_class_array_element_size (eclass
);
6486 mono_class_setup_supertypes (class);
6488 if (eclass
->generic_class
)
6489 mono_class_init (eclass
);
6490 if (!eclass
->size_inited
)
6491 mono_class_setup_fields (eclass
);
6492 if (eclass
->exception_type
) /*FIXME we fail the array type, but we have to let other fields be set.*/
6493 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
6495 class->has_references
= MONO_TYPE_IS_REFERENCE (&eclass
->byval_arg
) || eclass
->has_references
? TRUE
: FALSE
;
6499 if (eclass
->enumtype
)
6500 class->cast_class
= eclass
->element_class
;
6502 class->cast_class
= eclass
;
6504 switch (class->cast_class
->byval_arg
.type
) {
6506 class->cast_class
= mono_defaults
.byte_class
;
6509 class->cast_class
= mono_defaults
.int16_class
;
6512 #if SIZEOF_VOID_P == 4
6516 class->cast_class
= mono_defaults
.int32_class
;
6519 #if SIZEOF_VOID_P == 8
6523 class->cast_class
= mono_defaults
.int64_class
;
6527 class->element_class
= eclass
;
6529 if ((rank
> 1) || bounded
) {
6530 MonoArrayType
*at
= mono_image_alloc0 (image
, sizeof (MonoArrayType
));
6531 class->byval_arg
.type
= MONO_TYPE_ARRAY
;
6532 class->byval_arg
.data
.array
= at
;
6533 at
->eklass
= eclass
;
6535 /* FIXME: complete.... */
6537 class->byval_arg
.type
= MONO_TYPE_SZARRAY
;
6538 class->byval_arg
.data
.klass
= eclass
;
6540 class->this_arg
= class->byval_arg
;
6541 class->this_arg
.byref
= 1;
6546 class->generic_container
= eclass
->generic_container
;
6548 if (rank
== 1 && !bounded
) {
6549 MonoClass
*prev_class
;
6551 EnterCriticalSection (&image
->szarray_cache_lock
);
6552 prev_class
= g_hash_table_lookup (image
->szarray_cache
, eclass
);
6554 /* Someone got in before us */
6557 g_hash_table_insert (image
->szarray_cache
, eclass
, class);
6558 LeaveCriticalSection (&image
->szarray_cache_lock
);
6560 list
= g_slist_append (rootlist
, class);
6561 g_hash_table_insert (image
->array_cache
, eclass
, list
);
6564 mono_loader_unlock ();
6566 mono_profiler_class_loaded (class, MONO_PROFILE_OK
);
6572 * mono_array_class_get:
6573 * @element_class: element class
6574 * @rank: the dimension of the array class
6576 * Returns: a class object describing the array with element type @element_type and
6580 mono_array_class_get (MonoClass
*eclass
, guint32 rank
)
6582 return mono_bounded_array_class_get (eclass
, rank
, FALSE
);
6586 * mono_class_instance_size:
6589 * Returns: the size of an object instance
6592 mono_class_instance_size (MonoClass
*klass
)
6594 if (!klass
->size_inited
)
6595 mono_class_init (klass
);
6597 return klass
->instance_size
;
6601 * mono_class_min_align:
6604 * Returns: minimm alignment requirements
6607 mono_class_min_align (MonoClass
*klass
)
6609 if (!klass
->size_inited
)
6610 mono_class_init (klass
);
6612 return klass
->min_align
;
6616 * mono_class_value_size:
6619 * This function is used for value types, and return the
6620 * space and the alignment to store that kind of value object.
6622 * Returns: the size of a value of kind @klass
6625 mono_class_value_size (MonoClass
*klass
, guint32
*align
)
6629 /* fixme: check disable, because we still have external revereces to
6630 * mscorlib and Dummy Objects
6632 /*g_assert (klass->valuetype);*/
6634 size
= mono_class_instance_size (klass
) - sizeof (MonoObject
);
6637 *align
= klass
->min_align
;
6643 * mono_class_data_size:
6646 * Returns: the size of the static class data
6649 mono_class_data_size (MonoClass
*klass
)
6652 mono_class_init (klass
);
6653 /* This can happen with dynamically created types */
6654 if (!klass
->fields_inited
)
6655 mono_class_setup_fields_locking (klass
);
6657 /* in arrays, sizes.class_size is unioned with element_size
6658 * and arrays have no static fields
6662 return klass
->sizes
.class_size
;
6666 * Auxiliary routine to mono_class_get_field
6668 * Takes a field index instead of a field token.
6670 static MonoClassField
*
6671 mono_class_get_field_idx (MonoClass
*class, int idx
)
6673 mono_class_setup_fields_locking (class);
6674 if (class->exception_type
)
6678 if (class->image
->uncompressed_metadata
) {
6680 * class->field.first points to the FieldPtr table, while idx points into the
6681 * Field table, so we have to do a search.
6683 /*FIXME this is broken for types with multiple fields with the same name.*/
6684 const char *name
= mono_metadata_string_heap (class->image
, mono_metadata_decode_row_col (&class->image
->tables
[MONO_TABLE_FIELD
], idx
, MONO_FIELD_NAME
));
6687 for (i
= 0; i
< class->field
.count
; ++i
)
6688 if (mono_field_get_name (&class->fields
[i
]) == name
)
6689 return &class->fields
[i
];
6690 g_assert_not_reached ();
6692 if (class->field
.count
) {
6693 if ((idx
>= class->field
.first
) && (idx
< class->field
.first
+ class->field
.count
)){
6694 return &class->fields
[idx
- class->field
.first
];
6698 class = class->parent
;
6704 * mono_class_get_field:
6705 * @class: the class to lookup the field.
6706 * @field_token: the field token
6708 * Returns: A MonoClassField representing the type and offset of
6709 * the field, or a NULL value if the field does not belong to this
6713 mono_class_get_field (MonoClass
*class, guint32 field_token
)
6715 int idx
= mono_metadata_token_index (field_token
);
6717 g_assert (mono_metadata_token_code (field_token
) == MONO_TOKEN_FIELD_DEF
);
6719 return mono_class_get_field_idx (class, idx
- 1);
6723 * mono_class_get_field_from_name:
6724 * @klass: the class to lookup the field.
6725 * @name: the field name
6727 * Search the class @klass and it's parents for a field with the name @name.
6729 * Returns: the MonoClassField pointer of the named field or NULL
6732 mono_class_get_field_from_name (MonoClass
*klass
, const char *name
)
6734 return mono_class_get_field_from_name_full (klass
, name
, NULL
);
6738 * mono_class_get_field_from_name_full:
6739 * @klass: the class to lookup the field.
6740 * @name: the field name
6741 * @type: the type of the fields. This optional.
6743 * Search the class @klass and it's parents for a field with the name @name and type @type.
6745 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6746 * of its generic type definition.
6748 * Returns: the MonoClassField pointer of the named field or NULL
6751 mono_class_get_field_from_name_full (MonoClass
*klass
, const char *name
, MonoType
*type
)
6755 mono_class_setup_fields_locking (klass
);
6756 if (klass
->exception_type
)
6760 for (i
= 0; i
< klass
->field
.count
; ++i
) {
6761 MonoClassField
*field
= &klass
->fields
[i
];
6763 if (strcmp (name
, mono_field_get_name (field
)) != 0)
6767 MonoType
*field_type
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
)->type
;
6768 if (!mono_metadata_type_equal_full (type
, field_type
, TRUE
))
6773 klass
= klass
->parent
;
6779 * mono_class_get_field_token:
6780 * @field: the field we need the token of
6782 * Get the token of a field. Note that the tokesn is only valid for the image
6783 * the field was loaded from. Don't use this function for fields in dynamic types.
6785 * Returns: the token representing the field in the image it was loaded from.
6788 mono_class_get_field_token (MonoClassField
*field
)
6790 MonoClass
*klass
= field
->parent
;
6793 mono_class_setup_fields_locking (klass
);
6798 for (i
= 0; i
< klass
->field
.count
; ++i
) {
6799 if (&klass
->fields
[i
] == field
) {
6800 int idx
= klass
->field
.first
+ i
+ 1;
6802 if (klass
->image
->uncompressed_metadata
)
6803 idx
= mono_metadata_translate_token_index (klass
->image
, MONO_TABLE_FIELD
, idx
);
6804 return mono_metadata_make_token (MONO_TABLE_FIELD
, idx
);
6807 klass
= klass
->parent
;
6810 g_assert_not_reached ();
6815 mono_field_get_index (MonoClassField
*field
)
6817 int index
= field
- field
->parent
->fields
;
6819 g_assert (index
>= 0 && index
< field
->parent
->field
.count
);
6825 * mono_class_get_field_default_value:
6827 * Return the default value of the field as a pointer into the metadata blob.
6830 mono_class_get_field_default_value (MonoClassField
*field
, MonoTypeEnum
*def_type
)
6833 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
6835 MonoClass
*klass
= field
->parent
;
6837 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
);
6839 if (!klass
->ext
|| !klass
->ext
->field_def_values
) {
6840 mono_loader_lock ();
6841 mono_class_alloc_ext (klass
);
6842 if (!klass
->ext
->field_def_values
)
6843 klass
->ext
->field_def_values
= mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * klass
->field
.count
);
6844 mono_loader_unlock ();
6847 field_index
= mono_field_get_index (field
);
6849 if (!klass
->ext
->field_def_values
[field_index
].data
) {
6850 cindex
= mono_metadata_get_constant_index (field
->parent
->image
, mono_class_get_field_token (field
), 0);
6854 g_assert (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
));
6856 mono_metadata_decode_row (&field
->parent
->image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
6857 klass
->ext
->field_def_values
[field_index
].def_type
= constant_cols
[MONO_CONSTANT_TYPE
];
6858 klass
->ext
->field_def_values
[field_index
].data
= (gpointer
)mono_metadata_blob_heap (field
->parent
->image
, constant_cols
[MONO_CONSTANT_VALUE
]);
6861 *def_type
= klass
->ext
->field_def_values
[field_index
].def_type
;
6862 return klass
->ext
->field_def_values
[field_index
].data
;
6866 mono_property_get_index (MonoProperty
*prop
)
6868 int index
= prop
- prop
->parent
->ext
->properties
;
6870 g_assert (index
>= 0 && index
< prop
->parent
->ext
->property
.count
);
6876 * mono_class_get_property_default_value:
6878 * Return the default value of the field as a pointer into the metadata blob.
6881 mono_class_get_property_default_value (MonoProperty
*property
, MonoTypeEnum
*def_type
)
6884 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
6885 MonoClass
*klass
= property
->parent
;
6887 g_assert (property
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
);
6889 * We don't cache here because it is not used by C# so it's quite rare, but
6890 * we still do the lookup in klass->ext because that is where the data
6891 * is stored for dynamic assemblies.
6894 if (klass
->image
->dynamic
) {
6895 int prop_index
= mono_property_get_index (property
);
6896 if (klass
->ext
->prop_def_values
&& klass
->ext
->prop_def_values
[prop_index
].data
) {
6897 *def_type
= klass
->ext
->prop_def_values
[prop_index
].def_type
;
6898 return klass
->ext
->prop_def_values
[prop_index
].data
;
6902 cindex
= mono_metadata_get_constant_index (klass
->image
, mono_class_get_property_token (property
), 0);
6906 mono_metadata_decode_row (&klass
->image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
6907 *def_type
= constant_cols
[MONO_CONSTANT_TYPE
];
6908 return (gpointer
)mono_metadata_blob_heap (klass
->image
, constant_cols
[MONO_CONSTANT_VALUE
]);
6912 mono_class_get_event_token (MonoEvent
*event
)
6914 MonoClass
*klass
= event
->parent
;
6919 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
6920 if (&klass
->ext
->events
[i
] == event
)
6921 return mono_metadata_make_token (MONO_TABLE_EVENT
, klass
->ext
->event
.first
+ i
+ 1);
6924 klass
= klass
->parent
;
6927 g_assert_not_reached ();
6932 mono_class_get_property_from_name (MonoClass
*klass
, const char *name
)
6936 gpointer iter
= NULL
;
6937 while ((p
= mono_class_get_properties (klass
, &iter
))) {
6938 if (! strcmp (name
, p
->name
))
6941 klass
= klass
->parent
;
6947 mono_class_get_property_token (MonoProperty
*prop
)
6949 MonoClass
*klass
= prop
->parent
;
6953 gpointer iter
= NULL
;
6954 while ((p
= mono_class_get_properties (klass
, &iter
))) {
6955 if (&klass
->ext
->properties
[i
] == prop
)
6956 return mono_metadata_make_token (MONO_TABLE_PROPERTY
, klass
->ext
->property
.first
+ i
+ 1);
6960 klass
= klass
->parent
;
6963 g_assert_not_reached ();
6968 mono_class_name_from_token (MonoImage
*image
, guint32 type_token
)
6970 const char *name
, *nspace
;
6972 return g_strdup_printf ("DynamicType 0x%08x", type_token
);
6974 switch (type_token
& 0xff000000){
6975 case MONO_TOKEN_TYPE_DEF
: {
6976 guint32 cols
[MONO_TYPEDEF_SIZE
];
6977 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
6978 guint tidx
= mono_metadata_token_index (type_token
);
6980 if (tidx
> tt
->rows
)
6981 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
6983 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
6984 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
6985 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
6986 if (strlen (nspace
) == 0)
6987 return g_strdup_printf ("%s", name
);
6989 return g_strdup_printf ("%s.%s", nspace
, name
);
6992 case MONO_TOKEN_TYPE_REF
: {
6994 guint32 cols
[MONO_TYPEREF_SIZE
];
6995 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
6996 guint tidx
= mono_metadata_token_index (type_token
);
6999 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
7001 if (!mono_verifier_verify_typeref_row (image
, tidx
- 1, &error
)) {
7002 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (&error
));
7003 mono_error_cleanup (&error
);
7007 mono_metadata_decode_row (t
, tidx
-1, cols
, MONO_TYPEREF_SIZE
);
7008 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
7009 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
7010 if (strlen (nspace
) == 0)
7011 return g_strdup_printf ("%s", name
);
7013 return g_strdup_printf ("%s.%s", nspace
, name
);
7016 case MONO_TOKEN_TYPE_SPEC
:
7017 return g_strdup_printf ("Typespec 0x%08x", type_token
);
7019 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
7024 mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
)
7027 return g_strdup_printf ("DynamicAssembly %s", image
->name
);
7029 switch (type_token
& 0xff000000){
7030 case MONO_TOKEN_TYPE_DEF
:
7031 if (image
->assembly
)
7032 return mono_stringify_assembly_name (&image
->assembly
->aname
);
7033 else if (image
->assembly_name
)
7034 return g_strdup (image
->assembly_name
);
7035 return g_strdup_printf ("%s", image
->name
? image
->name
: "[Could not resolve assembly name");
7036 case MONO_TOKEN_TYPE_REF
: {
7038 MonoAssemblyName aname
;
7039 guint32 cols
[MONO_TYPEREF_SIZE
];
7040 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
7041 guint32 idx
= mono_metadata_token_index (type_token
);
7044 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
7046 if (!mono_verifier_verify_typeref_row (image
, idx
- 1, &error
)) {
7047 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (&error
));
7048 mono_error_cleanup (&error
);
7051 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPEREF_SIZE
);
7053 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLTION_SCOPE_BITS
;
7054 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLTION_SCOPE_MASK
) {
7055 case MONO_RESOLTION_SCOPE_MODULE
:
7057 return g_strdup ("");
7058 case MONO_RESOLTION_SCOPE_MODULEREF
:
7060 return g_strdup ("");
7061 case MONO_RESOLTION_SCOPE_TYPEREF
:
7063 return g_strdup ("");
7064 case MONO_RESOLTION_SCOPE_ASSEMBLYREF
:
7065 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
7066 return mono_stringify_assembly_name (&aname
);
7068 g_assert_not_reached ();
7072 case MONO_TOKEN_TYPE_SPEC
:
7074 return g_strdup ("");
7076 g_assert_not_reached ();
7083 * mono_class_get_full:
7084 * @image: the image where the class resides
7085 * @type_token: the token for the class
7086 * @context: the generic context used to evaluate generic instantiations in
7088 * Returns: the MonoClass that represents @type_token in @image
7091 mono_class_get_full (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
)
7094 MonoClass
*class = NULL
;
7096 if (image
->dynamic
) {
7097 int table
= mono_metadata_token_table (type_token
);
7099 if (table
!= MONO_TABLE_TYPEDEF
&& table
!= MONO_TABLE_TYPEREF
&& table
!= MONO_TABLE_TYPESPEC
) {
7100 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7103 return mono_lookup_dynamic_token (image
, type_token
, context
);
7106 switch (type_token
& 0xff000000){
7107 case MONO_TOKEN_TYPE_DEF
:
7108 class = mono_class_create_from_typedef (image
, type_token
, &error
);
7109 if (!mono_error_ok (&error
)) {
7110 mono_loader_set_error_from_mono_error (&error
);
7111 /*FIXME don't swallow the error message*/
7112 mono_error_cleanup (&error
);
7116 case MONO_TOKEN_TYPE_REF
:
7117 class = mono_class_from_typeref (image
, type_token
);
7119 case MONO_TOKEN_TYPE_SPEC
:
7120 class = mono_class_create_from_typespec (image
, type_token
, context
, &error
);
7121 if (!mono_error_ok (&error
)) {
7122 /*FIXME don't swallow the error message*/
7123 mono_error_cleanup (&error
);
7127 g_warning ("unknown token type %x", type_token
& 0xff000000);
7128 g_assert_not_reached ();
7132 char *name
= mono_class_name_from_token (image
, type_token
);
7133 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
7134 mono_loader_set_error_type_load (name
, assembly
);
7144 * mono_type_get_full:
7145 * @image: the image where the type resides
7146 * @type_token: the token for the type
7147 * @context: the generic context used to evaluate generic instantiations in
7149 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7151 * Returns: the MonoType that represents @type_token in @image
7154 mono_type_get_full (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
)
7157 MonoType
*type
= NULL
;
7158 gboolean inflated
= FALSE
;
7160 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7162 return mono_class_get_type (mono_lookup_dynamic_token (image
, type_token
, context
));
7164 if ((type_token
& 0xff000000) != MONO_TOKEN_TYPE_SPEC
) {
7165 MonoClass
*class = mono_class_get_full (image
, type_token
, context
);
7166 return class ? mono_class_get_type (class) : NULL
;
7169 type
= mono_type_retrieve_from_typespec (image
, type_token
, context
, &inflated
, &error
);
7171 if (!mono_error_ok (&error
)) {
7172 /*FIXME don't swalloc the error message.*/
7173 char *name
= mono_class_name_from_token (image
, type_token
);
7174 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
7176 g_warning ("Error loading type %s from %s due to %s", name
, assembly
, mono_error_get_message (&error
));
7178 mono_error_cleanup (&error
);
7179 mono_loader_set_error_type_load (name
, assembly
);
7184 MonoType
*tmp
= type
;
7185 type
= mono_class_get_type (mono_class_from_mono_type (type
));
7186 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7187 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7188 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7190 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7192 if (type
->type
!= tmp
->type
)
7195 mono_metadata_free_type (tmp
);
7202 mono_class_get (MonoImage
*image
, guint32 type_token
)
7204 return mono_class_get_full (image
, type_token
, NULL
);
7208 * mono_image_init_name_cache:
7210 * Initializes the class name cache stored in image->name_cache.
7212 * LOCKING: Acquires the corresponding image lock.
7215 mono_image_init_name_cache (MonoImage
*image
)
7217 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
7218 guint32 cols
[MONO_TYPEDEF_SIZE
];
7221 guint32 i
, visib
, nspace_index
;
7222 GHashTable
*name_cache2
, *nspace_table
;
7224 mono_image_lock (image
);
7226 if (image
->name_cache
) {
7227 mono_image_unlock (image
);
7231 image
->name_cache
= g_hash_table_new (g_str_hash
, g_str_equal
);
7233 if (image
->dynamic
) {
7234 mono_image_unlock (image
);
7238 /* Temporary hash table to avoid lookups in the nspace_table */
7239 name_cache2
= g_hash_table_new (NULL
, NULL
);
7241 for (i
= 1; i
<= t
->rows
; ++i
) {
7242 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
7243 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
7245 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7246 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7248 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
7250 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
7251 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
7253 nspace_index
= cols
[MONO_TYPEDEF_NAMESPACE
];
7254 nspace_table
= g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
7255 if (!nspace_table
) {
7256 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
7257 g_hash_table_insert (image
->name_cache
, (char*)nspace
, nspace_table
);
7258 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
7261 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (i
));
7264 /* Load type names from EXPORTEDTYPES table */
7266 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
7267 guint32 cols
[MONO_EXP_TYPE_SIZE
];
7270 for (i
= 0; i
< t
->rows
; ++i
) {
7271 mono_metadata_decode_row (t
, i
, cols
, MONO_EXP_TYPE_SIZE
);
7272 name
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAME
]);
7273 nspace
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAMESPACE
]);
7275 nspace_index
= cols
[MONO_EXP_TYPE_NAMESPACE
];
7276 nspace_table
= g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
7277 if (!nspace_table
) {
7278 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
7279 g_hash_table_insert (image
->name_cache
, (char*)nspace
, nspace_table
);
7280 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
7283 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE
, i
+ 1)));
7287 g_hash_table_destroy (name_cache2
);
7288 mono_image_unlock (image
);
7291 /*FIXME Only dynamic assemblies should allow this operation.*/
7293 mono_image_add_to_name_cache (MonoImage
*image
, const char *nspace
,
7294 const char *name
, guint32 index
)
7296 GHashTable
*nspace_table
;
7297 GHashTable
*name_cache
;
7300 mono_image_lock (image
);
7302 if (!image
->name_cache
)
7303 mono_image_init_name_cache (image
);
7305 name_cache
= image
->name_cache
;
7306 if (!(nspace_table
= g_hash_table_lookup (name_cache
, nspace
))) {
7307 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
7308 g_hash_table_insert (name_cache
, (char *)nspace
, (char *)nspace_table
);
7311 if ((old_index
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, (char*) name
))))
7312 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index
, image
->name
, nspace
, name
);
7314 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (index
));
7316 mono_image_unlock (image
);
7325 find_nocase (gpointer key
, gpointer value
, gpointer user_data
)
7327 char *name
= (char*)key
;
7328 FindUserData
*data
= (FindUserData
*)user_data
;
7330 if (!data
->value
&& (mono_utf8_strcasecmp (name
, (char*)data
->key
) == 0))
7331 data
->value
= value
;
7335 * mono_class_from_name_case:
7336 * @image: The MonoImage where the type is looked up in
7337 * @name_space: the type namespace
7338 * @name: the type short name.
7340 * Obtains a MonoClass with a given namespace and a given name which
7341 * is located in the given MonoImage. The namespace and name
7342 * lookups are case insensitive.
7345 mono_class_from_name_case (MonoImage
*image
, const char* name_space
, const char *name
)
7347 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
7348 guint32 cols
[MONO_TYPEDEF_SIZE
];
7353 if (image
->dynamic
) {
7355 FindUserData user_data
;
7357 mono_image_lock (image
);
7359 if (!image
->name_cache
)
7360 mono_image_init_name_cache (image
);
7362 user_data
.key
= name_space
;
7363 user_data
.value
= NULL
;
7364 g_hash_table_foreach (image
->name_cache
, find_nocase
, &user_data
);
7366 if (user_data
.value
) {
7367 GHashTable
*nspace_table
= (GHashTable
*)user_data
.value
;
7369 user_data
.key
= name
;
7370 user_data
.value
= NULL
;
7372 g_hash_table_foreach (nspace_table
, find_nocase
, &user_data
);
7374 if (user_data
.value
)
7375 token
= GPOINTER_TO_UINT (user_data
.value
);
7378 mono_image_unlock (image
);
7381 return mono_class_get (image
, MONO_TOKEN_TYPE_DEF
| token
);
7387 /* add a cache if needed */
7388 for (i
= 1; i
<= t
->rows
; ++i
) {
7389 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
7390 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
7392 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7393 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7395 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
7397 n
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
7398 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
7399 if (mono_utf8_strcasecmp (n
, name
) == 0 && mono_utf8_strcasecmp (nspace
, name_space
) == 0)
7400 return mono_class_get (image
, MONO_TOKEN_TYPE_DEF
| i
);
7406 return_nested_in (MonoClass
*class, char *nested
)
7409 char *s
= strchr (nested
, '/');
7410 gpointer iter
= NULL
;
7417 while ((found
= mono_class_get_nested_types (class, &iter
))) {
7418 if (strcmp (found
->name
, nested
) == 0) {
7420 return return_nested_in (found
, s
);
7428 search_modules (MonoImage
*image
, const char *name_space
, const char *name
)
7430 MonoTableInfo
*file_table
= &image
->tables
[MONO_TABLE_FILE
];
7431 MonoImage
*file_image
;
7436 * The EXPORTEDTYPES table only contains public types, so have to search the
7438 * Note: image->modules contains the contents of the MODULEREF table, while
7439 * the real module list is in the FILE table.
7441 for (i
= 0; i
< file_table
->rows
; i
++) {
7442 guint32 cols
[MONO_FILE_SIZE
];
7443 mono_metadata_decode_row (file_table
, i
, cols
, MONO_FILE_SIZE
);
7444 if (cols
[MONO_FILE_FLAGS
] == FILE_CONTAINS_NO_METADATA
)
7447 file_image
= mono_image_load_file_for_image (image
, i
+ 1);
7449 class = mono_class_from_name (file_image
, name_space
, name
);
7459 * mono_class_from_name:
7460 * @image: The MonoImage where the type is looked up in
7461 * @name_space: the type namespace
7462 * @name: the type short name.
7464 * Obtains a MonoClass with a given namespace and a given name which
7465 * is located in the given MonoImage.
7467 * To reference nested classes, use the "/" character as a separator.
7468 * For example use "Foo/Bar" to reference the class Bar that is nested
7469 * inside Foo, like this: "class Foo { class Bar {} }".
7472 mono_class_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
7474 GHashTable
*nspace_table
;
7475 MonoImage
*loaded_image
;
7482 if ((nested
= strchr (name
, '/'))) {
7483 int pos
= nested
- name
;
7484 int len
= strlen (name
);
7487 memcpy (buf
, name
, len
+ 1);
7489 nested
= buf
+ pos
+ 1;
7493 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7494 if (get_class_from_name
&& image
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
== 0) {
7495 gboolean res
= get_class_from_name (image
, name_space
, name
, &class);
7498 class = search_modules (image
, name_space
, name
);
7500 return class ? return_nested_in (class, nested
) : NULL
;
7506 mono_image_lock (image
);
7508 if (!image
->name_cache
)
7509 mono_image_init_name_cache (image
);
7511 nspace_table
= g_hash_table_lookup (image
->name_cache
, name_space
);
7514 token
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, name
));
7516 mono_image_unlock (image
);
7518 if (!token
&& image
->dynamic
&& image
->modules
) {
7519 /* Search modules as well */
7520 for (i
= 0; i
< image
->module_count
; ++i
) {
7521 MonoImage
*module
= image
->modules
[i
];
7523 class = mono_class_from_name (module
, name_space
, name
);
7530 class = search_modules (image
, name_space
, name
);
7538 if (mono_metadata_token_table (token
) == MONO_TABLE_EXPORTEDTYPE
) {
7539 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
7540 guint32 cols
[MONO_EXP_TYPE_SIZE
];
7543 idx
= mono_metadata_token_index (token
);
7545 mono_metadata_decode_row (t
, idx
- 1, cols
, MONO_EXP_TYPE_SIZE
);
7547 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
7548 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
) {
7549 loaded_image
= mono_assembly_load_module (image
->assembly
, impl
>> MONO_IMPLEMENTATION_BITS
);
7552 class = mono_class_from_name (loaded_image
, name_space
, name
);
7554 return return_nested_in (class, nested
);
7556 } else if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_ASSEMBLYREF
) {
7557 guint32 assembly_idx
;
7559 assembly_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
7561 mono_assembly_load_reference (image
, assembly_idx
- 1);
7562 g_assert (image
->references
[assembly_idx
- 1]);
7563 if (image
->references
[assembly_idx
- 1] == (gpointer
)-1)
7566 /* FIXME: Cycle detection */
7567 return mono_class_from_name (image
->references
[assembly_idx
- 1]->image
, name_space
, name
);
7569 g_error ("not yet implemented");
7573 token
= MONO_TOKEN_TYPE_DEF
| token
;
7575 class = mono_class_get (image
, token
);
7577 return return_nested_in (class, nested
);
7582 * mono_class_is_subclass_of:
7583 * @klass: class to probe if it is a subclass of another one
7584 * @klassc: the class we suspect is the base class
7585 * @check_interfaces: whether we should perform interface checks
7587 * This method determines whether @klass is a subclass of @klassc.
7589 * If the @check_interfaces flag is set, then if @klassc is an interface
7590 * this method return true if the @klass implements the interface or
7591 * if @klass is an interface, if one of its base classes is @klass.
7593 * If @check_interfaces is false then, then if @klass is not an interface
7594 * then it returns true if the @klass is a subclass of @klassc.
7596 * if @klass is an interface and @klassc is System.Object, then this function
7601 mono_class_is_subclass_of (MonoClass
*klass
, MonoClass
*klassc
,
7602 gboolean check_interfaces
)
7604 /*FIXME test for interfaces with variant generic arguments*/
7606 if (check_interfaces
&& MONO_CLASS_IS_INTERFACE (klassc
) && !MONO_CLASS_IS_INTERFACE (klass
)) {
7607 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass
, klassc
->interface_id
))
7609 } else if (check_interfaces
&& MONO_CLASS_IS_INTERFACE (klassc
) && MONO_CLASS_IS_INTERFACE (klass
)) {
7612 for (i
= 0; i
< klass
->interface_count
; i
++) {
7613 MonoClass
*ic
= klass
->interfaces
[i
];
7618 if (!MONO_CLASS_IS_INTERFACE (klass
) && mono_class_has_parent (klass
, klassc
))
7623 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7626 if (klassc
== mono_defaults
.object_class
)
7633 mono_type_is_generic_argument (MonoType
*type
)
7635 return type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
;
7639 mono_class_has_variant_generic_params (MonoClass
*klass
)
7642 MonoGenericContainer
*container
;
7644 if (!klass
->generic_class
)
7647 container
= klass
->generic_class
->container_class
->generic_container
;
7649 for (i
= 0; i
< container
->type_argc
; ++i
)
7650 if (mono_generic_container_get_param_info (container
, i
)->flags
& (MONO_GEN_PARAM_VARIANT
|MONO_GEN_PARAM_COVARIANT
))
7657 mono_gparam_is_reference_conversible (MonoClass
*target
, MonoClass
*candidate
, gboolean check_for_reference_conv
)
7659 if (target
== candidate
)
7662 if (check_for_reference_conv
&&
7663 mono_type_is_generic_argument (&target
->byval_arg
) &&
7664 mono_type_is_generic_argument (&candidate
->byval_arg
)) {
7665 MonoGenericParam
*gparam
= candidate
->byval_arg
.data
.generic_param
;
7666 MonoGenericParamInfo
*pinfo
= mono_generic_param_info (gparam
);
7668 if (!pinfo
|| (pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0)
7671 if (!mono_class_is_assignable_from (target
, candidate
))
7677 * @container the generic container from the GTD
7678 * @klass: the class to be assigned to
7679 * @oklass: the source class
7681 * Both klass and oklass must be instances of the same generic interface.
7682 * Return true if @klass can be assigned to a @klass variable
7685 mono_class_is_variant_compatible (MonoClass
*klass
, MonoClass
*oklass
, gboolean check_for_reference_conv
)
7688 MonoType
**klass_argv
, **oklass_argv
;
7689 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
7690 MonoGenericContainer
*container
= klass_gtd
->generic_container
;
7692 if (klass
== oklass
)
7695 /*Viable candidates are instances of the same generic interface*/
7696 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
7699 klass_argv
= &klass
->generic_class
->context
.class_inst
->type_argv
[0];
7700 oklass_argv
= &oklass
->generic_class
->context
.class_inst
->type_argv
[0];
7702 for (j
= 0; j
< container
->type_argc
; ++j
) {
7703 MonoClass
*param1_class
= mono_class_from_mono_type (klass_argv
[j
]);
7704 MonoClass
*param2_class
= mono_class_from_mono_type (oklass_argv
[j
]);
7706 if (param1_class
->valuetype
!= param2_class
->valuetype
|| (param1_class
->valuetype
&& param1_class
!= param2_class
))
7710 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7711 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7713 if (param1_class
!= param2_class
) {
7714 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
7715 if (!mono_gparam_is_reference_conversible (param1_class
, param2_class
, check_for_reference_conv
))
7717 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
7718 if (!mono_gparam_is_reference_conversible (param2_class
, param1_class
, check_for_reference_conv
))
7728 mono_gparam_is_assignable_from (MonoClass
*target
, MonoClass
*candidate
)
7730 MonoGenericParam
*gparam
, *ogparam
;
7731 MonoGenericParamInfo
*tinfo
, *cinfo
;
7732 MonoClass
**candidate_class
;
7733 gboolean class_constraint_satisfied
, valuetype_constraint_satisfied
;
7736 if (target
== candidate
)
7738 if (target
->byval_arg
.type
!= candidate
->byval_arg
.type
)
7741 gparam
= target
->byval_arg
.data
.generic_param
;
7742 ogparam
= candidate
->byval_arg
.data
.generic_param
;
7743 tinfo
= mono_generic_param_info (gparam
);
7744 cinfo
= mono_generic_param_info (ogparam
);
7746 class_constraint_satisfied
= FALSE
;
7747 valuetype_constraint_satisfied
= FALSE
;
7749 /*candidate must have a super set of target's special constraints*/
7750 tmask
= tinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
7751 cmask
= cinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
7753 if (cinfo
->constraints
) {
7754 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
7755 MonoClass
*cc
= *candidate_class
;
7757 if (mono_type_is_reference (&cc
->byval_arg
) && !MONO_CLASS_IS_INTERFACE (cc
))
7758 class_constraint_satisfied
= TRUE
;
7759 else if (!mono_type_is_reference (&cc
->byval_arg
) && !MONO_CLASS_IS_INTERFACE (cc
))
7760 valuetype_constraint_satisfied
= TRUE
;
7763 class_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) != 0;
7764 valuetype_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0;
7766 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) && !class_constraint_satisfied
)
7768 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) && !valuetype_constraint_satisfied
)
7770 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) && !((cmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) ||
7771 valuetype_constraint_satisfied
)) {
7776 /*candidate type constraints must be a superset of target's*/
7777 if (tinfo
->constraints
) {
7778 MonoClass
**target_class
;
7779 for (target_class
= tinfo
->constraints
; *target_class
; ++target_class
) {
7780 MonoClass
*tc
= *target_class
;
7783 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7784 * check it's constraints since it satisfy the constraint by itself.
7786 if (mono_metadata_type_equal (&tc
->byval_arg
, &candidate
->byval_arg
))
7789 if (!cinfo
->constraints
)
7792 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
7793 MonoClass
*cc
= *candidate_class
;
7795 if (mono_class_is_assignable_from (tc
, cc
))
7799 * This happens when we have the following:
7801 * Bar<K> where K : IFace
7802 * Foo<T, U> where T : U where U : IFace
7804 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7807 if (mono_type_is_generic_argument (&cc
->byval_arg
)) {
7808 if (mono_gparam_is_assignable_from (target
, cc
))
7812 if (!*candidate_class
)
7817 /*candidate itself must have a constraint that satisfy target*/
7818 if (cinfo
->constraints
) {
7819 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
7820 MonoClass
*cc
= *candidate_class
;
7821 if (mono_class_is_assignable_from (target
, cc
))
7829 * mono_class_is_assignable_from:
7830 * @klass: the class to be assigned to
7831 * @oklass: the source class
7833 * Return: true if an instance of object oklass can be assigned to an
7834 * instance of object @klass
7837 mono_class_is_assignable_from (MonoClass
*klass
, MonoClass
*oklass
)
7839 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7841 mono_class_init (klass
);
7843 if (!oklass
->inited
)
7844 mono_class_init (oklass
);
7846 if (klass
->exception_type
|| oklass
->exception_type
)
7849 if (mono_type_is_generic_argument (&klass
->byval_arg
)) {
7850 if (!mono_type_is_generic_argument (&oklass
->byval_arg
))
7852 return mono_gparam_is_assignable_from (klass
, oklass
);
7855 if (MONO_CLASS_IS_INTERFACE (klass
)) {
7856 if ((oklass
->byval_arg
.type
== MONO_TYPE_VAR
) || (oklass
->byval_arg
.type
== MONO_TYPE_MVAR
)) {
7857 MonoGenericParam
*gparam
= oklass
->byval_arg
.data
.generic_param
;
7858 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
7862 for (i
= 0; constraints
[i
]; ++i
) {
7863 if (mono_class_is_assignable_from (klass
, constraints
[i
]))
7871 /* interface_offsets might not be set for dynamic classes */
7872 if (oklass
->ref_info_handle
&& !oklass
->interface_bitmap
)
7874 * oklass might be a generic type parameter but they have
7875 * interface_offsets set.
7877 return mono_reflection_call_is_assignable_to (oklass
, klass
);
7878 if (!oklass
->interface_bitmap
)
7879 /* Happens with generic instances of not-yet created dynamic types */
7881 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass
, klass
->interface_id
))
7884 if (mono_class_has_variant_generic_params (klass
)) {
7887 mono_class_setup_interfaces (oklass
, &error
);
7888 if (!mono_error_ok (&error
)) {
7889 mono_error_cleanup (&error
);
7893 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7894 for (i
= 0; i
< oklass
->interface_offsets_count
; ++i
) {
7895 MonoClass
*iface
= oklass
->interfaces_packed
[i
];
7897 if (mono_class_is_variant_compatible (klass
, iface
, FALSE
))
7902 } else if (klass
->delegate
) {
7903 if (mono_class_has_variant_generic_params (klass
) && mono_class_is_variant_compatible (klass
, oklass
, FALSE
))
7905 }else if (klass
->rank
) {
7906 MonoClass
*eclass
, *eoclass
;
7908 if (oklass
->rank
!= klass
->rank
)
7911 /* vectors vs. one dimensional arrays */
7912 if (oklass
->byval_arg
.type
!= klass
->byval_arg
.type
)
7915 eclass
= klass
->cast_class
;
7916 eoclass
= oklass
->cast_class
;
7919 * a is b does not imply a[] is b[] when a is a valuetype, and
7920 * b is a reference type.
7923 if (eoclass
->valuetype
) {
7924 if ((eclass
== mono_defaults
.enum_class
) ||
7925 (eclass
== mono_defaults
.enum_class
->parent
) ||
7926 (eclass
== mono_defaults
.object_class
))
7930 return mono_class_is_assignable_from (klass
->cast_class
, oklass
->cast_class
);
7931 } else if (mono_class_is_nullable (klass
)) {
7932 if (mono_class_is_nullable (oklass
))
7933 return mono_class_is_assignable_from (klass
->cast_class
, oklass
->cast_class
);
7935 return mono_class_is_assignable_from (klass
->cast_class
, oklass
);
7936 } else if (klass
== mono_defaults
.object_class
)
7939 return mono_class_has_parent (oklass
, klass
);
7942 /*Check if @oklass is variant compatible with @klass.*/
7944 mono_class_is_variant_compatible_slow (MonoClass
*klass
, MonoClass
*oklass
)
7947 MonoType
**klass_argv
, **oklass_argv
;
7948 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
7949 MonoGenericContainer
*container
= klass_gtd
->generic_container
;
7951 /*Viable candidates are instances of the same generic interface*/
7952 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
7955 klass_argv
= &klass
->generic_class
->context
.class_inst
->type_argv
[0];
7956 oklass_argv
= &oklass
->generic_class
->context
.class_inst
->type_argv
[0];
7958 for (j
= 0; j
< container
->type_argc
; ++j
) {
7959 MonoClass
*param1_class
= mono_class_from_mono_type (klass_argv
[j
]);
7960 MonoClass
*param2_class
= mono_class_from_mono_type (oklass_argv
[j
]);
7962 if (param1_class
->valuetype
!= param2_class
->valuetype
)
7966 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7967 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7969 if (param1_class
!= param2_class
) {
7970 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
7971 if (!mono_class_is_assignable_from_slow (param1_class
, param2_class
))
7973 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
7974 if (!mono_class_is_assignable_from_slow (param2_class
, param1_class
))
7982 /*Check if @candidate implements the interface @target*/
7984 mono_class_implement_interface_slow (MonoClass
*target
, MonoClass
*candidate
)
7988 gboolean is_variant
= mono_class_has_variant_generic_params (target
);
7990 if (is_variant
&& MONO_CLASS_IS_INTERFACE (candidate
)) {
7991 if (mono_class_is_variant_compatible_slow (target
, candidate
))
7996 if (candidate
== target
)
7999 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8000 if (candidate
->image
->dynamic
&& !candidate
->wastypebuilder
) {
8001 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info (candidate
);
8003 if (tb
&& tb
->interfaces
) {
8004 for (j
= mono_array_length (tb
->interfaces
) - 1; j
>= 0; --j
) {
8005 MonoReflectionType
*iface
= mono_array_get (tb
->interfaces
, MonoReflectionType
*, j
);
8006 MonoClass
*iface_class
;
8008 /* we can't realize the type here since it can do pretty much anything. */
8011 iface_class
= mono_class_from_mono_type (iface
->type
);
8012 if (iface_class
== target
)
8014 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, iface_class
))
8016 if (mono_class_implement_interface_slow (target
, iface_class
))
8021 /*setup_interfaces don't mono_class_init anything*/
8022 /*FIXME this doesn't handle primitive type arrays.
8023 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8024 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8026 mono_class_setup_interfaces (candidate
, &error
);
8027 if (!mono_error_ok (&error
)) {
8028 mono_error_cleanup (&error
);
8032 for (i
= 0; i
< candidate
->interface_count
; ++i
) {
8033 if (candidate
->interfaces
[i
] == target
)
8036 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, candidate
->interfaces
[i
]))
8039 if (mono_class_implement_interface_slow (target
, candidate
->interfaces
[i
]))
8043 candidate
= candidate
->parent
;
8044 } while (candidate
);
8050 * Check if @oklass can be assigned to @klass.
8051 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8054 mono_class_is_assignable_from_slow (MonoClass
*target
, MonoClass
*candidate
)
8056 if (candidate
== target
)
8058 if (target
== mono_defaults
.object_class
)
8061 if (mono_class_has_parent (candidate
, target
))
8064 /*If target is not an interface there is no need to check them.*/
8065 if (MONO_CLASS_IS_INTERFACE (target
))
8066 return mono_class_implement_interface_slow (target
, candidate
);
8068 if (target
->delegate
&& mono_class_has_variant_generic_params (target
))
8069 return mono_class_is_variant_compatible (target
, candidate
, FALSE
);
8072 MonoClass
*eclass
, *eoclass
;
8074 if (target
->rank
!= candidate
->rank
)
8077 /* vectors vs. one dimensional arrays */
8078 if (target
->byval_arg
.type
!= candidate
->byval_arg
.type
)
8081 eclass
= target
->cast_class
;
8082 eoclass
= candidate
->cast_class
;
8085 * a is b does not imply a[] is b[] when a is a valuetype, and
8086 * b is a reference type.
8089 if (eoclass
->valuetype
) {
8090 if ((eclass
== mono_defaults
.enum_class
) ||
8091 (eclass
== mono_defaults
.enum_class
->parent
) ||
8092 (eclass
== mono_defaults
.object_class
))
8096 return mono_class_is_assignable_from_slow (target
->cast_class
, candidate
->cast_class
);
8098 /*FIXME properly handle nullables */
8099 /*FIXME properly handle (M)VAR */
8104 * mono_class_get_cctor:
8105 * @klass: A MonoClass pointer
8107 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8110 mono_class_get_cctor (MonoClass
*klass
)
8112 MonoCachedClassInfo cached_info
;
8114 if (klass
->image
->dynamic
) {
8116 * has_cctor is not set for these classes because mono_class_init () is
8119 return mono_class_get_method_from_name_flags (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
);
8122 if (!klass
->has_cctor
)
8125 if (mono_class_get_cached_class_info (klass
, &cached_info
))
8126 return mono_get_method (klass
->image
, cached_info
.cctor_token
, klass
);
8128 if (klass
->generic_class
&& !klass
->methods
)
8129 return mono_class_get_inflated_method (klass
, mono_class_get_cctor (klass
->generic_class
->container_class
));
8131 return mono_class_get_method_from_name_flags (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
);
8135 * mono_class_get_finalizer:
8136 * @klass: The MonoClass pointer
8138 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8141 mono_class_get_finalizer (MonoClass
*klass
)
8143 MonoCachedClassInfo cached_info
;
8146 mono_class_init (klass
);
8147 if (!mono_class_has_finalizer (klass
))
8150 if (mono_class_get_cached_class_info (klass
, &cached_info
))
8151 return mono_get_method (cached_info
.finalize_image
, cached_info
.finalize_token
, NULL
);
8153 mono_class_setup_vtable (klass
);
8154 return klass
->vtable
[finalize_slot
];
8159 * mono_class_needs_cctor_run:
8160 * @klass: the MonoClass pointer
8161 * @caller: a MonoMethod describing the caller
8163 * Determines whenever the class has a static constructor and whenever it
8164 * needs to be called when executing CALLER.
8167 mono_class_needs_cctor_run (MonoClass
*klass
, MonoMethod
*caller
)
8171 method
= mono_class_get_cctor (klass
);
8173 return (method
== caller
) ? FALSE
: TRUE
;
8179 * mono_class_array_element_size:
8182 * Returns: the number of bytes an element of type @klass
8183 * uses when stored into an array.
8186 mono_class_array_element_size (MonoClass
*klass
)
8188 MonoType
*type
= &klass
->byval_arg
;
8191 switch (type
->type
) {
8194 case MONO_TYPE_BOOLEAN
:
8198 case MONO_TYPE_CHAR
:
8207 case MONO_TYPE_CLASS
:
8208 case MONO_TYPE_STRING
:
8209 case MONO_TYPE_OBJECT
:
8210 case MONO_TYPE_SZARRAY
:
8211 case MONO_TYPE_ARRAY
:
8213 case MONO_TYPE_MVAR
:
8214 return sizeof (gpointer
);
8219 case MONO_TYPE_VALUETYPE
:
8220 if (type
->data
.klass
->enumtype
) {
8221 type
= mono_class_enum_basetype (type
->data
.klass
);
8222 klass
= klass
->element_class
;
8225 return mono_class_instance_size (klass
) - sizeof (MonoObject
);
8226 case MONO_TYPE_GENERICINST
:
8227 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
8230 case MONO_TYPE_VOID
:
8234 g_error ("unknown type 0x%02x in mono_class_array_element_size", type
->type
);
8240 * mono_array_element_size:
8241 * @ac: pointer to a #MonoArrayClass
8243 * Returns: the size of single array element.
8246 mono_array_element_size (MonoClass
*ac
)
8248 g_assert (ac
->rank
);
8249 return ac
->sizes
.element_size
;
8253 mono_ldtoken (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
8254 MonoGenericContext
*context
)
8256 if (image
->dynamic
) {
8257 MonoClass
*tmp_handle_class
;
8258 gpointer obj
= mono_lookup_dynamic_token_class (image
, token
, TRUE
, &tmp_handle_class
, context
);
8260 g_assert (tmp_handle_class
);
8262 *handle_class
= tmp_handle_class
;
8264 if (tmp_handle_class
== mono_defaults
.typehandle_class
)
8265 return &((MonoClass
*)obj
)->byval_arg
;
8270 switch (token
& 0xff000000) {
8271 case MONO_TOKEN_TYPE_DEF
:
8272 case MONO_TOKEN_TYPE_REF
:
8273 case MONO_TOKEN_TYPE_SPEC
: {
8276 *handle_class
= mono_defaults
.typehandle_class
;
8277 type
= mono_type_get_full (image
, token
, context
);
8280 mono_class_init (mono_class_from_mono_type (type
));
8281 /* We return a MonoType* as handle */
8284 case MONO_TOKEN_FIELD_DEF
: {
8286 guint32 type
= mono_metadata_typedef_from_field (image
, mono_metadata_token_index (token
));
8290 *handle_class
= mono_defaults
.fieldhandle_class
;
8291 class = mono_class_get_full (image
, MONO_TOKEN_TYPE_DEF
| type
, context
);
8294 mono_class_init (class);
8295 return mono_class_get_field (class, token
);
8297 case MONO_TOKEN_METHOD_DEF
:
8298 case MONO_TOKEN_METHOD_SPEC
: {
8300 meth
= mono_get_method_full (image
, token
, NULL
, context
);
8302 *handle_class
= mono_defaults
.methodhandle_class
;
8305 case MONO_TOKEN_MEMBER_REF
: {
8306 guint32 cols
[MONO_MEMBERREF_SIZE
];
8308 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
8309 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
8310 mono_metadata_decode_blob_size (sig
, &sig
);
8311 if (*sig
== 0x6) { /* it's a field */
8313 MonoClassField
*field
;
8314 field
= mono_field_from_token (image
, token
, &klass
, context
);
8316 *handle_class
= mono_defaults
.fieldhandle_class
;
8320 meth
= mono_get_method_full (image
, token
, NULL
, context
);
8322 *handle_class
= mono_defaults
.methodhandle_class
;
8327 g_warning ("Unknown token 0x%08x in ldtoken", token
);
8334 * This function might need to call runtime functions so it can't be part
8335 * of the metadata library.
8337 static MonoLookupDynamicToken lookup_dynamic
= NULL
;
8340 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func
)
8342 lookup_dynamic
= func
;
8346 mono_lookup_dynamic_token (MonoImage
*image
, guint32 token
, MonoGenericContext
*context
)
8348 MonoClass
*handle_class
;
8350 return lookup_dynamic (image
, token
, TRUE
, &handle_class
, context
);
8354 mono_lookup_dynamic_token_class (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
8356 return lookup_dynamic (image
, token
, valid_token
, handle_class
, context
);
8359 static MonoGetCachedClassInfo get_cached_class_info
= NULL
;
8362 mono_install_get_cached_class_info (MonoGetCachedClassInfo func
)
8364 get_cached_class_info
= func
;
8368 mono_class_get_cached_class_info (MonoClass
*klass
, MonoCachedClassInfo
*res
)
8370 if (!get_cached_class_info
)
8373 return get_cached_class_info (klass
, res
);
8377 mono_install_get_class_from_name (MonoGetClassFromName func
)
8379 get_class_from_name
= func
;
8383 mono_class_get_image (MonoClass
*klass
)
8385 return klass
->image
;
8389 * mono_class_get_element_class:
8390 * @klass: the MonoClass to act on
8392 * Returns: the element class of an array or an enumeration.
8395 mono_class_get_element_class (MonoClass
*klass
)
8397 return klass
->element_class
;
8401 * mono_class_is_valuetype:
8402 * @klass: the MonoClass to act on
8404 * Returns: true if the MonoClass represents a ValueType.
8407 mono_class_is_valuetype (MonoClass
*klass
)
8409 return klass
->valuetype
;
8413 * mono_class_is_enum:
8414 * @klass: the MonoClass to act on
8416 * Returns: true if the MonoClass represents an enumeration.
8419 mono_class_is_enum (MonoClass
*klass
)
8421 return klass
->enumtype
;
8425 * mono_class_enum_basetype:
8426 * @klass: the MonoClass to act on
8428 * Returns: the underlying type representation for an enumeration.
8431 mono_class_enum_basetype (MonoClass
*klass
)
8433 if (klass
->element_class
== klass
)
8434 /* SRE or broken types */
8437 return &klass
->element_class
->byval_arg
;
8441 * mono_class_get_parent
8442 * @klass: the MonoClass to act on
8444 * Returns: the parent class for this class.
8447 mono_class_get_parent (MonoClass
*klass
)
8449 return klass
->parent
;
8453 * mono_class_get_nesting_type;
8454 * @klass: the MonoClass to act on
8456 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8459 mono_class_get_nesting_type (MonoClass
*klass
)
8461 return klass
->nested_in
;
8465 * mono_class_get_rank:
8466 * @klass: the MonoClass to act on
8468 * Returns: the rank for the array (the number of dimensions).
8471 mono_class_get_rank (MonoClass
*klass
)
8477 * mono_class_get_flags:
8478 * @klass: the MonoClass to act on
8480 * The type flags from the TypeDef table from the metadata.
8481 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8484 * Returns: the flags from the TypeDef table.
8487 mono_class_get_flags (MonoClass
*klass
)
8489 return klass
->flags
;
8493 * mono_class_get_name
8494 * @klass: the MonoClass to act on
8496 * Returns: the name of the class.
8499 mono_class_get_name (MonoClass
*klass
)
8505 * mono_class_get_namespace:
8506 * @klass: the MonoClass to act on
8508 * Returns: the namespace of the class.
8511 mono_class_get_namespace (MonoClass
*klass
)
8513 return klass
->name_space
;
8517 * mono_class_get_type:
8518 * @klass: the MonoClass to act on
8520 * This method returns the internal Type representation for the class.
8522 * Returns: the MonoType from the class.
8525 mono_class_get_type (MonoClass
*klass
)
8527 return &klass
->byval_arg
;
8531 * mono_class_get_type_token
8532 * @klass: the MonoClass to act on
8534 * This method returns type token for the class.
8536 * Returns: the type token for the class.
8539 mono_class_get_type_token (MonoClass
*klass
)
8541 return klass
->type_token
;
8545 * mono_class_get_byref_type:
8546 * @klass: the MonoClass to act on
8551 mono_class_get_byref_type (MonoClass
*klass
)
8553 return &klass
->this_arg
;
8557 * mono_class_num_fields:
8558 * @klass: the MonoClass to act on
8560 * Returns: the number of static and instance fields in the class.
8563 mono_class_num_fields (MonoClass
*klass
)
8565 return klass
->field
.count
;
8569 * mono_class_num_methods:
8570 * @klass: the MonoClass to act on
8572 * Returns: the number of methods in the class.
8575 mono_class_num_methods (MonoClass
*klass
)
8577 return klass
->method
.count
;
8581 * mono_class_num_properties
8582 * @klass: the MonoClass to act on
8584 * Returns: the number of properties in the class.
8587 mono_class_num_properties (MonoClass
*klass
)
8589 mono_class_setup_properties (klass
);
8591 return klass
->ext
->property
.count
;
8595 * mono_class_num_events:
8596 * @klass: the MonoClass to act on
8598 * Returns: the number of events in the class.
8601 mono_class_num_events (MonoClass
*klass
)
8603 mono_class_setup_events (klass
);
8605 return klass
->ext
->event
.count
;
8609 * mono_class_get_fields:
8610 * @klass: the MonoClass to act on
8612 * This routine is an iterator routine for retrieving the fields in a class.
8614 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8615 * iterate over all of the elements. When no more values are
8616 * available, the return value is NULL.
8618 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8621 mono_class_get_fields (MonoClass
* klass
, gpointer
*iter
)
8623 MonoClassField
* field
;
8627 mono_class_setup_fields_locking (klass
);
8628 if (klass
->exception_type
)
8630 /* start from the first */
8631 if (klass
->field
.count
) {
8632 return *iter
= &klass
->fields
[0];
8640 if (field
< &klass
->fields
[klass
->field
.count
]) {
8641 return *iter
= field
;
8647 * mono_class_get_methods
8648 * @klass: the MonoClass to act on
8650 * This routine is an iterator routine for retrieving the fields in a class.
8652 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8653 * iterate over all of the elements. When no more values are
8654 * available, the return value is NULL.
8656 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8659 mono_class_get_methods (MonoClass
* klass
, gpointer
*iter
)
8661 MonoMethod
** method
;
8665 mono_class_setup_methods (klass
);
8668 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8669 * FIXME we should better report this error to the caller
8671 if (!klass
->methods
)
8673 /* start from the first */
8674 if (klass
->method
.count
) {
8675 *iter
= &klass
->methods
[0];
8676 return klass
->methods
[0];
8684 if (method
< &klass
->methods
[klass
->method
.count
]) {
8692 * mono_class_get_virtual_methods:
8694 * Iterate over the virtual methods of KLASS.
8696 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8699 mono_class_get_virtual_methods (MonoClass
* klass
, gpointer
*iter
)
8701 MonoMethod
** method
;
8704 if (klass
->methods
|| !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
8706 mono_class_setup_methods (klass
);
8708 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8709 * FIXME we should better report this error to the caller
8711 if (!klass
->methods
)
8713 /* start from the first */
8714 method
= &klass
->methods
[0];
8719 while (method
< &klass
->methods
[klass
->method
.count
]) {
8720 if (*method
&& ((*method
)->flags
& METHOD_ATTRIBUTE_VIRTUAL
))
8724 if (method
< &klass
->methods
[klass
->method
.count
]) {
8731 /* Search directly in metadata to avoid calling setup_methods () */
8732 MonoMethod
*res
= NULL
;
8738 start_index
= GPOINTER_TO_UINT (*iter
);
8741 for (i
= start_index
; i
< klass
->method
.count
; ++i
) {
8744 /* class->method.first points into the methodptr table */
8745 flags
= mono_metadata_decode_table_row_col (klass
->image
, MONO_TABLE_METHOD
, klass
->method
.first
+ i
, MONO_METHOD_FLAGS
);
8747 if (flags
& METHOD_ATTRIBUTE_VIRTUAL
)
8751 if (i
< klass
->method
.count
) {
8752 res
= mono_get_method (klass
->image
, MONO_TOKEN_METHOD_DEF
| (klass
->method
.first
+ i
+ 1), klass
);
8753 /* Add 1 here so the if (*iter) check fails */
8754 *iter
= GUINT_TO_POINTER (i
+ 1);
8763 * mono_class_get_properties:
8764 * @klass: the MonoClass to act on
8766 * This routine is an iterator routine for retrieving the properties in a class.
8768 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8769 * iterate over all of the elements. When no more values are
8770 * available, the return value is NULL.
8772 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8775 mono_class_get_properties (MonoClass
* klass
, gpointer
*iter
)
8777 MonoProperty
* property
;
8781 mono_class_setup_properties (klass
);
8782 /* start from the first */
8783 if (klass
->ext
->property
.count
) {
8784 return *iter
= &klass
->ext
->properties
[0];
8792 if (property
< &klass
->ext
->properties
[klass
->ext
->property
.count
]) {
8793 return *iter
= property
;
8799 * mono_class_get_events:
8800 * @klass: the MonoClass to act on
8802 * This routine is an iterator routine for retrieving the properties in a class.
8804 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8805 * iterate over all of the elements. When no more values are
8806 * available, the return value is NULL.
8808 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8811 mono_class_get_events (MonoClass
* klass
, gpointer
*iter
)
8817 mono_class_setup_events (klass
);
8818 /* start from the first */
8819 if (klass
->ext
->event
.count
) {
8820 return *iter
= &klass
->ext
->events
[0];
8828 if (event
< &klass
->ext
->events
[klass
->ext
->event
.count
]) {
8829 return *iter
= event
;
8835 * mono_class_get_interfaces
8836 * @klass: the MonoClass to act on
8838 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8840 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8841 * iterate over all of the elements. When no more values are
8842 * available, the return value is NULL.
8844 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8847 mono_class_get_interfaces (MonoClass
* klass
, gpointer
*iter
)
8855 mono_class_init (klass
);
8856 if (!klass
->interfaces_inited
) {
8857 mono_class_setup_interfaces (klass
, &error
);
8858 if (!mono_error_ok (&error
)) {
8859 mono_error_cleanup (&error
);
8863 /* start from the first */
8864 if (klass
->interface_count
) {
8865 *iter
= &klass
->interfaces
[0];
8866 return klass
->interfaces
[0];
8874 if (iface
< &klass
->interfaces
[klass
->interface_count
]) {
8882 * mono_class_get_nested_types
8883 * @klass: the MonoClass to act on
8885 * This routine is an iterator routine for retrieving the nested types of a class.
8886 * This works only if @klass is non-generic, or a generic type definition.
8888 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8889 * iterate over all of the elements. When no more values are
8890 * available, the return value is NULL.
8892 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8895 mono_class_get_nested_types (MonoClass
* klass
, gpointer
*iter
)
8903 if (!klass
->nested_classes_inited
) {
8904 if (!klass
->type_token
)
8905 klass
->nested_classes_inited
= TRUE
;
8906 mono_loader_lock ();
8907 if (!klass
->nested_classes_inited
) {
8908 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, 1);
8911 guint32 cols
[MONO_NESTED_CLASS_SIZE
];
8912 mono_metadata_decode_row (&klass
->image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, cols
, MONO_NESTED_CLASS_SIZE
);
8913 nclass
= mono_class_create_from_typedef (klass
->image
, MONO_TOKEN_TYPE_DEF
| cols
[MONO_NESTED_CLASS_NESTED
], &error
);
8914 if (!mono_error_ok (&error
)) {
8915 /*FIXME don't swallow the error message*/
8916 mono_error_cleanup (&error
);
8918 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, i
+ 1);
8921 mono_class_alloc_ext (klass
);
8922 klass
->ext
->nested_classes
= g_list_prepend_image (klass
->image
, klass
->ext
->nested_classes
, nclass
);
8924 i
= mono_metadata_nesting_typedef (klass
->image
, klass
->type_token
, i
+ 1);
8927 mono_memory_barrier ();
8928 klass
->nested_classes_inited
= TRUE
;
8929 mono_loader_unlock ();
8933 /* start from the first */
8934 if (klass
->ext
&& klass
->ext
->nested_classes
) {
8935 *iter
= klass
->ext
->nested_classes
;
8936 return klass
->ext
->nested_classes
->data
;
8938 /* no nested types */
8953 * mono_class_is_delegate
8954 * @klass: the MonoClass to act on
8956 * Returns: true if the MonoClass represents a System.Delegate.
8959 mono_class_is_delegate (MonoClass
*klass
)
8961 return klass
->delegate
;
8965 * mono_class_implements_interface
8966 * @klass: The MonoClass to act on
8967 * @interface: The interface to check if @klass implements.
8969 * Returns: true if @klass implements @interface.
8972 mono_class_implements_interface (MonoClass
* klass
, MonoClass
* iface
)
8974 return mono_class_is_assignable_from (iface
, klass
);
8978 * mono_field_get_name:
8979 * @field: the MonoClassField to act on
8981 * Returns: the name of the field.
8984 mono_field_get_name (MonoClassField
*field
)
8990 * mono_field_get_type:
8991 * @field: the MonoClassField to act on
8993 * Returns: MonoType of the field.
8996 mono_field_get_type (MonoClassField
*field
)
8999 MonoType
*type
= mono_field_get_type_checked (field
, &error
);
9000 if (!mono_error_ok (&error
)) {
9001 mono_trace_warning (MONO_TRACE_TYPE
, "Could not load field's type due to %s", mono_error_get_message (&error
));
9002 mono_error_cleanup (&error
);
9009 * mono_field_get_type_checked:
9010 * @field: the MonoClassField to act on
9011 * @error: used to return any erro found while retrieving @field type
9013 * Returns: MonoType of the field.
9016 mono_field_get_type_checked (MonoClassField
*field
, MonoError
*error
)
9018 mono_error_init (error
);
9020 mono_field_resolve_type (field
, error
);
9025 * mono_field_get_parent:
9026 * @field: the MonoClassField to act on
9028 * Returns: MonoClass where the field was defined.
9031 mono_field_get_parent (MonoClassField
*field
)
9033 return field
->parent
;
9037 * mono_field_get_flags;
9038 * @field: the MonoClassField to act on
9040 * The metadata flags for a field are encoded using the
9041 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9043 * Returns: the flags for the field.
9046 mono_field_get_flags (MonoClassField
*field
)
9049 return mono_field_resolve_flags (field
);
9050 return field
->type
->attrs
;
9054 * mono_field_get_offset;
9055 * @field: the MonoClassField to act on
9057 * Returns: the field offset.
9060 mono_field_get_offset (MonoClassField
*field
)
9062 return field
->offset
;
9066 mono_field_get_rva (MonoClassField
*field
)
9070 MonoClass
*klass
= field
->parent
;
9072 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
);
9074 if (!klass
->ext
|| !klass
->ext
->field_def_values
) {
9075 mono_loader_lock ();
9076 mono_class_alloc_ext (klass
);
9077 if (!klass
->ext
->field_def_values
)
9078 klass
->ext
->field_def_values
= mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * klass
->field
.count
);
9079 mono_loader_unlock ();
9082 field_index
= mono_field_get_index (field
);
9084 if (!klass
->ext
->field_def_values
[field_index
].data
&& !klass
->image
->dynamic
) {
9085 mono_metadata_field_info (field
->parent
->image
, klass
->field
.first
+ field_index
, NULL
, &rva
, NULL
);
9087 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field
), field
->parent
->name
);
9088 klass
->ext
->field_def_values
[field_index
].data
= mono_image_rva_map (field
->parent
->image
, rva
);
9091 return klass
->ext
->field_def_values
[field_index
].data
;
9095 * mono_field_get_data;
9096 * @field: the MonoClassField to act on
9098 * Returns: pointer to the metadata constant value or to the field
9099 * data if it has an RVA flag.
9102 mono_field_get_data (MonoClassField
*field
)
9104 if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
) {
9105 MonoTypeEnum def_type
;
9107 return mono_class_get_field_default_value (field
, &def_type
);
9108 } else if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
9109 return mono_field_get_rva (field
);
9116 * mono_property_get_name:
9117 * @prop: the MonoProperty to act on
9119 * Returns: the name of the property
9122 mono_property_get_name (MonoProperty
*prop
)
9128 * mono_property_get_set_method
9129 * @prop: the MonoProperty to act on.
9131 * Returns: the setter method of the property (A MonoMethod)
9134 mono_property_get_set_method (MonoProperty
*prop
)
9140 * mono_property_get_get_method
9141 * @prop: the MonoProperty to act on.
9143 * Returns: the setter method of the property (A MonoMethod)
9146 mono_property_get_get_method (MonoProperty
*prop
)
9152 * mono_property_get_parent:
9153 * @prop: the MonoProperty to act on.
9155 * Returns: the MonoClass where the property was defined.
9158 mono_property_get_parent (MonoProperty
*prop
)
9160 return prop
->parent
;
9164 * mono_property_get_flags:
9165 * @prop: the MonoProperty to act on.
9167 * The metadata flags for a property are encoded using the
9168 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9170 * Returns: the flags for the property.
9173 mono_property_get_flags (MonoProperty
*prop
)
9179 * mono_event_get_name:
9180 * @event: the MonoEvent to act on
9182 * Returns: the name of the event.
9185 mono_event_get_name (MonoEvent
*event
)
9191 * mono_event_get_add_method:
9192 * @event: The MonoEvent to act on.
9194 * Returns: the @add' method for the event (a MonoMethod).
9197 mono_event_get_add_method (MonoEvent
*event
)
9203 * mono_event_get_remove_method:
9204 * @event: The MonoEvent to act on.
9206 * Returns: the @remove method for the event (a MonoMethod).
9209 mono_event_get_remove_method (MonoEvent
*event
)
9211 return event
->remove
;
9215 * mono_event_get_raise_method:
9216 * @event: The MonoEvent to act on.
9218 * Returns: the @raise method for the event (a MonoMethod).
9221 mono_event_get_raise_method (MonoEvent
*event
)
9223 return event
->raise
;
9227 * mono_event_get_parent:
9228 * @event: the MonoEvent to act on.
9230 * Returns: the MonoClass where the event is defined.
9233 mono_event_get_parent (MonoEvent
*event
)
9235 return event
->parent
;
9239 * mono_event_get_flags
9240 * @event: the MonoEvent to act on.
9242 * The metadata flags for an event are encoded using the
9243 * EVENT_* constants. See the tabledefs.h file for details.
9245 * Returns: the flags for the event.
9248 mono_event_get_flags (MonoEvent
*event
)
9250 return event
->attrs
;
9254 * mono_class_get_method_from_name:
9255 * @klass: where to look for the method
9256 * @name_space: name of the method
9257 * @param_count: number of parameters. -1 for any number.
9259 * Obtains a MonoMethod with a given name and number of parameters.
9260 * It only works if there are no multiple signatures for any given method name.
9263 mono_class_get_method_from_name (MonoClass
*klass
, const char *name
, int param_count
)
9265 return mono_class_get_method_from_name_flags (klass
, name
, param_count
, 0);
9269 find_method_in_metadata (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
9271 MonoMethod
*res
= NULL
;
9274 /* Search directly in the metadata to avoid calling setup_methods () */
9275 for (i
= 0; i
< klass
->method
.count
; ++i
) {
9276 guint32 cols
[MONO_METHOD_SIZE
];
9278 MonoMethodSignature
*sig
;
9280 /* class->method.first points into the methodptr table */
9281 mono_metadata_decode_table_row (klass
->image
, MONO_TABLE_METHOD
, klass
->method
.first
+ i
, cols
, MONO_METHOD_SIZE
);
9283 if (!strcmp (mono_metadata_string_heap (klass
->image
, cols
[MONO_METHOD_NAME
]), name
)) {
9284 method
= mono_get_method (klass
->image
, MONO_TOKEN_METHOD_DEF
| (klass
->method
.first
+ i
+ 1), klass
);
9285 if (param_count
== -1) {
9289 sig
= mono_method_signature (method
);
9290 if (sig
&& sig
->param_count
== param_count
) {
9301 * mono_class_get_method_from_name_flags:
9302 * @klass: where to look for the method
9303 * @name_space: name of the method
9304 * @param_count: number of parameters. -1 for any number.
9305 * @flags: flags which must be set in the method
9307 * Obtains a MonoMethod with a given name and number of parameters.
9308 * It only works if there are no multiple signatures for any given method name.
9311 mono_class_get_method_from_name_flags (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
9313 MonoMethod
*res
= NULL
;
9316 mono_class_init (klass
);
9318 if (klass
->generic_class
&& !klass
->methods
) {
9319 res
= mono_class_get_method_from_name_flags (klass
->generic_class
->container_class
, name
, param_count
, flags
);
9321 res
= mono_class_inflate_generic_method_full (res
, klass
, mono_class_get_context (klass
));
9325 if (klass
->methods
|| !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
9326 mono_class_setup_methods (klass
);
9328 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9329 See mono/tests/array_load_exception.il
9330 FIXME we should better report this error to the caller
9332 if (!klass
->methods
)
9334 for (i
= 0; i
< klass
->method
.count
; ++i
) {
9335 MonoMethod
*method
= klass
->methods
[i
];
9337 if (method
->name
[0] == name
[0] &&
9338 !strcmp (name
, method
->name
) &&
9339 (param_count
== -1 || mono_method_signature (method
)->param_count
== param_count
) &&
9340 ((method
->flags
& flags
) == flags
)) {
9347 res
= find_method_in_metadata (klass
, name
, param_count
, flags
);
9354 * mono_class_set_failure:
9355 * @klass: class in which the failure was detected
9356 * @ex_type: the kind of exception/error to be thrown (later)
9357 * @ex_data: exception data (specific to each type of exception/error)
9359 * Keep a detected failure informations in the class for later processing.
9360 * Note that only the first failure is kept.
9362 * LOCKING: Acquires the loader lock.
9365 mono_class_set_failure (MonoClass
*klass
, guint32 ex_type
, void *ex_data
)
9367 if (klass
->exception_type
)
9370 mono_loader_lock ();
9371 klass
->exception_type
= ex_type
;
9373 mono_image_property_insert (klass
->image
, klass
, MONO_CLASS_PROP_EXCEPTION_DATA
, ex_data
);
9374 mono_loader_unlock ();
9380 * mono_class_get_exception_data:
9382 * Return the exception_data property of KLASS.
9384 * LOCKING: Acquires the loader lock.
9387 mono_class_get_exception_data (MonoClass
*klass
)
9389 return mono_image_property_lookup (klass
->image
, klass
, MONO_CLASS_PROP_EXCEPTION_DATA
);
9393 * mono_classes_init:
9395 * Initialize the resources used by this module.
9398 mono_classes_init (void)
9400 mono_counters_register ("Inflated methods size",
9401 MONO_COUNTER_GENERICS
| MONO_COUNTER_INT
, &inflated_methods_size
);
9402 mono_counters_register ("Inflated classes",
9403 MONO_COUNTER_GENERICS
| MONO_COUNTER_INT
, &inflated_classes
);
9404 mono_counters_register ("Inflated classes size",
9405 MONO_COUNTER_GENERICS
| MONO_COUNTER_INT
, &inflated_classes_size
);
9406 mono_counters_register ("MonoClass size",
9407 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &classes_size
);
9408 mono_counters_register ("MonoClassExt size",
9409 MONO_COUNTER_METADATA
| MONO_COUNTER_INT
, &class_ext_size
);
9413 * mono_classes_cleanup:
9415 * Free the resources used by this module.
9418 mono_classes_cleanup (void)
9420 if (global_interface_bitset
)
9421 mono_bitset_free (global_interface_bitset
);
9422 global_interface_bitset
= NULL
;
9426 * mono_class_get_exception_for_failure:
9427 * @klass: class in which the failure was detected
9429 * Return a constructed MonoException than the caller can then throw
9430 * using mono_raise_exception - or NULL if no failure is present (or
9431 * doesn't result in an exception).
9434 mono_class_get_exception_for_failure (MonoClass
*klass
)
9436 gpointer exception_data
= mono_class_get_exception_data (klass
);
9438 switch (klass
->exception_type
) {
9439 #ifndef DISABLE_SECURITY
9440 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND
: {
9441 MonoDomain
*domain
= mono_domain_get ();
9442 MonoSecurityManager
* secman
= mono_security_manager_get_methods ();
9443 MonoMethod
*method
= exception_data
;
9444 guint32 error
= (method
) ? MONO_METADATA_INHERITANCEDEMAND_METHOD
: MONO_METADATA_INHERITANCEDEMAND_CLASS
;
9445 MonoObject
*exc
= NULL
;
9449 args
[1] = mono_assembly_get_object (domain
, mono_image_get_assembly (klass
->image
));
9450 args
[2] = mono_type_get_object (domain
, &klass
->byval_arg
);
9451 args
[3] = (method
) ? mono_method_get_object (domain
, method
, NULL
) : NULL
;
9453 mono_runtime_invoke (secman
->inheritsecurityexception
, NULL
, args
, &exc
);
9454 return (MonoException
*) exc
;
9457 case MONO_EXCEPTION_TYPE_LOAD
: {
9460 char *str
= mono_type_get_full_name (klass
);
9461 char *astr
= klass
->image
->assembly
? mono_stringify_assembly_name (&klass
->image
->assembly
->aname
): NULL
;
9462 name
= mono_string_new (mono_domain_get (), str
);
9464 ex
= mono_get_exception_type_load (name
, astr
);
9468 case MONO_EXCEPTION_MISSING_METHOD
: {
9469 char *class_name
= exception_data
;
9470 char *assembly_name
= class_name
+ strlen (class_name
) + 1;
9472 return mono_get_exception_missing_method (class_name
, assembly_name
);
9474 case MONO_EXCEPTION_MISSING_FIELD
: {
9475 char *class_name
= exception_data
;
9476 char *member_name
= class_name
+ strlen (class_name
) + 1;
9478 return mono_get_exception_missing_field (class_name
, member_name
);
9480 case MONO_EXCEPTION_FILE_NOT_FOUND
: {
9481 char *msg_format
= exception_data
;
9482 char *assembly_name
= msg_format
+ strlen (msg_format
) + 1;
9483 char *msg
= g_strdup_printf (msg_format
, assembly_name
);
9486 ex
= mono_get_exception_file_not_found2 (msg
, mono_string_new (mono_domain_get (), assembly_name
));
9492 case MONO_EXCEPTION_BAD_IMAGE
: {
9493 return mono_get_exception_bad_image_format (exception_data
);
9496 MonoLoaderError
*error
;
9499 error
= mono_loader_get_last_error ();
9501 ex
= mono_loader_error_prepare_exception (error
);
9505 /* TODO - handle other class related failures */
9512 is_nesting_type (MonoClass
*outer_klass
, MonoClass
*inner_klass
)
9514 outer_klass
= mono_class_get_generic_type_definition (outer_klass
);
9515 inner_klass
= mono_class_get_generic_type_definition (inner_klass
);
9517 if (outer_klass
== inner_klass
)
9519 inner_klass
= inner_klass
->nested_in
;
9520 } while (inner_klass
);
9525 mono_class_get_generic_type_definition (MonoClass
*klass
)
9527 return klass
->generic_class
? klass
->generic_class
->container_class
: klass
;
9531 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9533 * Generic instantiations are ignored for all super types of @klass.
9535 * Visibility checks ignoring generic instantiations.
9538 mono_class_has_parent_and_ignore_generics (MonoClass
*klass
, MonoClass
*parent
)
9541 klass
= mono_class_get_generic_type_definition (klass
);
9542 parent
= mono_class_get_generic_type_definition (parent
);
9543 mono_class_setup_supertypes (klass
);
9545 for (i
= 0; i
< klass
->idepth
; ++i
) {
9546 if (parent
== mono_class_get_generic_type_definition (klass
->supertypes
[i
]))
9552 * Subtype can only access parent members with family protection if the site object
9553 * is subclass of Subtype. For example:
9554 * class A { protected int x; }
9556 * void valid_access () {
9560 * void invalid_access () {
9567 is_valid_family_access (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
*context_klass
)
9569 if (!mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
))
9572 if (context_klass
== NULL
)
9574 /*if access_klass is not member_klass context_klass must be type compat*/
9575 if (access_klass
!= member_klass
&& !mono_class_has_parent_and_ignore_generics (context_klass
, access_klass
))
9581 can_access_internals (MonoAssembly
*accessing
, MonoAssembly
* accessed
)
9584 if (accessing
== accessed
)
9586 if (!accessed
|| !accessing
)
9589 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9590 * anywhere so untrusted friends are not safe to access platform's code internals */
9591 if (mono_security_core_clr_enabled ()) {
9592 if (!mono_security_core_clr_can_access_internals (accessing
->image
, accessed
->image
))
9596 mono_assembly_load_friends (accessed
);
9597 for (tmp
= accessed
->friend_assembly_names
; tmp
; tmp
= tmp
->next
) {
9598 MonoAssemblyName
*friend = tmp
->data
;
9599 /* Be conservative with checks */
9602 if (strcmp (accessing
->aname
.name
, friend->name
))
9604 if (friend->public_key_token
[0]) {
9605 if (!accessing
->aname
.public_key_token
[0])
9607 if (!mono_public_tokens_are_equal (friend->public_key_token
, accessing
->aname
.public_key_token
))
9616 * If klass is a generic type or if it is derived from a generic type, return the
9617 * MonoClass of the generic definition
9618 * Returns NULL if not found
9621 get_generic_definition_class (MonoClass
*klass
)
9624 if (klass
->generic_class
&& klass
->generic_class
->container_class
)
9625 return klass
->generic_class
->container_class
;
9626 klass
= klass
->parent
;
9632 can_access_instantiation (MonoClass
*access_klass
, MonoGenericInst
*ginst
)
9635 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
9636 MonoType
*type
= ginst
->type_argv
[i
];
9637 switch (type
->type
) {
9638 case MONO_TYPE_SZARRAY
:
9639 if (!can_access_type (access_klass
, type
->data
.klass
))
9642 case MONO_TYPE_ARRAY
:
9643 if (!can_access_type (access_klass
, type
->data
.array
->eklass
))
9647 if (!can_access_type (access_klass
, mono_class_from_mono_type (type
->data
.type
)))
9650 case MONO_TYPE_CLASS
:
9651 case MONO_TYPE_VALUETYPE
:
9652 case MONO_TYPE_GENERICINST
:
9653 if (!can_access_type (access_klass
, mono_class_from_mono_type (type
)))
9661 can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
)
9665 if (access_klass
->image
->assembly
&& access_klass
->image
->assembly
->corlib_internal
)
9668 if (access_klass
->element_class
&& !access_klass
->enumtype
)
9669 access_klass
= access_klass
->element_class
;
9671 if (member_klass
->element_class
&& !member_klass
->enumtype
)
9672 member_klass
= member_klass
->element_class
;
9674 access_level
= member_klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
9676 if (member_klass
->byval_arg
.type
== MONO_TYPE_VAR
|| member_klass
->byval_arg
.type
== MONO_TYPE_MVAR
)
9679 if (member_klass
->generic_class
&& !can_access_instantiation (access_klass
, member_klass
->generic_class
->context
.class_inst
))
9682 if (is_nesting_type (access_klass
, member_klass
) || (access_klass
->nested_in
&& is_nesting_type (access_klass
->nested_in
, member_klass
)))
9685 if (member_klass
->nested_in
&& !can_access_type (access_klass
, member_klass
->nested_in
))
9688 /*Non nested type with nested visibility. We just fail it.*/
9689 if (access_level
>= TYPE_ATTRIBUTE_NESTED_PRIVATE
&& access_level
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
&& member_klass
->nested_in
== NULL
)
9692 switch (access_level
) {
9693 case TYPE_ATTRIBUTE_NOT_PUBLIC
:
9694 return can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
);
9696 case TYPE_ATTRIBUTE_PUBLIC
:
9699 case TYPE_ATTRIBUTE_NESTED_PUBLIC
:
9702 case TYPE_ATTRIBUTE_NESTED_PRIVATE
:
9703 return is_nesting_type (member_klass
, access_klass
);
9705 case TYPE_ATTRIBUTE_NESTED_FAMILY
:
9706 return mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
->nested_in
);
9708 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY
:
9709 return can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
);
9711 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM
:
9712 return can_access_internals (access_klass
->image
->assembly
, member_klass
->nested_in
->image
->assembly
) &&
9713 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
->nested_in
);
9715 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
:
9716 return can_access_internals (access_klass
->image
->assembly
, member_klass
->nested_in
->image
->assembly
) ||
9717 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
->nested_in
);
9722 /* FIXME: check visibility of type, too */
9724 can_access_member (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
* context_klass
, int access_level
)
9726 MonoClass
*member_generic_def
;
9727 if (access_klass
->image
->assembly
&& access_klass
->image
->assembly
->corlib_internal
)
9730 if (((access_klass
->generic_class
&& access_klass
->generic_class
->container_class
) ||
9731 access_klass
->generic_container
) &&
9732 (member_generic_def
= get_generic_definition_class (member_klass
))) {
9733 MonoClass
*access_container
;
9735 if (access_klass
->generic_container
)
9736 access_container
= access_klass
;
9738 access_container
= access_klass
->generic_class
->container_class
;
9740 if (can_access_member (access_container
, member_generic_def
, context_klass
, access_level
))
9744 /* Partition I 8.5.3.2 */
9745 /* the access level values are the same for fields and methods */
9746 switch (access_level
) {
9747 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED
:
9748 /* same compilation unit */
9749 return access_klass
->image
== member_klass
->image
;
9750 case FIELD_ATTRIBUTE_PRIVATE
:
9751 return access_klass
== member_klass
;
9752 case FIELD_ATTRIBUTE_FAM_AND_ASSEM
:
9753 if (is_valid_family_access (access_klass
, member_klass
, context_klass
) &&
9754 can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
))
9757 case FIELD_ATTRIBUTE_ASSEMBLY
:
9758 return can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
);
9759 case FIELD_ATTRIBUTE_FAMILY
:
9760 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
9763 case FIELD_ATTRIBUTE_FAM_OR_ASSEM
:
9764 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
9766 return can_access_internals (access_klass
->image
->assembly
, member_klass
->image
->assembly
);
9767 case FIELD_ATTRIBUTE_PUBLIC
:
9774 mono_method_can_access_field (MonoMethod
*method
, MonoClassField
*field
)
9776 /* FIXME: check all overlapping fields */
9777 int can
= can_access_member (method
->klass
, field
->parent
, NULL
, mono_field_get_type (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
9779 MonoClass
*nested
= method
->klass
->nested_in
;
9781 can
= can_access_member (nested
, field
->parent
, NULL
, mono_field_get_type (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
9784 nested
= nested
->nested_in
;
9791 mono_method_can_access_method (MonoMethod
*method
, MonoMethod
*called
)
9793 int can
= can_access_member (method
->klass
, called
->klass
, NULL
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
9795 MonoClass
*nested
= method
->klass
->nested_in
;
9797 can
= can_access_member (nested
, called
->klass
, NULL
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
9800 nested
= nested
->nested_in
;
9805 * with generics calls to explicit interface implementations can be expressed
9806 * directly: the method is private, but we must allow it. This may be opening
9807 * a hole or the generics code should handle this differently.
9808 * Maybe just ensure the interface type is public.
9810 if ((called
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) && (called
->flags
& METHOD_ATTRIBUTE_FINAL
))
9816 * mono_method_can_access_method_full:
9817 * @method: The caller method
9818 * @called: The called method
9819 * @context_klass: The static type on stack of the owner @called object used
9821 * This function must be used with instance calls, as they have more strict family accessibility.
9822 * It can be used with static methods, but context_klass should be NULL.
9824 * Returns: TRUE if caller have proper visibility and acessibility to @called
9827 mono_method_can_access_method_full (MonoMethod
*method
, MonoMethod
*called
, MonoClass
*context_klass
)
9829 MonoClass
*access_class
= method
->klass
;
9830 MonoClass
*member_class
= called
->klass
;
9831 int can
= can_access_member (access_class
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
9833 MonoClass
*nested
= access_class
->nested_in
;
9835 can
= can_access_member (nested
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
9838 nested
= nested
->nested_in
;
9845 can
= can_access_type (access_class
, member_class
);
9847 MonoClass
*nested
= access_class
->nested_in
;
9849 can
= can_access_type (nested
, member_class
);
9852 nested
= nested
->nested_in
;
9859 if (called
->is_inflated
) {
9860 MonoMethodInflated
* infl
= (MonoMethodInflated
*)called
;
9861 if (infl
->context
.method_inst
&& !can_access_instantiation (access_class
, infl
->context
.method_inst
))
9870 * mono_method_can_access_field_full:
9871 * @method: The caller method
9872 * @field: The accessed field
9873 * @context_klass: The static type on stack of the owner @field object used
9875 * This function must be used with instance fields, as they have more strict family accessibility.
9876 * It can be used with static fields, but context_klass should be NULL.
9878 * Returns: TRUE if caller have proper visibility and acessibility to @field
9881 mono_method_can_access_field_full (MonoMethod
*method
, MonoClassField
*field
, MonoClass
*context_klass
)
9883 MonoClass
*access_class
= method
->klass
;
9884 MonoClass
*member_class
= field
->parent
;
9885 /* FIXME: check all overlapping fields */
9886 int can
= can_access_member (access_class
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
9888 MonoClass
*nested
= access_class
->nested_in
;
9890 can
= can_access_member (nested
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
9893 nested
= nested
->nested_in
;
9900 can
= can_access_type (access_class
, member_class
);
9902 MonoClass
*nested
= access_class
->nested_in
;
9904 can
= can_access_type (nested
, member_class
);
9907 nested
= nested
->nested_in
;
9917 * mono_class_can_access_class:
9918 * @source_class: The source class
9919 * @target_class: The accessed class
9921 * This function returns is @target_class is visible to @source_class
9923 * Returns: TRUE if source have proper visibility and acessibility to target
9926 mono_class_can_access_class (MonoClass
*source_class
, MonoClass
*target_class
)
9928 return can_access_type (source_class
, target_class
);
9932 * mono_type_is_valid_enum_basetype:
9933 * @type: The MonoType to check
9935 * Returns: TRUE if the type can be used as the basetype of an enum
9937 gboolean
mono_type_is_valid_enum_basetype (MonoType
* type
) {
9938 switch (type
->type
) {
9941 case MONO_TYPE_BOOLEAN
:
9944 case MONO_TYPE_CHAR
:
9957 * mono_class_is_valid_enum:
9958 * @klass: An enum class to be validated
9960 * This method verify the required properties an enum should have.
9962 * Returns: TRUE if the informed enum class is valid
9964 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9965 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9966 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9968 gboolean
mono_class_is_valid_enum (MonoClass
*klass
) {
9969 MonoClassField
* field
;
9970 gpointer iter
= NULL
;
9971 gboolean found_base_field
= FALSE
;
9973 g_assert (klass
->enumtype
);
9974 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9975 if (!klass
->parent
|| strcmp (klass
->parent
->name
, "Enum") || strcmp (klass
->parent
->name_space
, "System") ) {
9979 if ((klass
->flags
& TYPE_ATTRIBUTE_LAYOUT_MASK
) != TYPE_ATTRIBUTE_AUTO_LAYOUT
)
9982 while ((field
= mono_class_get_fields (klass
, &iter
))) {
9983 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
9984 if (found_base_field
)
9986 found_base_field
= TRUE
;
9987 if (!mono_type_is_valid_enum_basetype (field
->type
))
9992 if (!found_base_field
)
9995 if (klass
->method
.count
> 0)
10002 mono_generic_class_is_generic_type_definition (MonoGenericClass
*gklass
)
10004 return gklass
->context
.class_inst
== gklass
->container_class
->generic_container
->context
.class_inst
;
10008 * mono_class_setup_interface_id:
10010 * Initializes MonoClass::interface_id if required.
10012 * LOCKING: Acquires the loader lock.
10015 mono_class_setup_interface_id (MonoClass
*class)
10017 mono_loader_lock ();
10018 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id
)
10019 class->interface_id
= mono_get_unique_iid (class);
10020 mono_loader_unlock ();
10024 * mono_class_alloc_ext:
10026 * Allocate klass->ext if not already done.
10027 * LOCKING: Assumes the loader lock is held.
10030 mono_class_alloc_ext (MonoClass
*klass
)
10033 klass
->ext
= mono_class_alloc0 (klass
, sizeof (MonoClassExt
));
10034 class_ext_size
+= sizeof (MonoClassExt
);
10039 * mono_class_setup_interfaces:
10041 * Initialize class->interfaces/interfaces_count.
10042 * LOCKING: Acquires the loader lock.
10043 * This function can fail the type.
10046 mono_class_setup_interfaces (MonoClass
*klass
, MonoError
*error
)
10050 mono_error_init (error
);
10052 if (klass
->interfaces_inited
)
10055 mono_loader_lock ();
10057 if (klass
->interfaces_inited
) {
10058 mono_loader_unlock ();
10062 if (klass
->rank
== 1 && klass
->byval_arg
.type
!= MONO_TYPE_ARRAY
) {
10063 MonoType
*args
[1];
10065 /* generic IList, ICollection, IEnumerable */
10066 klass
->interface_count
= mono_defaults
.generic_ireadonlylist_class
? 2 : 1;
10067 klass
->interfaces
= mono_image_alloc0 (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
10069 args
[0] = &klass
->element_class
->byval_arg
;
10070 klass
->interfaces
[0] = mono_class_bind_generic_parameters (
10071 mono_defaults
.generic_ilist_class
, 1, args
, FALSE
);
10072 if (klass
->interface_count
> 1)
10073 klass
->interfaces
[1] = mono_class_bind_generic_parameters (
10074 mono_defaults
.generic_ireadonlylist_class
, 1, args
, FALSE
);
10075 } else if (klass
->generic_class
) {
10076 MonoClass
*gklass
= klass
->generic_class
->container_class
;
10078 klass
->interface_count
= gklass
->interface_count
;
10079 klass
->interfaces
= mono_class_new0 (klass
, MonoClass
*, klass
->interface_count
);
10080 for (i
= 0; i
< klass
->interface_count
; i
++) {
10081 klass
->interfaces
[i
] = mono_class_inflate_generic_class_checked (gklass
->interfaces
[i
], mono_generic_class_get_context (klass
->generic_class
), error
);
10082 if (!mono_error_ok (error
)) {
10083 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, g_strdup ("Could not setup the interfaces"));
10084 klass
->interfaces
= NULL
;
10090 mono_memory_barrier ();
10092 klass
->interfaces_inited
= TRUE
;
10094 mono_loader_unlock ();
10098 mono_field_resolve_type (MonoClassField
*field
, MonoError
*error
)
10100 MonoClass
*class = field
->parent
;
10101 MonoImage
*image
= class->image
;
10102 MonoClass
*gtd
= class->generic_class
? mono_class_get_generic_type_definition (class) : NULL
;
10103 int field_idx
= field
- class->fields
;
10105 mono_error_init (error
);
10108 MonoClassField
*gfield
= >d
->fields
[field_idx
];
10109 MonoType
*gtype
= mono_field_get_type_checked (gfield
, error
);
10110 if (!mono_error_ok (error
)) {
10111 char *err_msg
= g_strdup_printf ("Could not load field %d type due to: %s", field_idx
, mono_error_get_message (error
));
10112 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
10116 field
->type
= mono_class_inflate_generic_type_no_copy (image
, gtype
, mono_class_get_context (class), error
);
10117 if (!mono_error_ok (error
)) {
10118 char *err_msg
= g_strdup_printf ("Could not load field %d type due to: %s", field_idx
, mono_error_get_message (error
));
10119 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, err_msg
);
10124 guint32 cols
[MONO_FIELD_SIZE
];
10125 MonoGenericContainer
*container
= NULL
;
10126 int idx
= class->field
.first
+ field_idx
;
10128 /*FIXME, in theory we do not lazy load SRE fields*/
10129 g_assert (!image
->dynamic
);
10131 if (class->generic_container
) {
10132 container
= class->generic_container
;
10134 container
= gtd
->generic_container
;
10135 g_assert (container
);
10138 /* class->field.first and idx points into the fieldptr table */
10139 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
10141 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], NULL
)) {
10142 mono_error_set_type_load_class (error
, class, "Could not verify field %s signature", field
->name
);
10143 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
10147 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
10149 mono_metadata_decode_value (sig
, &sig
);
10150 /* FIELD signature == 0x06 */
10151 g_assert (*sig
== 0x06);
10152 field
->type
= mono_metadata_parse_type_full (image
, container
, MONO_PARSE_FIELD
, cols
[MONO_FIELD_FLAGS
], sig
+ 1, &sig
);
10154 mono_class_set_failure_from_loader_error (class, error
, g_strdup_printf ("Could not load field %s type", field
->name
));
10159 mono_field_resolve_flags (MonoClassField
*field
)
10161 MonoClass
*class = field
->parent
;
10162 MonoImage
*image
= class->image
;
10163 MonoClass
*gtd
= class->generic_class
? mono_class_get_generic_type_definition (class) : NULL
;
10164 int field_idx
= field
- class->fields
;
10168 MonoClassField
*gfield
= >d
->fields
[field_idx
];
10169 return mono_field_get_flags (gfield
);
10171 int idx
= class->field
.first
+ field_idx
;
10173 /*FIXME, in theory we do not lazy load SRE fields*/
10174 g_assert (!image
->dynamic
);
10176 return mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_FLAGS
);
10181 * mono_class_setup_basic_field_info:
10182 * @class: The class to initialize
10184 * Initializes the class->fields array of fields.
10185 * Aquires the loader lock.
10188 mono_class_setup_basic_field_info_locking (MonoClass
*class)
10190 mono_loader_lock ();
10191 mono_class_setup_basic_field_info (class);
10192 mono_loader_unlock ();
10196 * mono_class_get_fields_lazy:
10197 * @klass: the MonoClass to act on
10199 * This routine is an iterator routine for retrieving the fields in a class.
10200 * Only minimal information about fields are loaded. Accessors must be used
10201 * for all MonoClassField returned.
10203 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10204 * iterate over all of the elements. When no more values are
10205 * available, the return value is NULL.
10207 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10210 mono_class_get_fields_lazy (MonoClass
* klass
, gpointer
*iter
)
10212 MonoClassField
* field
;
10216 mono_class_setup_basic_field_info_locking (klass
);
10217 if (!klass
->fields
)
10219 /* start from the first */
10220 if (klass
->field
.count
) {
10221 return *iter
= &klass
->fields
[0];
10229 if (field
< &klass
->fields
[klass
->field
.count
]) {
10230 return *iter
= field
;
10236 mono_class_full_name (MonoClass
*klass
)
10238 return mono_type_full_name (&klass
->byval_arg
);