3 * Class management for the Mono runtime
6 * Miguel de Icaza (miguel@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/image-internals.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/exception-internals.h>
26 #include <mono/metadata/metadata.h>
27 #include <mono/metadata/metadata-internals.h>
28 #include <mono/metadata/profiler-private.h>
29 #include <mono/metadata/tabledefs.h>
30 #include <mono/metadata/tokentype.h>
31 #include <mono/metadata/class-init.h>
32 #include <mono/metadata/class-internals.h>
33 #include <mono/metadata/object.h>
34 #include <mono/metadata/appdomain.h>
35 #include <mono/metadata/mono-endian.h>
36 #include <mono/metadata/debug-helpers.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/exception.h>
39 #include <mono/metadata/security-manager.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/attrdefs.h>
42 #include <mono/metadata/gc-internals.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-debug.h>
45 #include <mono/utils/mono-counters.h>
46 #include <mono/utils/mono-string.h>
47 #include <mono/utils/mono-error-internals.h>
48 #include <mono/utils/mono-logger-internals.h>
49 #include <mono/utils/mono-memory-model.h>
50 #include <mono/utils/atomic.h>
51 #include <mono/utils/unlocked.h>
52 #include <mono/utils/bsearch.h>
53 #include <mono/utils/checked-build.h>
58 extern gint32 mono_inflated_methods_size
;
60 /* Function supplied by the runtime to find classes by name using information from the AOT file */
61 static MonoGetClassFromName get_class_from_name
= NULL
;
63 static gboolean
can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
);
65 static char* mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
);
66 static guint32
mono_field_resolve_flags (MonoClassField
*field
);
68 static MonoProperty
* mono_class_get_property_from_name_internal (MonoClass
*klass
, const char *name
);
70 static gboolean
mono_class_is_subclass_of_internal (MonoClass
*klass
, MonoClass
*klassc
, gboolean check_interfaces
);
72 GENERATE_GET_CLASS_WITH_CACHE (valuetype
, "System", "ValueType")
73 GENERATE_TRY_GET_CLASS_WITH_CACHE (handleref
, "System.Runtime.InteropServices", "HandleRef")
77 mono_method_get_image (MonoMethod
*method
)
79 return m_class_get_image (method
->klass
);
83 * mono_class_from_typeref:
84 * \param image a MonoImage
85 * \param type_token a TypeRef token
87 * Creates the \c MonoClass* structure representing the type defined by
88 * the typeref token valid inside \p image.
89 * \returns The \c MonoClass* representing the typeref token, or NULL if it could
93 mono_class_from_typeref (MonoImage
*image
, guint32 type_token
)
96 MonoClass
*klass
= mono_class_from_typeref_checked (image
, type_token
, error
);
97 g_assert (mono_error_ok (error
)); /*FIXME proper error handling*/
102 * mono_class_from_typeref_checked:
103 * \param image a MonoImage
104 * \param type_token a TypeRef token
105 * \param error error return code, if any.
107 * Creates the \c MonoClass* structure representing the type defined by
108 * the typeref token valid inside \p image.
110 * \returns The \c MonoClass* representing the typeref token, NULL if it could
111 * not be loaded with the \p error value filled with the information about the
115 mono_class_from_typeref_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
117 guint32 cols
[MONO_TYPEREF_SIZE
];
118 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
120 const char *name
, *nspace
;
121 MonoClass
*res
= NULL
;
126 if (!mono_verifier_verify_typeref_row (image
, (type_token
& 0xffffff) - 1, error
))
129 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
131 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
132 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
134 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
135 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
136 case MONO_RESOLUTION_SCOPE_MODULE
:
138 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
139 This is not the observed behavior of existing implementations.
140 The defacto behavior is that it's just a typedef in disguise.
142 /* a typedef in disguise */
143 res
= mono_class_from_name_checked (image
, nspace
, name
, error
);
146 case MONO_RESOLUTION_SCOPE_MODULEREF
:
147 module
= mono_image_load_module_checked (image
, idx
, error
);
149 res
= mono_class_from_name_checked (module
, nspace
, name
, error
);
152 case MONO_RESOLUTION_SCOPE_TYPEREF
: {
153 MonoClass
*enclosing
;
156 if (idx
== mono_metadata_token_index (type_token
)) {
157 mono_error_set_bad_image (error
, image
, "Image with self-referencing typeref token %08x.", type_token
);
161 enclosing
= mono_class_from_typeref_checked (image
, MONO_TOKEN_TYPE_REF
| idx
, error
);
162 return_val_if_nok (error
, NULL
);
164 GList
*nested_classes
= mono_class_get_nested_classes_property (enclosing
);
165 if (m_class_is_nested_classes_inited (enclosing
) && nested_classes
) {
166 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
167 for (tmp
= nested_classes
; tmp
; tmp
= tmp
->next
) {
168 res
= (MonoClass
*)tmp
->data
;
169 if (strcmp (m_class_get_name (res
), name
) == 0)
173 MonoImage
*enclosing_image
= m_class_get_image (enclosing
);
174 guint32 enclosing_type_token
= m_class_get_type_token (enclosing
);
175 /* Don't call mono_class_init_internal as we might've been called by it recursively */
176 int i
= mono_metadata_nesting_typedef (enclosing_image
, enclosing_type_token
, 1);
178 guint32 class_nested
= mono_metadata_decode_row_col (&enclosing_image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, MONO_NESTED_CLASS_NESTED
);
179 guint32 string_offset
= mono_metadata_decode_row_col (&enclosing_image
->tables
[MONO_TABLE_TYPEDEF
], class_nested
- 1, MONO_TYPEDEF_NAME
);
180 const char *nname
= mono_metadata_string_heap (enclosing_image
, string_offset
);
182 if (strcmp (nname
, name
) == 0)
183 return mono_class_create_from_typedef (enclosing_image
, MONO_TOKEN_TYPE_DEF
| class_nested
, error
);
185 i
= mono_metadata_nesting_typedef (enclosing_image
, enclosing_type_token
, i
+ 1);
188 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx
, nspace
, name
, image
->name
);
191 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
195 if (idx
> image
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
) {
196 mono_error_set_bad_image (error
, image
, "Image with invalid assemblyref token %08x.", idx
);
200 if (!image
->references
|| !image
->references
[idx
- 1])
201 mono_assembly_load_reference (image
, idx
- 1);
202 g_assert (image
->references
[idx
- 1]);
204 /* If the assembly did not load, register this as a type load exception */
205 if (image
->references
[idx
- 1] == REFERENCE_MISSING
){
206 MonoAssemblyName aname
;
209 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
210 human_name
= mono_stringify_assembly_name (&aname
);
211 gboolean refonly
= FALSE
;
213 refonly
= mono_asmctx_get_kind (&image
->assembly
->context
) == MONO_ASMCTX_REFONLY
;
214 mono_error_set_simple_file_not_found (error
, human_name
, refonly
);
219 res
= mono_class_from_name_checked (image
->references
[idx
- 1]->image
, nspace
, name
, error
);
222 /* Generic case, should be avoided for when a better error is possible. */
223 if (!res
&& mono_error_ok (error
)) {
224 char *name
= mono_class_name_from_token (image
, type_token
);
225 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
226 mono_error_set_type_load_name (error
, name
, assembly
, "Could not resolve type with token %08x from typeref (expected class '%s' in assembly '%s')", type_token
, name
, assembly
);
233 mono_image_memdup (MonoImage
*image
, void *data
, guint size
)
235 void *res
= mono_image_alloc (image
, size
);
236 memcpy (res
, data
, size
);
240 /* Copy everything mono_metadata_free_array free. */
242 mono_dup_array_type (MonoImage
*image
, MonoArrayType
*a
)
245 a
= (MonoArrayType
*)mono_image_memdup (image
, a
, sizeof (MonoArrayType
));
247 a
->sizes
= (int *)mono_image_memdup (image
, a
->sizes
, a
->numsizes
* sizeof (int));
249 a
->lobounds
= (int *)mono_image_memdup (image
, a
->lobounds
, a
->numlobounds
* sizeof (int));
251 a
= (MonoArrayType
*)g_memdup (a
, sizeof (MonoArrayType
));
253 a
->sizes
= (int *)g_memdup (a
->sizes
, a
->numsizes
* sizeof (int));
255 a
->lobounds
= (int *)g_memdup (a
->lobounds
, a
->numlobounds
* sizeof (int));
260 /* Copy everything mono_metadata_free_method_signature free. */
262 mono_metadata_signature_deep_dup (MonoImage
*image
, MonoMethodSignature
*sig
)
266 sig
= mono_metadata_signature_dup_full (image
, sig
);
268 sig
->ret
= mono_metadata_type_dup (image
, sig
->ret
);
269 for (i
= 0; i
< sig
->param_count
; ++i
)
270 sig
->params
[i
] = mono_metadata_type_dup (image
, sig
->params
[i
]);
276 _mono_type_get_assembly_name (MonoClass
*klass
, GString
*str
)
278 MonoAssembly
*ta
= m_class_get_image (klass
)->assembly
;
281 name
= mono_stringify_assembly_name (&ta
->aname
);
282 g_string_append_printf (str
, ", %s", name
);
287 mono_type_name_check_byref (MonoType
*type
, GString
*str
)
290 g_string_append_c (str
, '&');
294 * mono_identifier_escape_type_name_chars:
295 * \param str a destination string
296 * \param identifier an IDENTIFIER in internal form
300 * The displayed form of the identifier is appended to str.
302 * The displayed form of an identifier has the characters ,+&*[]\
303 * that have special meaning in type names escaped with a preceeding
304 * backslash (\) character.
307 mono_identifier_escape_type_name_chars (GString
* str
, const char* identifier
)
313 // reserve space for common case: there will be no escaped characters.
314 g_string_set_size(str
, n
+ strlen(identifier
));
315 g_string_set_size(str
, n
);
317 for (const char* s
= identifier
; *s
!= 0 ; s
++) {
326 g_string_append_c (str
, '\\');
327 g_string_append_c (str
, *s
);
330 g_string_append_c (str
, *s
);
338 mono_type_get_name_recurse (MonoType
*type
, GString
*str
, gboolean is_recursed
,
339 MonoTypeNameFormat format
)
343 switch (type
->type
) {
344 case MONO_TYPE_ARRAY
: {
345 int i
, rank
= type
->data
.array
->rank
;
346 MonoTypeNameFormat nested_format
;
348 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
349 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
351 mono_type_get_name_recurse (
352 m_class_get_byval_arg (type
->data
.array
->eklass
), str
, FALSE
, nested_format
);
353 g_string_append_c (str
, '[');
355 g_string_append_c (str
, '*');
356 for (i
= 1; i
< rank
; i
++)
357 g_string_append_c (str
, ',');
358 g_string_append_c (str
, ']');
360 mono_type_name_check_byref (type
, str
);
362 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
363 _mono_type_get_assembly_name (type
->data
.array
->eklass
, str
);
366 case MONO_TYPE_SZARRAY
: {
367 MonoTypeNameFormat nested_format
;
369 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
370 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
372 mono_type_get_name_recurse (
373 m_class_get_byval_arg (type
->data
.klass
), str
, FALSE
, nested_format
);
374 g_string_append (str
, "[]");
376 mono_type_name_check_byref (type
, str
);
378 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
379 _mono_type_get_assembly_name (type
->data
.klass
, str
);
382 case MONO_TYPE_PTR
: {
383 MonoTypeNameFormat nested_format
;
385 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
386 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
388 mono_type_get_name_recurse (
389 type
->data
.type
, str
, FALSE
, nested_format
);
390 g_string_append_c (str
, '*');
392 mono_type_name_check_byref (type
, str
);
394 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
395 _mono_type_get_assembly_name (mono_class_from_mono_type_internal (type
->data
.type
), str
);
400 if (!mono_generic_param_name (type
->data
.generic_param
))
401 g_string_append_printf (str
, "%s%d", type
->type
== MONO_TYPE_VAR
? "!" : "!!", type
->data
.generic_param
->num
);
403 g_string_append (str
, mono_generic_param_name (type
->data
.generic_param
));
405 mono_type_name_check_byref (type
, str
);
409 klass
= mono_class_from_mono_type_internal (type
);
410 if (m_class_get_nested_in (klass
)) {
411 mono_type_get_name_recurse (
412 m_class_get_byval_arg (m_class_get_nested_in (klass
)), str
, TRUE
, format
);
413 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
414 g_string_append_c (str
, '.');
416 g_string_append_c (str
, '+');
417 } else if (*m_class_get_name_space (klass
)) {
418 const char *klass_name_space
= m_class_get_name_space (klass
);
419 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
420 g_string_append (str
, klass_name_space
);
422 mono_identifier_escape_type_name_chars (str
, klass_name_space
);
423 g_string_append_c (str
, '.');
425 const char *klass_name
= m_class_get_name (klass
);
426 if (format
== MONO_TYPE_NAME_FORMAT_IL
) {
427 const char *s
= strchr (klass_name
, '`');
428 gssize len
= s
? (s
- klass_name
) : (gssize
)strlen (klass_name
);
429 g_string_append_len (str
, klass_name
, len
);
431 mono_identifier_escape_type_name_chars (str
, klass_name
);
435 if (mono_class_is_ginst (klass
)) {
436 MonoGenericClass
*gclass
= mono_class_get_generic_class (klass
);
437 MonoGenericInst
*inst
= gclass
->context
.class_inst
;
438 MonoTypeNameFormat nested_format
;
441 nested_format
= format
== MONO_TYPE_NAME_FORMAT_FULL_NAME
?
442 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
: format
;
444 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
445 g_string_append_c (str
, '<');
447 g_string_append_c (str
, '[');
448 for (i
= 0; i
< inst
->type_argc
; i
++) {
449 MonoType
*t
= inst
->type_argv
[i
];
452 g_string_append_c (str
, ',');
453 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
454 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
455 g_string_append_c (str
, '[');
456 mono_type_get_name_recurse (inst
->type_argv
[i
], str
, FALSE
, nested_format
);
457 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
458 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
459 g_string_append_c (str
, ']');
461 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
462 g_string_append_c (str
, '>');
464 g_string_append_c (str
, ']');
465 } else if (mono_class_is_gtd (klass
) &&
466 (format
!= MONO_TYPE_NAME_FORMAT_FULL_NAME
) &&
467 (format
!= MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)) {
470 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
471 g_string_append_c (str
, '<');
473 g_string_append_c (str
, '[');
474 for (i
= 0; i
< mono_class_get_generic_container (klass
)->type_argc
; i
++) {
476 g_string_append_c (str
, ',');
477 g_string_append (str
, mono_generic_container_get_param_info (mono_class_get_generic_container (klass
), i
)->name
);
479 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
480 g_string_append_c (str
, '>');
482 g_string_append_c (str
, ']');
485 mono_type_name_check_byref (type
, str
);
487 if ((format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
488 (type
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
489 _mono_type_get_assembly_name (klass
, str
);
495 * mono_type_get_name_full:
497 * \param format the format for the return string.
500 * \returns The string representation in a number of formats:
502 * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
503 * returned in the format required by \c System.Reflection, this is the
504 * inverse of mono_reflection_parse_type().
506 * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
507 * be used by the IL assembler.
509 * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
511 * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
514 mono_type_get_name_full (MonoType
*type
, MonoTypeNameFormat format
)
518 result
= g_string_new ("");
520 mono_type_get_name_recurse (type
, result
, FALSE
, format
);
522 return g_string_free (result
, FALSE
);
526 * mono_type_get_full_name:
527 * \param class a class
529 * \returns The string representation for type as required by System.Reflection.
530 * The inverse of mono_reflection_parse_type().
533 mono_type_get_full_name (MonoClass
*klass
)
535 return mono_type_get_name_full (m_class_get_byval_arg (klass
), MONO_TYPE_NAME_FORMAT_REFLECTION
);
539 * mono_type_get_name:
541 * \returns The string representation for type as it would be represented in IL code.
544 mono_type_get_name (MonoType
*type
)
546 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_IL
);
550 * mono_type_get_underlying_type:
552 * \returns The \c MonoType for the underlying integer type if \p type
553 * is an enum and byref is false, otherwise the type itself.
556 mono_type_get_underlying_type (MonoType
*type
)
558 if (type
->type
== MONO_TYPE_VALUETYPE
&& m_class_is_enumtype (type
->data
.klass
) && !type
->byref
)
559 return mono_class_enum_basetype_internal (type
->data
.klass
);
560 if (type
->type
== MONO_TYPE_GENERICINST
&& m_class_is_enumtype (type
->data
.generic_class
->container_class
) && !type
->byref
)
561 return mono_class_enum_basetype_internal (type
->data
.generic_class
->container_class
);
566 * mono_class_is_open_constructed_type:
569 * \returns TRUE if type represents a generics open constructed type.
570 * IOW, not all type parameters required for the instantiation have
571 * been provided or it's a generic type definition.
573 * An open constructed type means it's a non realizable type. Not to
574 * be mixed up with an abstract type - we can't cast or dispatch to
575 * an open type, for example.
578 mono_class_is_open_constructed_type (MonoType
*t
)
584 case MONO_TYPE_SZARRAY
:
585 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t
->data
.klass
));
586 case MONO_TYPE_ARRAY
:
587 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t
->data
.array
->eklass
));
589 return mono_class_is_open_constructed_type (t
->data
.type
);
590 case MONO_TYPE_GENERICINST
:
591 return t
->data
.generic_class
->context
.class_inst
->is_open
;
592 case MONO_TYPE_CLASS
:
593 case MONO_TYPE_VALUETYPE
:
594 return mono_class_is_gtd (t
->data
.klass
);
601 This is a simple function to catch the most common bad instances of generic types.
602 Specially those that might lead to further failures in the runtime.
605 mono_type_is_valid_generic_argument (MonoType
*type
)
607 switch (type
->type
) {
609 case MONO_TYPE_TYPEDBYREF
:
611 case MONO_TYPE_VALUETYPE
:
612 return !m_class_is_byreflike (type
->data
.klass
);
619 can_inflate_gparam_with (MonoGenericParam
*gparam
, MonoType
*type
)
621 if (!mono_type_is_valid_generic_argument (type
))
623 /* Avoid inflating gparams with valuetype constraints with ref types during gsharing */
624 MonoGenericParamInfo
*info
= mono_generic_param_info (gparam
);
625 if (info
&& (info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
)) {
626 if (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
) {
627 MonoGenericParam
*inst_gparam
= type
->data
.generic_param
;
628 if (inst_gparam
->gshared_constraint
&& inst_gparam
->gshared_constraint
->type
== MONO_TYPE_OBJECT
)
636 inflate_generic_type (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
640 switch (type
->type
) {
641 case MONO_TYPE_MVAR
: {
643 int num
= mono_type_get_generic_param_num (type
);
644 MonoGenericInst
*inst
= context
->method_inst
;
647 MonoGenericParam
*gparam
= type
->data
.generic_param
;
648 if (num
>= inst
->type_argc
) {
649 const char *pname
= mono_generic_param_name (gparam
);
650 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
651 num
, pname
? pname
: "", inst
->type_argc
);
655 if (!can_inflate_gparam_with (gparam
, inst
->type_argv
[num
])) {
656 const char *pname
= mono_generic_param_name (gparam
);
657 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded with type 0x%x",
658 num
, pname
? pname
: "", inst
->type_argv
[num
]->type
);
662 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
663 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
664 * ->byref and ->attrs from @type are propagated to the returned type.
666 nt
= mono_metadata_type_dup_with_cmods (image
, inst
->type_argv
[num
], type
);
667 nt
->byref
= type
->byref
;
668 nt
->attrs
= type
->attrs
;
671 case MONO_TYPE_VAR
: {
673 int num
= mono_type_get_generic_param_num (type
);
674 MonoGenericInst
*inst
= context
->class_inst
;
677 MonoGenericParam
*gparam
= type
->data
.generic_param
;
678 if (num
>= inst
->type_argc
) {
679 const char *pname
= mono_generic_param_name (gparam
);
680 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
681 num
, pname
? pname
: "", inst
->type_argc
);
684 if (!can_inflate_gparam_with (gparam
, inst
->type_argv
[num
])) {
685 const char *pname
= mono_generic_param_name (gparam
);
686 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded with type 0x%x",
687 num
, pname
? pname
: "", inst
->type_argv
[num
]->type
);
691 nt
= mono_metadata_type_dup_with_cmods (image
, inst
->type_argv
[num
], type
);
692 nt
->byref
= type
->byref
;
693 nt
->attrs
= type
->attrs
;
696 case MONO_TYPE_SZARRAY
: {
697 MonoClass
*eclass
= type
->data
.klass
;
698 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (eclass
), context
, error
);
699 if (!inflated
|| !mono_error_ok (error
))
701 nt
= mono_metadata_type_dup (image
, type
);
702 nt
->data
.klass
= mono_class_from_mono_type_internal (inflated
);
703 mono_metadata_free_type (inflated
);
706 case MONO_TYPE_ARRAY
: {
707 MonoClass
*eclass
= type
->data
.array
->eklass
;
708 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (eclass
), context
, error
);
709 if (!inflated
|| !mono_error_ok (error
))
711 nt
= mono_metadata_type_dup (image
, type
);
712 nt
->data
.array
->eklass
= mono_class_from_mono_type_internal (inflated
);
713 mono_metadata_free_type (inflated
);
716 case MONO_TYPE_GENERICINST
: {
717 MonoGenericClass
*gclass
= type
->data
.generic_class
;
718 MonoGenericInst
*inst
;
720 if (!gclass
->context
.class_inst
->is_open
)
723 inst
= mono_metadata_inflate_generic_inst (gclass
->context
.class_inst
, context
, error
);
724 return_val_if_nok (error
, NULL
);
726 if (inst
!= gclass
->context
.class_inst
)
727 gclass
= mono_metadata_lookup_generic_class (gclass
->container_class
, inst
, gclass
->is_dynamic
);
729 if (gclass
== type
->data
.generic_class
)
732 nt
= mono_metadata_type_dup (image
, type
);
733 nt
->data
.generic_class
= gclass
;
736 case MONO_TYPE_CLASS
:
737 case MONO_TYPE_VALUETYPE
: {
738 MonoClass
*klass
= type
->data
.klass
;
739 MonoGenericContainer
*container
= mono_class_try_get_generic_container (klass
);
740 MonoGenericInst
*inst
;
741 MonoGenericClass
*gclass
= NULL
;
747 /* We can't use context->class_inst directly, since it can have more elements */
748 inst
= mono_metadata_inflate_generic_inst (container
->context
.class_inst
, context
, error
);
749 return_val_if_nok (error
, NULL
);
751 if (inst
== container
->context
.class_inst
)
754 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, image_is_dynamic (m_class_get_image (klass
)));
756 nt
= mono_metadata_type_dup (image
, type
);
757 nt
->type
= MONO_TYPE_GENERICINST
;
758 nt
->data
.generic_class
= gclass
;
761 case MONO_TYPE_PTR
: {
762 MonoType
*nt
, *inflated
= inflate_generic_type (image
, type
->data
.type
, context
, error
);
763 if (!inflated
|| !mono_error_ok (error
))
765 nt
= mono_metadata_type_dup (image
, type
);
766 nt
->data
.type
= inflated
;
776 mono_generic_class_get_context (MonoGenericClass
*gclass
)
778 return &gclass
->context
;
782 mono_class_get_context (MonoClass
*klass
)
784 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
785 return gklass
? mono_generic_class_get_context (gklass
) : NULL
;
789 * mono_class_inflate_generic_type_with_mempool:
790 * @mempool: a mempool
792 * @context: a generics context
793 * @error: error context
795 * The same as mono_class_inflate_generic_type, but allocates the MonoType
796 * from mempool if it is non-NULL. If it is NULL, the MonoType is
797 * allocated on the heap and is owned by the caller.
798 * The returned type can potentially be the same as TYPE, so it should not be
799 * modified by the caller, and it should be freed using mono_metadata_free_type ().
802 mono_class_inflate_generic_type_with_mempool (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
804 MonoType
*inflated
= NULL
;
808 inflated
= inflate_generic_type (image
, type
, context
, error
);
809 return_val_if_nok (error
, NULL
);
812 MonoType
*shared
= mono_metadata_get_shared_type (type
);
814 if (shared
&& !type
->has_cmods
) {
817 return mono_metadata_type_dup (image
, type
);
821 UnlockedIncrement (&mono_stats
.inflated_type_count
);
826 * mono_class_inflate_generic_type:
828 * \param context a generics context
829 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
831 * If \p type is a generic type and \p context is not NULL, instantiate it using the
832 * generics context \p context.
834 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
835 * on the heap and is owned by the caller. Returns NULL on error.
838 mono_class_inflate_generic_type (MonoType
*type
, MonoGenericContext
*context
)
842 result
= mono_class_inflate_generic_type_checked (type
, context
, error
);
843 mono_error_cleanup (error
);
848 * mono_class_inflate_generic_type:
850 * @context: a generics context
851 * @error: error context to use
853 * If @type is a generic type and @context is not NULL, instantiate it using the
854 * generics context @context.
856 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
857 * on the heap and is owned by the caller.
860 mono_class_inflate_generic_type_checked (MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
862 return mono_class_inflate_generic_type_with_mempool (NULL
, type
, context
, error
);
866 * mono_class_inflate_generic_type_no_copy:
868 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
872 mono_class_inflate_generic_type_no_copy (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
874 MonoType
*inflated
= NULL
;
878 inflated
= inflate_generic_type (image
, type
, context
, error
);
879 return_val_if_nok (error
, NULL
);
885 UnlockedIncrement (&mono_stats
.inflated_type_count
);
890 * mono_class_inflate_generic_class:
892 * Inflate the class @gklass with @context. Set @error on failure.
895 mono_class_inflate_generic_class_checked (MonoClass
*gklass
, MonoGenericContext
*context
, MonoError
*error
)
900 inflated
= mono_class_inflate_generic_type_checked (m_class_get_byval_arg (gklass
), context
, error
);
901 return_val_if_nok (error
, NULL
);
903 res
= mono_class_from_mono_type_internal (inflated
);
904 mono_metadata_free_type (inflated
);
909 static MonoGenericContext
910 inflate_generic_context (MonoGenericContext
*context
, MonoGenericContext
*inflate_with
, MonoError
*error
)
912 MonoGenericInst
*class_inst
= NULL
;
913 MonoGenericInst
*method_inst
= NULL
;
914 MonoGenericContext res
= { NULL
, NULL
};
918 if (context
->class_inst
) {
919 class_inst
= mono_metadata_inflate_generic_inst (context
->class_inst
, inflate_with
, error
);
920 if (!mono_error_ok (error
))
924 if (context
->method_inst
) {
925 method_inst
= mono_metadata_inflate_generic_inst (context
->method_inst
, inflate_with
, error
);
926 if (!mono_error_ok (error
))
930 res
.class_inst
= class_inst
;
931 res
.method_inst
= method_inst
;
937 * mono_class_inflate_generic_method:
938 * \param method a generic method
939 * \param context a generics context
941 * Instantiate the generic method \p method using the generics context \p context.
943 * \returns The new instantiated method
946 mono_class_inflate_generic_method (MonoMethod
*method
, MonoGenericContext
*context
)
950 MonoMethod
*res
= mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
951 mono_error_assert_msg_ok (error
, "Could not inflate generic method");
956 mono_class_inflate_generic_method_checked (MonoMethod
*method
, MonoGenericContext
*context
, MonoError
*error
)
958 return mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
962 * mono_class_inflate_generic_method_full_checked:
963 * Instantiate method \p method with the generic context \p context.
964 * On failure returns NULL and sets \p error.
966 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
967 * Use mono_method_signature_internal () and mono_method_get_header () to get the correct values.
970 mono_class_inflate_generic_method_full_checked (MonoMethod
*method
, MonoClass
*klass_hint
, MonoGenericContext
*context
, MonoError
*error
)
973 MonoMethodInflated
*iresult
, *cached
;
974 MonoMethodSignature
*sig
;
975 MonoGenericContext tmp_context
;
979 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
980 while (method
->is_inflated
) {
981 MonoGenericContext
*method_context
= mono_method_get_context (method
);
982 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
984 tmp_context
= inflate_generic_context (method_context
, context
, error
);
985 return_val_if_nok (error
, NULL
);
987 context
= &tmp_context
;
989 if (mono_metadata_generic_context_equal (method_context
, context
))
992 method
= imethod
->declaring
;
996 * A method only needs to be inflated if the context has argument for which it is
999 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1000 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1003 if (!((method
->is_generic
&& context
->method_inst
) ||
1004 (mono_class_is_gtd (method
->klass
) && context
->class_inst
)))
1007 iresult
= g_new0 (MonoMethodInflated
, 1);
1008 iresult
->context
= *context
;
1009 iresult
->declaring
= method
;
1011 if (!context
->method_inst
&& method
->is_generic
)
1012 iresult
->context
.method_inst
= mono_method_get_generic_container (method
)->context
.method_inst
;
1014 if (!context
->class_inst
) {
1015 g_assert (!mono_class_is_ginst (iresult
->declaring
->klass
));
1016 if (mono_class_is_gtd (iresult
->declaring
->klass
))
1017 iresult
->context
.class_inst
= mono_class_get_generic_container (iresult
->declaring
->klass
)->context
.class_inst
;
1019 /* This can happen with some callers like mono_object_get_virtual_method_internal () */
1020 if (!mono_class_is_gtd (iresult
->declaring
->klass
) && !mono_class_is_ginst (iresult
->declaring
->klass
))
1021 iresult
->context
.class_inst
= NULL
;
1023 MonoImageSet
*set
= mono_metadata_get_image_set_for_method (iresult
);
1026 mono_image_set_lock (set
);
1027 cached
= (MonoMethodInflated
*)g_hash_table_lookup (set
->gmethod_cache
, iresult
);
1028 mono_image_set_unlock (set
);
1032 return (MonoMethod
*)cached
;
1035 UnlockedIncrement (&mono_stats
.inflated_method_count
);
1037 UnlockedAdd (&mono_inflated_methods_size
, sizeof (MonoMethodInflated
));
1039 sig
= mono_method_signature_internal (method
);
1041 char *name
= mono_type_get_full_name (method
->klass
);
1042 mono_error_set_bad_image (error
, mono_method_get_image (method
), "Could not resolve signature of method %s:%s", name
, method
->name
);
1048 memcpy (&iresult
->method
.pinvoke
, method
, sizeof (MonoMethodPInvoke
));
1050 memcpy (&iresult
->method
.method
, method
, sizeof (MonoMethod
));
1053 result
= (MonoMethod
*) iresult
;
1054 result
->is_inflated
= TRUE
;
1055 result
->is_generic
= FALSE
;
1056 result
->sre_method
= FALSE
;
1057 result
->signature
= NULL
;
1059 if (method
->wrapper_type
) {
1060 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)method
;
1061 MonoMethodWrapper
*resw
= (MonoMethodWrapper
*)result
;
1062 int len
= GPOINTER_TO_INT (((void**)mw
->method_data
) [0]);
1064 resw
->method_data
= (void **)g_malloc (sizeof (gpointer
) * (len
+ 1));
1065 memcpy (resw
->method_data
, mw
->method_data
, sizeof (gpointer
) * (len
+ 1));
1068 if (iresult
->context
.method_inst
) {
1069 MonoGenericInst
*method_inst
= iresult
->context
.method_inst
;
1070 /* Set the generic_container of the result to the generic_container of method */
1071 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
1073 if (generic_container
&& method_inst
== generic_container
->context
.method_inst
) {
1074 result
->is_generic
= 1;
1075 mono_method_set_generic_container (result
, generic_container
);
1078 /* Check that the method is not instantiated with any invalid types */
1079 for (int i
= 0; i
< method_inst
->type_argc
; i
++) {
1080 if (!mono_type_is_valid_generic_argument (method_inst
->type_argv
[i
])) {
1081 mono_error_set_bad_image (error
, mono_method_get_image (method
), "MVAR %d cannot be expanded with type 0x%x",
1082 i
, method_inst
->type_argv
[i
]->type
);
1089 MonoGenericClass
*gklass_hint
= mono_class_try_get_generic_class (klass_hint
);
1090 if (gklass_hint
&& (gklass_hint
->container_class
!= method
->klass
|| gklass_hint
->context
.class_inst
!= context
->class_inst
))
1094 if (mono_class_is_gtd (method
->klass
))
1095 result
->klass
= klass_hint
;
1097 if (!result
->klass
) {
1098 MonoType
*inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (method
->klass
), context
, error
);
1099 if (!mono_error_ok (error
))
1102 result
->klass
= inflated
? mono_class_from_mono_type_internal (inflated
) : method
->klass
;
1104 mono_metadata_free_type (inflated
);
1108 * FIXME: This should hold, but it doesn't:
1110 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1111 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1112 * g_assert (result->is_generic);
1115 * Fixing this here causes other things to break, hence a very
1116 * ugly hack in mini-trampolines.c - see
1117 * is_generic_method_definition().
1121 mono_image_set_lock (set
);
1122 cached
= (MonoMethodInflated
*)g_hash_table_lookup (set
->gmethod_cache
, iresult
);
1124 g_hash_table_insert (set
->gmethod_cache
, iresult
, iresult
);
1125 iresult
->owner
= set
;
1128 mono_image_set_unlock (set
);
1130 return (MonoMethod
*)cached
;
1138 * mono_get_inflated_method:
1140 * Obsolete. We keep it around since it's mentioned in the public API.
1143 mono_get_inflated_method (MonoMethod
*method
)
1149 * mono_method_get_context_general:
1151 * @uninflated: handle uninflated methods?
1153 * Returns the generic context of a method or NULL if it doesn't have
1154 * one. For an inflated method that's the context stored in the
1155 * method. Otherwise it's in the method's generic container or in the
1156 * generic container of the method's class.
1159 mono_method_get_context_general (MonoMethod
*method
, gboolean uninflated
)
1161 if (method
->is_inflated
) {
1162 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1163 return &imethod
->context
;
1167 if (method
->is_generic
)
1168 return &(mono_method_get_generic_container (method
)->context
);
1169 if (mono_class_is_gtd (method
->klass
))
1170 return &mono_class_get_generic_container (method
->klass
)->context
;
1175 * mono_method_get_context:
1178 * Returns the generic context for method if it's inflated, otherwise
1182 mono_method_get_context (MonoMethod
*method
)
1184 return mono_method_get_context_general (method
, FALSE
);
1188 * mono_method_get_generic_container:
1190 * Returns the generic container of METHOD, which should be a generic method definition.
1191 * Returns NULL if METHOD is not a generic method definition.
1192 * LOCKING: Acquires the loader lock.
1194 MonoGenericContainer
*
1195 mono_method_get_generic_container (MonoMethod
*method
)
1197 MonoGenericContainer
*container
;
1199 if (!method
->is_generic
)
1202 container
= (MonoGenericContainer
*)mono_image_property_lookup (mono_method_get_image (method
), method
, MONO_METHOD_PROP_GENERIC_CONTAINER
);
1203 g_assert (container
);
1209 * mono_method_set_generic_container:
1211 * Sets the generic container of METHOD to CONTAINER.
1212 * LOCKING: Acquires the image lock.
1215 mono_method_set_generic_container (MonoMethod
*method
, MonoGenericContainer
* container
)
1217 g_assert (method
->is_generic
);
1219 mono_image_property_insert (mono_method_get_image (method
), method
, MONO_METHOD_PROP_GENERIC_CONTAINER
, container
);
1223 * mono_class_find_enum_basetype:
1224 * \param class The enum class
1226 * Determine the basetype of an enum by iterating through its fields. We do this
1227 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1230 mono_class_find_enum_basetype (MonoClass
*klass
, MonoError
*error
)
1232 MonoGenericContainer
*container
= NULL
;
1233 MonoImage
*image
= m_class_get_image (klass
);
1234 const int top
= mono_class_get_field_count (klass
);
1235 int i
, first_field_idx
;
1237 g_assert (m_class_is_enumtype (klass
));
1241 container
= mono_class_try_get_generic_container (klass
);
1242 if (mono_class_is_ginst (klass
)) {
1243 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1245 container
= mono_class_get_generic_container (gklass
);
1246 g_assert (container
);
1250 * Fetch all the field information.
1252 first_field_idx
= mono_class_get_first_field_idx (klass
);
1253 for (i
= 0; i
< top
; i
++){
1255 guint32 cols
[MONO_FIELD_SIZE
];
1256 int idx
= first_field_idx
+ i
;
1259 /* first_field_idx and idx points into the fieldptr table */
1260 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
1262 if (cols
[MONO_FIELD_FLAGS
] & FIELD_ATTRIBUTE_STATIC
) //no need to decode static fields
1265 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
))
1268 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
1269 mono_metadata_decode_value (sig
, &sig
);
1270 /* FIELD signature == 0x06 */
1272 mono_error_set_bad_image (error
, image
, "Invalid field signature %x, expected 0x6 but got %x", cols
[MONO_FIELD_SIGNATURE
], *sig
);
1276 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
1280 if (mono_class_is_ginst (klass
)) {
1281 //FIXME do we leak here?
1282 ftype
= mono_class_inflate_generic_type_checked (ftype
, mono_class_get_context (klass
), error
);
1283 if (!mono_error_ok (error
))
1285 ftype
->attrs
= cols
[MONO_FIELD_FLAGS
];
1290 mono_error_set_type_load_class (error
, klass
, "Could not find base type");
1297 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1300 mono_type_has_exceptions (MonoType
*type
)
1302 switch (type
->type
) {
1303 case MONO_TYPE_CLASS
:
1304 case MONO_TYPE_VALUETYPE
:
1305 case MONO_TYPE_SZARRAY
:
1306 return mono_class_has_failure (type
->data
.klass
);
1307 case MONO_TYPE_ARRAY
:
1308 return mono_class_has_failure (type
->data
.array
->eklass
);
1309 case MONO_TYPE_GENERICINST
:
1310 return mono_class_has_failure (mono_class_create_generic_inst (type
->data
.generic_class
));
1317 mono_error_set_for_class_failure (MonoError
*oerror
, const MonoClass
*klass
)
1319 g_assert (mono_class_has_failure (klass
));
1320 MonoErrorBoxed
*box
= mono_class_get_exception_data ((MonoClass
*)klass
);
1321 mono_error_set_from_boxed (oerror
, box
);
1327 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1331 mono_class_alloc (MonoClass
*klass
, int size
)
1333 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1335 return mono_image_set_alloc (gklass
->owner
, size
);
1337 return mono_image_alloc (m_class_get_image (klass
), size
);
1341 (mono_class_alloc0
) (MonoClass
*klass
, int size
)
1345 res
= mono_class_alloc (klass
, size
);
1346 memset (res
, 0, size
);
1350 #define mono_class_new0(klass,struct_type, n_structs) \
1351 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1354 * mono_class_set_failure_causedby_class:
1355 * \param klass the class that is failing
1356 * \param caused_by the class that caused the failure
1357 * \param msg Why \p klass is failing.
1359 * If \p caused_by has a failure, sets a TypeLoadException failure on
1360 * \p klass with message "\p msg, due to: {\p caused_by message}".
1362 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1365 mono_class_set_type_load_failure_causedby_class (MonoClass
*klass
, const MonoClass
*caused_by
, const gchar
* msg
)
1367 if (mono_class_has_failure (caused_by
)) {
1368 ERROR_DECL (cause_error
);
1369 mono_error_set_for_class_failure (cause_error
, caused_by
);
1370 mono_class_set_type_load_failure (klass
, "%s, due to: %s", msg
, mono_error_get_message (cause_error
));
1371 mono_error_cleanup (cause_error
);
1380 * mono_type_get_basic_type_from_generic:
1383 * Returns a closed type corresponding to the possibly open type
1387 mono_type_get_basic_type_from_generic (MonoType
*type
)
1389 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1390 if (!type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
) &&
1391 (!type
->data
.generic_param
->gshared_constraint
|| type
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_OBJECT
))
1392 return mono_get_object_type ();
1397 * mono_class_get_method_by_index:
1399 * Returns klass->methods [index], initializing klass->methods if neccesary.
1401 * LOCKING: Acquires the loader lock.
1404 mono_class_get_method_by_index (MonoClass
*klass
, int index
)
1408 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1409 /* Avoid calling setup_methods () if possible */
1410 if (gklass
&& !m_class_get_methods (klass
)) {
1413 m
= mono_class_inflate_generic_method_full_checked (
1414 m_class_get_methods (gklass
->container_class
) [index
], klass
, mono_class_get_context (klass
), error
);
1415 g_assert (mono_error_ok (error
)); /* FIXME don't swallow the error */
1417 * If setup_methods () is called later for this class, no duplicates are created,
1418 * since inflate_generic_method guarantees that only one instance of a method
1419 * is created for each context.
1422 mono_class_setup_methods (klass);
1423 g_assert (m == klass->methods [index]);
1427 mono_class_setup_methods (klass
);
1428 if (mono_class_has_failure (klass
)) /*FIXME do proper error handling*/
1430 g_assert (index
>= 0 && index
< mono_class_get_method_count (klass
));
1431 return m_class_get_methods (klass
) [index
];
1436 * mono_class_get_inflated_method:
1437 * \param klass an inflated class
1438 * \param method a method of \p klass's generic definition
1439 * \param error set on error
1441 * Given an inflated class \p klass and a method \p method which should be a
1442 * method of \p klass's generic definition, return the inflated method
1443 * corresponding to \p method.
1445 * On failure sets \p error and returns NULL.
1448 mono_class_get_inflated_method (MonoClass
*klass
, MonoMethod
*method
, MonoError
*error
)
1450 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1453 g_assert (method
->klass
== gklass
);
1455 mono_class_setup_methods (gklass
);
1456 if (mono_class_has_failure (gklass
)) {
1457 mono_error_set_for_class_failure (error
, gklass
);
1461 MonoMethod
**gklass_methods
= m_class_get_methods (gklass
);
1462 mcount
= mono_class_get_method_count (gklass
);
1463 for (i
= 0; i
< mcount
; ++i
) {
1464 if (gklass_methods
[i
] == method
) {
1465 MonoMethod
*inflated_method
= NULL
;
1466 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
1467 if (klass_methods
) {
1468 inflated_method
= klass_methods
[i
];
1470 inflated_method
= mono_class_inflate_generic_method_full_checked (gklass_methods
[i
], klass
, mono_class_get_context (klass
), error
);
1471 return_val_if_nok (error
, NULL
);
1473 g_assert (inflated_method
);
1474 return inflated_method
;
1478 g_assert_not_reached ();
1482 * mono_class_get_vtable_entry:
1484 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
1485 * LOCKING: Acquires the loader lock.
1488 mono_class_get_vtable_entry (MonoClass
*klass
, int offset
)
1492 if (m_class_get_rank (klass
) == 1) {
1493 MonoClass
*klass_parent
= m_class_get_parent (klass
);
1495 * szarrays do not overwrite any methods of Array, so we can avoid
1496 * initializing their vtables in some cases.
1498 mono_class_setup_vtable (klass_parent
);
1499 if (offset
< m_class_get_vtable_size (klass_parent
))
1500 return m_class_get_vtable (klass_parent
) [offset
];
1503 if (mono_class_is_ginst (klass
)) {
1505 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1506 mono_class_setup_vtable (gklass
);
1507 m
= m_class_get_vtable (gklass
) [offset
];
1509 m
= mono_class_inflate_generic_method_full_checked (m
, klass
, mono_class_get_context (klass
), error
);
1510 g_assert (mono_error_ok (error
)); /* FIXME don't swallow this error */
1512 mono_class_setup_vtable (klass
);
1513 if (mono_class_has_failure (klass
))
1515 m
= m_class_get_vtable (klass
) [offset
];
1522 * mono_class_get_vtable_size:
1524 * Return the vtable size for KLASS.
1527 mono_class_get_vtable_size (MonoClass
*klass
)
1529 mono_class_setup_vtable (klass
);
1531 return m_class_get_vtable_size (klass
);
1535 collect_implemented_interfaces_aux (MonoClass
*klass
, GPtrArray
**res
, GHashTable
**ifaces
, MonoError
*error
)
1540 mono_class_setup_interfaces (klass
, error
);
1541 return_if_nok (error
);
1543 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
1544 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
1545 ic
= klass_interfaces
[i
];
1548 *res
= g_ptr_array_new ();
1549 if (*ifaces
== NULL
)
1550 *ifaces
= g_hash_table_new (NULL
, NULL
);
1551 if (g_hash_table_lookup (*ifaces
, ic
))
1553 /* A gparam is not an implemented interface for the purposes of
1554 * mono_class_get_implemented_interfaces */
1555 if (mono_class_is_gparam (ic
))
1557 g_ptr_array_add (*res
, ic
);
1558 g_hash_table_insert (*ifaces
, ic
, ic
);
1559 mono_class_init_internal (ic
);
1560 if (mono_class_has_failure (ic
)) {
1561 mono_error_set_type_load_class (error
, ic
, "Error Loading class");
1565 collect_implemented_interfaces_aux (ic
, res
, ifaces
, error
);
1566 return_if_nok (error
);
1571 mono_class_get_implemented_interfaces (MonoClass
*klass
, MonoError
*error
)
1573 GPtrArray
*res
= NULL
;
1574 GHashTable
*ifaces
= NULL
;
1576 collect_implemented_interfaces_aux (klass
, &res
, &ifaces
, error
);
1578 g_hash_table_destroy (ifaces
);
1579 if (!mono_error_ok (error
)) {
1581 g_ptr_array_free (res
, TRUE
);
1588 compare_interface_ids (const void *p_key
, const void *p_element
)
1590 MonoClass
*key
= (MonoClass
*)p_key
;
1591 MonoClass
*element
= *(MonoClass
**)p_element
;
1593 return (m_class_get_interface_id (key
) - m_class_get_interface_id (element
));
1596 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
1598 mono_class_interface_offset (MonoClass
*klass
, MonoClass
*itf
)
1600 MonoClass
**klass_interfaces_packed
= m_class_get_interfaces_packed (klass
);
1601 MonoClass
**result
= (MonoClass
**)mono_binary_search (
1603 klass_interfaces_packed
,
1604 m_class_get_interface_offsets_count (klass
),
1605 sizeof (MonoClass
*),
1606 compare_interface_ids
);
1608 return m_class_get_interface_offsets_packed (klass
) [result
- klass_interfaces_packed
];
1615 * mono_class_interface_offset_with_variance:
1617 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
1618 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
1620 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
1622 * FIXME figure out MS disambiguation rules and fix this function.
1625 mono_class_interface_offset_with_variance (MonoClass
*klass
, MonoClass
*itf
, gboolean
*non_exact_match
)
1627 int i
= mono_class_interface_offset (klass
, itf
);
1628 *non_exact_match
= FALSE
;
1632 int klass_interface_offsets_count
= m_class_get_interface_offsets_count (klass
);
1634 if (m_class_is_array_special_interface (itf
) && m_class_get_rank (klass
) < 2) {
1635 MonoClass
*gtd
= mono_class_get_generic_type_definition (itf
);
1638 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1639 if (mono_class_is_variant_compatible (itf
, m_class_get_interfaces_packed (klass
) [i
], FALSE
)) {
1641 *non_exact_match
= TRUE
;
1647 return m_class_get_interface_offsets_packed (klass
) [found
];
1649 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1650 if (mono_class_get_generic_type_definition (m_class_get_interfaces_packed (klass
) [i
]) == gtd
) {
1652 *non_exact_match
= TRUE
;
1660 return m_class_get_interface_offsets_packed (klass
) [found
];
1663 if (!mono_class_has_variant_generic_params (itf
))
1666 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1667 if (mono_class_is_variant_compatible (itf
, m_class_get_interfaces_packed (klass
) [i
], FALSE
)) {
1668 *non_exact_match
= TRUE
;
1669 return m_class_get_interface_offsets_packed (klass
) [i
];
1678 * mono_method_get_vtable_slot:
1680 * Returns method->slot, computing it if neccesary. Return -1 on failure.
1681 * LOCKING: Acquires the loader lock.
1683 * FIXME Use proper MonoError machinery here.
1686 mono_method_get_vtable_slot (MonoMethod
*method
)
1688 if (method
->slot
== -1) {
1689 mono_class_setup_vtable (method
->klass
);
1690 if (mono_class_has_failure (method
->klass
))
1692 if (method
->slot
== -1) {
1696 if (!mono_class_is_ginst (method
->klass
)) {
1697 g_assert (method
->is_inflated
);
1698 return mono_method_get_vtable_slot (((MonoMethodInflated
*)method
)->declaring
);
1701 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
1702 g_assert (mono_class_is_ginst (method
->klass
));
1703 gklass
= mono_class_get_generic_class (method
->klass
)->container_class
;
1704 mono_class_setup_methods (method
->klass
);
1705 MonoMethod
**klass_methods
= m_class_get_methods (method
->klass
);
1706 g_assert (klass_methods
);
1707 mcount
= mono_class_get_method_count (method
->klass
);
1708 for (i
= 0; i
< mcount
; ++i
) {
1709 if (klass_methods
[i
] == method
)
1712 g_assert (i
< mcount
);
1713 g_assert (m_class_get_methods (gklass
));
1714 method
->slot
= m_class_get_methods (gklass
) [i
]->slot
;
1716 g_assert (method
->slot
!= -1);
1718 return method
->slot
;
1722 * mono_method_get_vtable_index:
1723 * \param method a method
1725 * Returns the index into the runtime vtable to access the method or,
1726 * in the case of a virtual generic method, the virtual generic method
1727 * thunk. Returns -1 on failure.
1729 * FIXME Use proper MonoError machinery here.
1732 mono_method_get_vtable_index (MonoMethod
*method
)
1734 if (method
->is_inflated
&& (method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
1735 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
1736 if (imethod
->declaring
->is_generic
)
1737 return mono_method_get_vtable_slot (imethod
->declaring
);
1739 return mono_method_get_vtable_slot (method
);
1743 * mono_class_has_finalizer:
1745 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
1748 * LOCKING: Acquires the loader lock;
1751 mono_class_has_finalizer (MonoClass
*klass
)
1753 if (!m_class_is_has_finalize_inited (klass
))
1754 mono_class_setup_has_finalizer (klass
);
1756 return m_class_has_finalize (klass
);
1760 mono_is_corlib_image (MonoImage
*image
)
1762 return image
== mono_defaults
.corlib
;
1766 /** Is klass a Nullable<T> ginst? */
1768 mono_class_is_nullable (MonoClass
*klass
)
1770 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1771 return gklass
&& gklass
->container_class
== mono_defaults
.generic_nullable_class
;
1775 /** if klass is T? return T */
1777 mono_class_get_nullable_param (MonoClass
*klass
)
1779 g_assert (mono_class_is_nullable (klass
));
1780 return mono_class_from_mono_type_internal (mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0]);
1784 mono_type_is_primitive (MonoType
*type
)
1786 return (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_R8
) ||
1787 type
-> type
== MONO_TYPE_I
|| type
->type
== MONO_TYPE_U
;
1791 get_image_for_container (MonoGenericContainer
*container
)
1794 if (container
->is_anonymous
) {
1795 result
= container
->owner
.image
;
1798 if (container
->is_method
) {
1799 MonoMethod
*method
= container
->owner
.method
;
1800 g_assert_checked (method
);
1801 klass
= method
->klass
;
1803 klass
= container
->owner
.klass
;
1805 g_assert_checked (klass
);
1806 result
= m_class_get_image (klass
);
1813 mono_get_image_for_generic_param (MonoGenericParam
*param
)
1815 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
1816 g_assert_checked (container
);
1817 return get_image_for_container (container
);
1820 // Make a string in the designated image consisting of a single integer.
1821 #define INT_STRING_SIZE 16
1823 mono_make_generic_name_string (MonoImage
*image
, int num
)
1825 char *name
= (char *)mono_image_alloc0 (image
, INT_STRING_SIZE
);
1826 g_snprintf (name
, INT_STRING_SIZE
, "%d", num
);
1831 * mono_class_from_generic_parameter:
1832 * \param param Parameter to find/construct a class for.
1833 * \param arg2 Is ignored.
1834 * \param arg3 Is ignored.
1837 mono_class_from_generic_parameter (MonoGenericParam
*param
, MonoImage
*arg2 G_GNUC_UNUSED
, gboolean arg3 G_GNUC_UNUSED
)
1839 return mono_class_create_generic_parameter (param
);
1843 * mono_ptr_class_get:
1846 mono_ptr_class_get (MonoType
*type
)
1848 return mono_class_create_ptr (type
);
1852 * mono_class_from_mono_type:
1853 * \param type describes the type to return
1854 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
1857 mono_class_from_mono_type (MonoType
*type
)
1860 MONO_ENTER_GC_UNSAFE
;
1861 result
= mono_class_from_mono_type_internal (type
);
1862 MONO_EXIT_GC_UNSAFE
;
1867 mono_class_from_mono_type_internal (MonoType
*type
)
1869 switch (type
->type
) {
1870 case MONO_TYPE_OBJECT
:
1871 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.object_class
;
1872 case MONO_TYPE_VOID
:
1873 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.void_class
;
1874 case MONO_TYPE_BOOLEAN
:
1875 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.boolean_class
;
1876 case MONO_TYPE_CHAR
:
1877 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.char_class
;
1879 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.sbyte_class
;
1881 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.byte_class
;
1883 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int16_class
;
1885 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint16_class
;
1887 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int32_class
;
1889 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint32_class
;
1891 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int_class
;
1893 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint_class
;
1895 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int64_class
;
1897 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint64_class
;
1899 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.single_class
;
1901 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.double_class
;
1902 case MONO_TYPE_STRING
:
1903 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.string_class
;
1904 case MONO_TYPE_TYPEDBYREF
:
1905 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.typed_reference_class
;
1906 case MONO_TYPE_ARRAY
:
1907 return mono_class_create_bounded_array (type
->data
.array
->eklass
, type
->data
.array
->rank
, TRUE
);
1909 return mono_class_create_ptr (type
->data
.type
);
1910 case MONO_TYPE_FNPTR
:
1911 return mono_class_create_fnptr (type
->data
.method
);
1912 case MONO_TYPE_SZARRAY
:
1913 return mono_class_create_array (type
->data
.klass
, 1);
1914 case MONO_TYPE_CLASS
:
1915 case MONO_TYPE_VALUETYPE
:
1916 return type
->data
.klass
;
1917 case MONO_TYPE_GENERICINST
:
1918 return mono_class_create_generic_inst (type
->data
.generic_class
);
1919 case MONO_TYPE_MVAR
:
1921 return mono_class_create_generic_parameter (type
->data
.generic_param
);
1923 g_warning ("mono_class_from_mono_type_internal: implement me 0x%02x\n", type
->type
);
1924 g_assert_not_reached ();
1927 // Yes, this returns NULL, even if it is documented as not doing so, but there
1928 // is no way for the code to make it this far, due to the assert above.
1933 * mono_type_retrieve_from_typespec
1934 * \param image context where the image is created
1935 * \param type_spec typespec token
1936 * \param context the generic context used to evaluate generic instantiations in
1939 mono_type_retrieve_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, gboolean
*did_inflate
, MonoError
*error
)
1941 MonoType
*t
= mono_type_create_from_typespec_checked (image
, type_spec
, error
);
1943 *did_inflate
= FALSE
;
1948 if (context
&& (context
->class_inst
|| context
->method_inst
)) {
1949 MonoType
*inflated
= inflate_generic_type (NULL
, t
, context
, error
);
1951 if (!mono_error_ok (error
)) {
1957 *did_inflate
= TRUE
;
1964 * mono_class_create_from_typespec
1965 * \param image context where the image is created
1966 * \param type_spec typespec token
1967 * \param context the generic context used to evaluate generic instantiations in
1970 mono_class_create_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, MonoError
*error
)
1973 gboolean inflated
= FALSE
;
1974 MonoType
*t
= mono_type_retrieve_from_typespec (image
, type_spec
, context
, &inflated
, error
);
1975 return_val_if_nok (error
, NULL
);
1976 ret
= mono_class_from_mono_type_internal (t
);
1978 mono_metadata_free_type (t
);
1983 * mono_bounded_array_class_get:
1984 * \param element_class element class
1985 * \param rank the dimension of the array class
1986 * \param bounded whenever the array has non-zero bounds
1987 * \returns A class object describing the array with element type \p element_type and
1988 * dimension \p rank.
1991 mono_bounded_array_class_get (MonoClass
*eclass
, guint32 rank
, gboolean bounded
)
1993 return mono_class_create_bounded_array (eclass
, rank
, bounded
);
1997 * mono_array_class_get:
1998 * \param element_class element class
1999 * \param rank the dimension of the array class
2000 * \returns A class object describing the array with element type \p element_type and
2001 * dimension \p rank.
2004 mono_array_class_get (MonoClass
*eclass
, guint32 rank
)
2006 return mono_class_create_array (eclass
, rank
);
2010 * mono_class_instance_size:
2011 * \param klass a class
2013 * Use to get the size of a class in bytes.
2015 * \returns The size of an object instance
2018 mono_class_instance_size (MonoClass
*klass
)
2020 if (!m_class_is_size_inited (klass
))
2021 mono_class_init_internal (klass
);
2023 return m_class_get_instance_size (klass
);
2027 * mono_class_min_align:
2028 * \param klass a class
2030 * Use to get the computed minimum alignment requirements for the specified class.
2032 * Returns: minimum alignment requirements
2035 mono_class_min_align (MonoClass
*klass
)
2037 if (!m_class_is_size_inited (klass
))
2038 mono_class_init_internal (klass
);
2040 return m_class_get_min_align (klass
);
2044 * mono_class_data_size:
2045 * \param klass a class
2047 * \returns The size of the static class data
2050 mono_class_data_size (MonoClass
*klass
)
2052 if (!m_class_is_inited (klass
))
2053 mono_class_init_internal (klass
);
2054 /* This can happen with dynamically created types */
2055 if (!m_class_is_fields_inited (klass
))
2056 mono_class_setup_fields (klass
);
2058 /* in arrays, sizes.class_size is unioned with element_size
2059 * and arrays have no static fields
2061 if (m_class_get_rank (klass
))
2063 return m_class_get_sizes (klass
).class_size
;
2067 * Auxiliary routine to mono_class_get_field
2069 * Takes a field index instead of a field token.
2071 static MonoClassField
*
2072 mono_class_get_field_idx (MonoClass
*klass
, int idx
)
2074 mono_class_setup_fields (klass
);
2075 if (mono_class_has_failure (klass
))
2079 int first_field_idx
= mono_class_get_first_field_idx (klass
);
2080 int fcount
= mono_class_get_field_count (klass
);
2081 MonoImage
*klass_image
= m_class_get_image (klass
);
2082 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
2083 if (klass_image
->uncompressed_metadata
) {
2085 * first_field_idx points to the FieldPtr table, while idx points into the
2086 * Field table, so we have to do a search.
2088 /*FIXME this is broken for types with multiple fields with the same name.*/
2089 const char *name
= mono_metadata_string_heap (klass_image
, mono_metadata_decode_row_col (&klass_image
->tables
[MONO_TABLE_FIELD
], idx
, MONO_FIELD_NAME
));
2092 for (i
= 0; i
< fcount
; ++i
)
2093 if (mono_field_get_name (&klass_fields
[i
]) == name
)
2094 return &klass_fields
[i
];
2095 g_assert_not_reached ();
2098 if ((idx
>= first_field_idx
) && (idx
< first_field_idx
+ fcount
)){
2099 return &klass_fields
[idx
- first_field_idx
];
2103 klass
= m_class_get_parent (klass
);
2109 * mono_class_get_field:
2110 * \param class the class to lookup the field.
2111 * \param field_token the field token
2113 * \returns A \c MonoClassField representing the type and offset of
2114 * the field, or a NULL value if the field does not belong to this
2118 mono_class_get_field (MonoClass
*klass
, guint32 field_token
)
2120 int idx
= mono_metadata_token_index (field_token
);
2122 g_assert (mono_metadata_token_code (field_token
) == MONO_TOKEN_FIELD_DEF
);
2124 return mono_class_get_field_idx (klass
, idx
- 1);
2128 * mono_class_get_field_from_name:
2129 * \param klass the class to lookup the field.
2130 * \param name the field name
2132 * Search the class \p klass and its parents for a field with the name \p name.
2134 * \returns The \c MonoClassField pointer of the named field or NULL
2137 mono_class_get_field_from_name (MonoClass
*klass
, const char *name
)
2139 MonoClassField
*result
;
2140 MONO_ENTER_GC_UNSAFE
;
2141 result
= mono_class_get_field_from_name_full (klass
, name
, NULL
);
2142 MONO_EXIT_GC_UNSAFE
;
2147 * mono_class_get_field_from_name_full:
2148 * \param klass the class to lookup the field.
2149 * \param name the field name
2150 * \param type the type of the fields. This optional.
2152 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
2154 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
2155 * of its generic type definition.
2157 * \returns The MonoClassField pointer of the named field or NULL
2160 mono_class_get_field_from_name_full (MonoClass
*klass
, const char *name
, MonoType
*type
)
2162 MONO_REQ_GC_UNSAFE_MODE
;
2166 mono_class_setup_fields (klass
);
2167 if (mono_class_has_failure (klass
))
2171 int fcount
= mono_class_get_field_count (klass
);
2172 for (i
= 0; i
< fcount
; ++i
) {
2173 MonoClassField
*field
= &m_class_get_fields (klass
) [i
];
2175 if (strcmp (name
, mono_field_get_name (field
)) != 0)
2179 MonoType
*field_type
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
)->type
;
2180 if (!mono_metadata_type_equal_full (type
, field_type
, TRUE
))
2185 klass
= m_class_get_parent (klass
);
2191 * mono_class_get_field_token:
2192 * \param field the field we need the token of
2194 * Get the token of a field. Note that the tokesn is only valid for the image
2195 * the field was loaded from. Don't use this function for fields in dynamic types.
2197 * \returns The token representing the field in the image it was loaded from.
2200 mono_class_get_field_token (MonoClassField
*field
)
2202 MonoClass
*klass
= field
->parent
;
2205 mono_class_setup_fields (klass
);
2208 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
2211 int first_field_idx
= mono_class_get_first_field_idx (klass
);
2212 int fcount
= mono_class_get_field_count (klass
);
2213 for (i
= 0; i
< fcount
; ++i
) {
2214 if (&klass_fields
[i
] == field
) {
2215 int idx
= first_field_idx
+ i
+ 1;
2217 if (m_class_get_image (klass
)->uncompressed_metadata
)
2218 idx
= mono_metadata_translate_token_index (m_class_get_image (klass
), MONO_TABLE_FIELD
, idx
);
2219 return mono_metadata_make_token (MONO_TABLE_FIELD
, idx
);
2222 klass
= m_class_get_parent (klass
);
2225 g_assert_not_reached ();
2230 mono_field_get_index (MonoClassField
*field
)
2232 int index
= field
- m_class_get_fields (field
->parent
);
2233 g_assert (index
>= 0 && index
< mono_class_get_field_count (field
->parent
));
2239 * mono_class_get_field_default_value:
2241 * Return the default value of the field as a pointer into the metadata blob.
2244 mono_class_get_field_default_value (MonoClassField
*field
, MonoTypeEnum
*def_type
)
2247 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
2249 MonoClass
*klass
= field
->parent
;
2250 MonoFieldDefaultValue
*def_values
;
2252 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
);
2254 def_values
= mono_class_get_field_def_values (klass
);
2256 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
2258 mono_class_set_field_def_values (klass
, def_values
);
2261 field_index
= mono_field_get_index (field
);
2263 if (!def_values
[field_index
].data
) {
2264 MonoImage
*field_parent_image
= m_class_get_image (field
->parent
);
2265 cindex
= mono_metadata_get_constant_index (field_parent_image
, mono_class_get_field_token (field
), 0);
2269 g_assert (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
));
2271 mono_metadata_decode_row (&field_parent_image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
2272 def_values
[field_index
].def_type
= (MonoTypeEnum
)constant_cols
[MONO_CONSTANT_TYPE
];
2273 mono_memory_barrier ();
2274 def_values
[field_index
].data
= (const char *)mono_metadata_blob_heap (field_parent_image
, constant_cols
[MONO_CONSTANT_VALUE
]);
2277 *def_type
= def_values
[field_index
].def_type
;
2278 return def_values
[field_index
].data
;
2282 mono_property_get_index (MonoProperty
*prop
)
2284 MonoClassPropertyInfo
*info
= mono_class_get_property_info (prop
->parent
);
2285 int index
= prop
- info
->properties
;
2287 g_assert (index
>= 0 && index
< info
->count
);
2293 * mono_class_get_property_default_value:
2295 * Return the default value of the field as a pointer into the metadata blob.
2298 mono_class_get_property_default_value (MonoProperty
*property
, MonoTypeEnum
*def_type
)
2301 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
2302 MonoClass
*klass
= property
->parent
;
2303 MonoImage
*klass_image
= m_class_get_image (klass
);
2305 g_assert (property
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
);
2307 * We don't cache here because it is not used by C# so it's quite rare, but
2308 * we still do the lookup in klass->ext because that is where the data
2309 * is stored for dynamic assemblies.
2312 if (image_is_dynamic (klass_image
)) {
2313 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
2314 int prop_index
= mono_property_get_index (property
);
2315 if (info
->def_values
&& info
->def_values
[prop_index
].data
) {
2316 *def_type
= info
->def_values
[prop_index
].def_type
;
2317 return info
->def_values
[prop_index
].data
;
2321 cindex
= mono_metadata_get_constant_index (klass_image
, mono_class_get_property_token (property
), 0);
2325 mono_metadata_decode_row (&klass_image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
2326 *def_type
= (MonoTypeEnum
)constant_cols
[MONO_CONSTANT_TYPE
];
2327 return (const char *)mono_metadata_blob_heap (klass_image
, constant_cols
[MONO_CONSTANT_VALUE
]);
2331 * mono_class_get_event_token:
2334 mono_class_get_event_token (MonoEvent
*event
)
2336 MonoClass
*klass
= event
->parent
;
2340 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
2342 for (i
= 0; i
< info
->count
; ++i
) {
2343 if (&info
->events
[i
] == event
)
2344 return mono_metadata_make_token (MONO_TABLE_EVENT
, info
->first
+ i
+ 1);
2347 klass
= m_class_get_parent (klass
);
2350 g_assert_not_reached ();
2355 * mono_class_get_property_from_name:
2356 * \param klass a class
2357 * \param name name of the property to lookup in the specified class
2359 * Use this method to lookup a property in a class
2360 * \returns the \c MonoProperty with the given name, or NULL if the property
2361 * does not exist on the \p klass.
2364 mono_class_get_property_from_name (MonoClass
*klass
, const char *name
)
2366 MonoProperty
*result
= NULL
;
2367 MONO_ENTER_GC_UNSAFE
;
2368 result
= mono_class_get_property_from_name_internal (klass
, name
);
2369 MONO_EXIT_GC_UNSAFE
;
2374 mono_class_get_property_from_name_internal (MonoClass
*klass
, const char *name
)
2376 MONO_REQ_GC_UNSAFE_MODE
;
2379 gpointer iter
= NULL
;
2380 while ((p
= mono_class_get_properties (klass
, &iter
))) {
2381 if (! strcmp (name
, p
->name
))
2384 klass
= m_class_get_parent (klass
);
2390 * mono_class_get_property_token:
2391 * \param prop MonoProperty to query
2393 * \returns The ECMA token for the specified property.
2396 mono_class_get_property_token (MonoProperty
*prop
)
2398 MonoClass
*klass
= prop
->parent
;
2402 gpointer iter
= NULL
;
2403 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
2404 while ((p
= mono_class_get_properties (klass
, &iter
))) {
2405 if (&info
->properties
[i
] == prop
)
2406 return mono_metadata_make_token (MONO_TABLE_PROPERTY
, info
->first
+ i
+ 1);
2410 klass
= m_class_get_parent (klass
);
2413 g_assert_not_reached ();
2418 * mono_class_name_from_token:
2421 mono_class_name_from_token (MonoImage
*image
, guint32 type_token
)
2423 const char *name
, *nspace
;
2424 if (image_is_dynamic (image
))
2425 return g_strdup_printf ("DynamicType 0x%08x", type_token
);
2427 switch (type_token
& 0xff000000){
2428 case MONO_TOKEN_TYPE_DEF
: {
2429 guint32 cols
[MONO_TYPEDEF_SIZE
];
2430 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2431 guint tidx
= mono_metadata_token_index (type_token
);
2433 if (tidx
> tt
->rows
)
2434 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2436 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
2437 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2438 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2439 if (strlen (nspace
) == 0)
2440 return g_strdup_printf ("%s", name
);
2442 return g_strdup_printf ("%s.%s", nspace
, name
);
2445 case MONO_TOKEN_TYPE_REF
: {
2447 guint32 cols
[MONO_TYPEREF_SIZE
];
2448 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2449 guint tidx
= mono_metadata_token_index (type_token
);
2452 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2454 if (!mono_verifier_verify_typeref_row (image
, tidx
- 1, error
)) {
2455 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (error
));
2456 mono_error_cleanup (error
);
2460 mono_metadata_decode_row (t
, tidx
-1, cols
, MONO_TYPEREF_SIZE
);
2461 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
2462 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
2463 if (strlen (nspace
) == 0)
2464 return g_strdup_printf ("%s", name
);
2466 return g_strdup_printf ("%s.%s", nspace
, name
);
2469 case MONO_TOKEN_TYPE_SPEC
:
2470 return g_strdup_printf ("Typespec 0x%08x", type_token
);
2472 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2477 mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
)
2479 if (image_is_dynamic (image
))
2480 return g_strdup_printf ("DynamicAssembly %s", image
->name
);
2482 switch (type_token
& 0xff000000){
2483 case MONO_TOKEN_TYPE_DEF
:
2484 if (image
->assembly
)
2485 return mono_stringify_assembly_name (&image
->assembly
->aname
);
2486 else if (image
->assembly_name
)
2487 return g_strdup (image
->assembly_name
);
2488 return g_strdup_printf ("%s", image
->name
? image
->name
: "[Could not resolve assembly name");
2489 case MONO_TOKEN_TYPE_REF
: {
2491 MonoAssemblyName aname
;
2492 guint32 cols
[MONO_TYPEREF_SIZE
];
2493 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2494 guint32 idx
= mono_metadata_token_index (type_token
);
2497 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2499 if (!mono_verifier_verify_typeref_row (image
, idx
- 1, error
)) {
2500 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (error
));
2501 mono_error_cleanup (error
);
2504 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPEREF_SIZE
);
2506 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
2507 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
2508 case MONO_RESOLUTION_SCOPE_MODULE
:
2510 return g_strdup ("");
2511 case MONO_RESOLUTION_SCOPE_MODULEREF
:
2513 return g_strdup ("");
2514 case MONO_RESOLUTION_SCOPE_TYPEREF
:
2516 return g_strdup ("");
2517 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
2518 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
2519 return mono_stringify_assembly_name (&aname
);
2521 g_assert_not_reached ();
2525 case MONO_TOKEN_TYPE_SPEC
:
2527 return g_strdup ("");
2529 g_assert_not_reached ();
2536 * mono_class_get_full:
2537 * \param image the image where the class resides
2538 * \param type_token the token for the class
2539 * \param context the generic context used to evaluate generic instantiations in
2540 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
2541 * \returns The \c MonoClass that represents \p type_token in \p image
2544 mono_class_get_full (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
)
2548 klass
= mono_class_get_checked (image
, type_token
, error
);
2550 if (klass
&& context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
2551 klass
= mono_class_inflate_generic_class_checked (klass
, context
, error
);
2553 mono_error_assert_ok (error
);
2559 mono_class_get_and_inflate_typespec_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
2564 klass
= mono_class_get_checked (image
, type_token
, error
);
2566 if (klass
&& context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
2567 klass
= mono_class_inflate_generic_class_checked (klass
, context
, error
);
2572 * mono_class_get_checked:
2573 * \param image the image where the class resides
2574 * \param type_token the token for the class
2575 * \param error error object to return any error
2577 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
2580 mono_class_get_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
2582 MonoClass
*klass
= NULL
;
2586 if (image_is_dynamic (image
)) {
2587 int table
= mono_metadata_token_table (type_token
);
2589 if (table
!= MONO_TABLE_TYPEDEF
&& table
!= MONO_TABLE_TYPEREF
&& table
!= MONO_TABLE_TYPESPEC
) {
2590 mono_error_set_bad_image (error
, image
,"Bad token table for dynamic image: %x", table
);
2593 klass
= (MonoClass
*)mono_lookup_dynamic_token (image
, type_token
, NULL
, error
);
2597 switch (type_token
& 0xff000000){
2598 case MONO_TOKEN_TYPE_DEF
:
2599 klass
= mono_class_create_from_typedef (image
, type_token
, error
);
2601 case MONO_TOKEN_TYPE_REF
:
2602 klass
= mono_class_from_typeref_checked (image
, type_token
, error
);
2604 case MONO_TOKEN_TYPE_SPEC
:
2605 klass
= mono_class_create_from_typespec (image
, type_token
, NULL
, error
);
2608 mono_error_set_bad_image (error
, image
, "Unknown type token %x", type_token
& 0xff000000);
2612 /* Generic case, should be avoided for when a better error is possible. */
2613 if (!klass
&& mono_error_ok (error
)) {
2614 char *name
= mono_class_name_from_token (image
, type_token
);
2615 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
2616 mono_error_set_type_load_name (error
, name
, assembly
, "Could not resolve type with token %08x (expected class '%s' in assembly '%s')", type_token
, name
, assembly
);
2624 * mono_type_get_checked:
2625 * \param image the image where the type resides
2626 * \param type_token the token for the type
2627 * \param context the generic context used to evaluate generic instantiations in
2628 * \param error Error handling context
2630 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
2632 * \returns The MonoType that represents \p type_token in \p image
2635 mono_type_get_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
2637 MonoType
*type
= NULL
;
2638 gboolean inflated
= FALSE
;
2642 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
2643 if (image_is_dynamic (image
)) {
2644 MonoClass
*klass
= (MonoClass
*)mono_lookup_dynamic_token (image
, type_token
, context
, error
);
2645 return_val_if_nok (error
, NULL
);
2646 return m_class_get_byval_arg (klass
);
2649 if ((type_token
& 0xff000000) != MONO_TOKEN_TYPE_SPEC
) {
2650 MonoClass
*klass
= mono_class_get_checked (image
, type_token
, error
);
2654 if (m_class_has_failure (klass
)) {
2655 mono_error_set_for_class_failure (error
, klass
);
2658 return m_class_get_byval_arg (klass
);
2661 type
= mono_type_retrieve_from_typespec (image
, type_token
, context
, &inflated
, error
);
2668 MonoType
*tmp
= type
;
2669 type
= m_class_get_byval_arg (mono_class_from_mono_type_internal (type
));
2670 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
2671 * A MonoClass::_byval_arg of a generic type definion has type CLASS.
2672 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with _byval_arg.
2674 * The long term solution is to chaise this places and make then set MonoType::type correctly.
2676 if (type
->type
!= tmp
->type
)
2679 mono_metadata_free_type (tmp
);
2686 * \param image image where the class token will be looked up.
2687 * \param type_token a type token from the image
2688 * \returns the \c MonoClass with the given \p type_token on the \p image
2691 mono_class_get (MonoImage
*image
, guint32 type_token
)
2695 MonoClass
*result
= mono_class_get_checked (image
, type_token
, error
);
2696 mono_error_assert_ok (error
);
2701 * mono_image_init_name_cache:
2703 * Initializes the class name cache stored in image->name_cache.
2705 * LOCKING: Acquires the corresponding image lock.
2708 mono_image_init_name_cache (MonoImage
*image
)
2710 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2711 guint32 cols
[MONO_TYPEDEF_SIZE
];
2714 guint32 i
, visib
, nspace_index
;
2715 GHashTable
*name_cache2
, *nspace_table
, *the_name_cache
;
2717 if (image
->name_cache
)
2720 the_name_cache
= g_hash_table_new (g_str_hash
, g_str_equal
);
2722 if (image_is_dynamic (image
)) {
2723 mono_image_lock (image
);
2724 if (image
->name_cache
) {
2725 /* Somebody initialized it before us */
2726 g_hash_table_destroy (the_name_cache
);
2728 mono_atomic_store_release (&image
->name_cache
, the_name_cache
);
2730 mono_image_unlock (image
);
2734 /* Temporary hash table to avoid lookups in the nspace_table */
2735 name_cache2
= g_hash_table_new (NULL
, NULL
);
2737 for (i
= 1; i
<= t
->rows
; ++i
) {
2738 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
2739 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
2741 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
2742 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
2744 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
2746 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2747 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2749 nspace_index
= cols
[MONO_TYPEDEF_NAMESPACE
];
2750 nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
2751 if (!nspace_table
) {
2752 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2753 g_hash_table_insert (the_name_cache
, (char*)nspace
, nspace_table
);
2754 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
2757 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (i
));
2760 /* Load type names from EXPORTEDTYPES table */
2762 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
2763 guint32 cols
[MONO_EXP_TYPE_SIZE
];
2766 for (i
= 0; i
< t
->rows
; ++i
) {
2767 mono_metadata_decode_row (t
, i
, cols
, MONO_EXP_TYPE_SIZE
);
2769 guint32 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
2770 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_EXP_TYPE
)
2774 name
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAME
]);
2775 nspace
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAMESPACE
]);
2777 nspace_index
= cols
[MONO_EXP_TYPE_NAMESPACE
];
2778 nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
2779 if (!nspace_table
) {
2780 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2781 g_hash_table_insert (the_name_cache
, (char*)nspace
, nspace_table
);
2782 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
2785 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE
, i
+ 1)));
2789 g_hash_table_destroy (name_cache2
);
2791 mono_image_lock (image
);
2792 if (image
->name_cache
) {
2793 /* Somebody initialized it before us */
2794 g_hash_table_destroy (the_name_cache
);
2796 mono_atomic_store_release (&image
->name_cache
, the_name_cache
);
2798 mono_image_unlock (image
);
2801 /*FIXME Only dynamic assemblies should allow this operation.*/
2803 * mono_image_add_to_name_cache:
2806 mono_image_add_to_name_cache (MonoImage
*image
, const char *nspace
,
2807 const char *name
, guint32 index
)
2809 GHashTable
*nspace_table
;
2810 GHashTable
*name_cache
;
2813 mono_image_init_name_cache (image
);
2814 mono_image_lock (image
);
2816 name_cache
= image
->name_cache
;
2817 if (!(nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache
, nspace
))) {
2818 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2819 g_hash_table_insert (name_cache
, (char *)nspace
, (char *)nspace_table
);
2822 if ((old_index
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, (char*) name
))))
2823 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index
, image
->name
, nspace
, name
);
2825 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (index
));
2827 mono_image_unlock (image
);
2836 find_nocase (gpointer key
, gpointer value
, gpointer user_data
)
2838 char *name
= (char*)key
;
2839 FindUserData
*data
= (FindUserData
*)user_data
;
2841 if (!data
->value
&& (mono_utf8_strcasecmp (name
, (char*)data
->key
) == 0))
2842 data
->value
= value
;
2846 * mono_class_from_name_case:
2847 * \param image The MonoImage where the type is looked up in
2848 * \param name_space the type namespace
2849 * \param name the type short name.
2850 * \deprecated use the mono_class_from_name_case_checked variant instead.
2852 * Obtains a \c MonoClass with a given namespace and a given name which
2853 * is located in the given \c MonoImage. The namespace and name
2854 * lookups are case insensitive.
2857 mono_class_from_name_case (MonoImage
*image
, const char* name_space
, const char *name
)
2860 MonoClass
*res
= mono_class_from_name_case_checked (image
, name_space
, name
, error
);
2861 mono_error_cleanup (error
);
2867 * mono_class_from_name_case_checked:
2868 * \param image The MonoImage where the type is looked up in
2869 * \param name_space the type namespace
2870 * \param name the type short name.
2873 * Obtains a MonoClass with a given namespace and a given name which
2874 * is located in the given MonoImage. The namespace and name
2875 * lookups are case insensitive.
2877 * \returns The MonoClass if the given namespace and name were found, or NULL if it
2878 * was not found. The \p error object will contain information about the problem
2882 mono_class_from_name_case_checked (MonoImage
*image
, const char *name_space
, const char *name
, MonoError
*error
)
2884 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2885 guint32 cols
[MONO_TYPEDEF_SIZE
];
2892 if (image_is_dynamic (image
)) {
2894 FindUserData user_data
;
2896 mono_image_init_name_cache (image
);
2897 mono_image_lock (image
);
2899 user_data
.key
= name_space
;
2900 user_data
.value
= NULL
;
2901 g_hash_table_foreach (image
->name_cache
, find_nocase
, &user_data
);
2903 if (user_data
.value
) {
2904 GHashTable
*nspace_table
= (GHashTable
*)user_data
.value
;
2906 user_data
.key
= name
;
2907 user_data
.value
= NULL
;
2909 g_hash_table_foreach (nspace_table
, find_nocase
, &user_data
);
2911 if (user_data
.value
)
2912 token
= GPOINTER_TO_UINT (user_data
.value
);
2915 mono_image_unlock (image
);
2918 return mono_class_get_checked (image
, MONO_TOKEN_TYPE_DEF
| token
, error
);
2924 /* add a cache if needed */
2925 for (i
= 1; i
<= t
->rows
; ++i
) {
2926 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
2927 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
2929 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
2930 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
2932 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
2934 n
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2935 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2936 if (mono_utf8_strcasecmp (n
, name
) == 0 && mono_utf8_strcasecmp (nspace
, name_space
) == 0)
2937 return mono_class_get_checked (image
, MONO_TOKEN_TYPE_DEF
| i
, error
);
2943 return_nested_in (MonoClass
*klass
, char *nested
)
2946 char *s
= strchr (nested
, '/');
2947 gpointer iter
= NULL
;
2954 while ((found
= mono_class_get_nested_types (klass
, &iter
))) {
2955 if (strcmp (m_class_get_name (found
), nested
) == 0) {
2957 return return_nested_in (found
, s
);
2965 search_modules (MonoImage
*image
, const char *name_space
, const char *name
, MonoError
*error
)
2967 MonoTableInfo
*file_table
= &image
->tables
[MONO_TABLE_FILE
];
2968 MonoImage
*file_image
;
2975 * The EXPORTEDTYPES table only contains public types, so have to search the
2977 * Note: image->modules contains the contents of the MODULEREF table, while
2978 * the real module list is in the FILE table.
2980 for (i
= 0; i
< file_table
->rows
; i
++) {
2981 guint32 cols
[MONO_FILE_SIZE
];
2982 mono_metadata_decode_row (file_table
, i
, cols
, MONO_FILE_SIZE
);
2983 if (cols
[MONO_FILE_FLAGS
] == FILE_CONTAINS_NO_METADATA
)
2986 file_image
= mono_image_load_file_for_image_checked (image
, i
+ 1, error
);
2988 klass
= mono_class_from_name_checked (file_image
, name_space
, name
, error
);
2989 if (klass
|| !is_ok (error
))
2998 mono_class_from_name_checked_aux (MonoImage
*image
, const char* name_space
, const char *name
, GHashTable
* visited_images
, MonoError
*error
)
3000 GHashTable
*nspace_table
;
3001 MonoImage
*loaded_image
;
3010 // Checking visited images avoids stack overflows when cyclic references exist.
3011 if (g_hash_table_lookup (visited_images
, image
))
3014 g_hash_table_insert (visited_images
, image
, GUINT_TO_POINTER(1));
3016 if ((nested
= (char*)strchr (name
, '/'))) {
3017 int pos
= nested
- name
;
3018 int len
= strlen (name
);
3021 memcpy (buf
, name
, len
+ 1);
3023 nested
= buf
+ pos
+ 1;
3027 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
3028 if (get_class_from_name
&& image
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
== 0) {
3029 gboolean res
= get_class_from_name (image
, name_space
, name
, &klass
);
3032 klass
= search_modules (image
, name_space
, name
, error
);
3037 return klass
? return_nested_in (klass
, nested
) : NULL
;
3043 mono_image_init_name_cache (image
);
3044 mono_image_lock (image
);
3046 nspace_table
= (GHashTable
*)g_hash_table_lookup (image
->name_cache
, name_space
);
3049 token
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, name
));
3051 mono_image_unlock (image
);
3053 if (!token
&& image_is_dynamic (image
) && image
->modules
) {
3054 /* Search modules as well */
3055 for (i
= 0; i
< image
->module_count
; ++i
) {
3056 MonoImage
*module
= image
->modules
[i
];
3058 klass
= mono_class_from_name_checked (module
, name_space
, name
, error
);
3059 if (klass
|| !is_ok (error
))
3065 klass
= search_modules (image
, name_space
, name
, error
);
3066 if (klass
|| !is_ok (error
))
3071 if (mono_metadata_token_table (token
) == MONO_TABLE_EXPORTEDTYPE
) {
3072 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3073 guint32 cols
[MONO_EXP_TYPE_SIZE
];
3076 idx
= mono_metadata_token_index (token
);
3078 mono_metadata_decode_row (t
, idx
- 1, cols
, MONO_EXP_TYPE_SIZE
);
3080 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
3081 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
) {
3082 loaded_image
= mono_assembly_load_module_checked (image
->assembly
, impl
>> MONO_IMPLEMENTATION_BITS
, error
);
3085 klass
= mono_class_from_name_checked_aux (loaded_image
, name_space
, name
, visited_images
, error
);
3087 return klass
? return_nested_in (klass
, nested
) : NULL
;
3089 } else if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_ASSEMBLYREF
) {
3090 guint32 assembly_idx
;
3092 assembly_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
3094 mono_assembly_load_reference (image
, assembly_idx
- 1);
3095 g_assert (image
->references
[assembly_idx
- 1]);
3096 if (image
->references
[assembly_idx
- 1] == (gpointer
)-1)
3098 klass
= mono_class_from_name_checked_aux (image
->references
[assembly_idx
- 1]->image
, name_space
, name
, visited_images
, error
);
3100 return klass
? return_nested_in (klass
, nested
) : NULL
;
3103 g_assert_not_reached ();
3107 token
= MONO_TOKEN_TYPE_DEF
| token
;
3109 klass
= mono_class_get_checked (image
, token
, error
);
3111 return return_nested_in (klass
, nested
);
3116 * mono_class_from_name_checked:
3117 * \param image The MonoImage where the type is looked up in
3118 * \param name_space the type namespace
3119 * \param name the type short name.
3121 * Obtains a MonoClass with a given namespace and a given name which
3122 * is located in the given MonoImage.
3124 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
3125 * set if the class was not found or it will return NULL and set the error if there was a loading error.
3128 mono_class_from_name_checked (MonoImage
*image
, const char* name_space
, const char *name
, MonoError
*error
)
3131 GHashTable
*visited_images
;
3133 visited_images
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
3135 klass
= mono_class_from_name_checked_aux (image
, name_space
, name
, visited_images
, error
);
3137 g_hash_table_destroy (visited_images
);
3143 * mono_class_from_name:
3144 * \param image The \c MonoImage where the type is looked up in
3145 * \param name_space the type namespace
3146 * \param name the type short name.
3148 * Obtains a \c MonoClass with a given namespace and a given name which
3149 * is located in the given \c MonoImage.
3151 * To reference nested classes, use the "/" character as a separator.
3152 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
3153 * inside \c Foo, like this: "class Foo { class Bar {} }".
3156 mono_class_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3159 MONO_ENTER_GC_UNSAFE
;
3162 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3163 mono_error_cleanup (error
); /* FIXME Don't swallow the error */
3164 MONO_EXIT_GC_UNSAFE
;
3169 * mono_class_load_from_name:
3170 * \param image The MonoImage where the type is looked up in
3171 * \param name_space the type namespace
3172 * \param name the type short name.
3174 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
3175 * This function should be used by the runtime for critical types to which there's no way to recover but crash
3176 * If they are missing. Thing of System.Object or System.String.
3179 mono_class_load_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3184 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3186 g_error ("Runtime critical type %s.%s not found", name_space
, name
);
3187 mono_error_assertf_ok (error
, "Could not load runtime critical type %s.%s", name_space
, name
);
3192 * mono_class_try_load_from_name:
3193 * \param image The MonoImage where the type is looked up in
3194 * \param name_space the type namespace
3195 * \param name the type short name.
3197 * This function tries to load a type, returning the class was found or NULL otherwise.
3198 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
3200 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
3201 * a type that we would otherwise assume to be available but was not due some error.
3205 mono_class_try_load_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3210 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3211 mono_error_assertf_ok (error
, "Could not load runtime critical type %s.%s", name_space
, name
);
3217 * mono_class_is_subclass_of:
3218 * \param klass class to probe if it is a subclass of another one
3219 * \param klassc the class we suspect is the base class
3220 * \param check_interfaces whether we should perform interface checks
3222 * This method determines whether \p klass is a subclass of \p klassc.
3224 * If the \p check_interfaces flag is set, then if \p klassc is an interface
3225 * this method return TRUE if the \p klass implements the interface or
3226 * if \p klass is an interface, if one of its base classes is \p klass.
3228 * If \p check_interfaces is false, then if \p klass is not an interface,
3229 * it returns TRUE if the \p klass is a subclass of \p klassc.
3231 * if \p klass is an interface and \p klassc is \c System.Object, then this function
3236 mono_class_is_subclass_of (MonoClass
*klass
, MonoClass
*klassc
,
3237 gboolean check_interfaces
)
3240 MONO_ENTER_GC_UNSAFE
;
3241 result
= mono_class_is_subclass_of_internal (klass
, klassc
, check_interfaces
);
3242 MONO_EXIT_GC_UNSAFE
;
3247 mono_class_is_subclass_of_internal (MonoClass
*klass
, MonoClass
*klassc
,
3248 gboolean check_interfaces
)
3250 /* FIXME test for interfaces with variant generic arguments */
3251 mono_class_init_internal (klass
);
3252 mono_class_init_internal (klassc
);
3254 if (check_interfaces
&& MONO_CLASS_IS_INTERFACE_INTERNAL (klassc
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3255 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass
, m_class_get_interface_id (klassc
)))
3257 } else if (check_interfaces
&& MONO_CLASS_IS_INTERFACE_INTERNAL (klassc
) && MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3260 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
3261 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
3262 MonoClass
*ic
= klass_interfaces
[i
];
3267 if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass
) && mono_class_has_parent (klass
, klassc
))
3272 * MS.NET thinks interfaces are a subclass of Object, so we think it as
3275 if (klassc
== mono_defaults
.object_class
)
3282 mono_type_is_generic_argument (MonoType
*type
)
3284 return type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
;
3288 mono_class_has_variant_generic_params (MonoClass
*klass
)
3291 MonoGenericContainer
*container
;
3293 if (!mono_class_is_ginst (klass
))
3296 container
= mono_class_get_generic_container (mono_class_get_generic_class (klass
)->container_class
);
3298 for (i
= 0; i
< container
->type_argc
; ++i
)
3299 if (mono_generic_container_get_param_info (container
, i
)->flags
& (MONO_GEN_PARAM_VARIANT
|MONO_GEN_PARAM_COVARIANT
))
3306 mono_gparam_is_reference_conversible (MonoClass
*target
, MonoClass
*candidate
, gboolean check_for_reference_conv
)
3308 if (target
== candidate
)
3311 if (check_for_reference_conv
&&
3312 mono_type_is_generic_argument (m_class_get_byval_arg (target
)) &&
3313 mono_type_is_generic_argument (m_class_get_byval_arg (candidate
))) {
3314 MonoGenericParam
*gparam
= m_class_get_byval_arg (candidate
)->data
.generic_param
;
3315 MonoGenericParamInfo
*pinfo
= mono_generic_param_info (gparam
);
3317 if (!pinfo
|| (pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0)
3320 if (!mono_class_is_assignable_from_internal (target
, candidate
))
3326 * @container the generic container from the GTD
3327 * @klass: the class to be assigned to
3328 * @oklass: the source class
3330 * Both @klass and @oklass must be instances of the same generic interface.
3332 * Returns: TRUE if @klass can be assigned to a @klass variable
3335 mono_class_is_variant_compatible (MonoClass
*klass
, MonoClass
*oklass
, gboolean check_for_reference_conv
)
3338 MonoType
**klass_argv
, **oklass_argv
;
3339 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3340 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3342 if (klass
== oklass
)
3345 /*Viable candidates are instances of the same generic interface*/
3346 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3349 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3350 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3352 for (j
= 0; j
< container
->type_argc
; ++j
) {
3353 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3354 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3356 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
) || (m_class_is_valuetype (param1_class
) && param1_class
!= param2_class
))
3360 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3361 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3363 if (param1_class
!= param2_class
) {
3364 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3365 if (!mono_gparam_is_reference_conversible (param1_class
, param2_class
, check_for_reference_conv
))
3367 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3368 if (!mono_gparam_is_reference_conversible (param2_class
, param1_class
, check_for_reference_conv
))
3378 mono_gparam_is_assignable_from (MonoClass
*target
, MonoClass
*candidate
)
3380 MonoGenericParam
*gparam
, *ogparam
;
3381 MonoGenericParamInfo
*tinfo
, *cinfo
;
3382 MonoClass
**candidate_class
;
3383 gboolean class_constraint_satisfied
, valuetype_constraint_satisfied
;
3386 if (target
== candidate
)
3388 MonoType
*target_byval_arg
= m_class_get_byval_arg (target
);
3389 MonoType
*candidate_byval_arg
= m_class_get_byval_arg (candidate
);
3390 if (target_byval_arg
->type
!= candidate_byval_arg
->type
)
3393 gparam
= target_byval_arg
->data
.generic_param
;
3394 ogparam
= candidate_byval_arg
->data
.generic_param
;
3395 tinfo
= mono_generic_param_info (gparam
);
3396 cinfo
= mono_generic_param_info (ogparam
);
3398 class_constraint_satisfied
= FALSE
;
3399 valuetype_constraint_satisfied
= FALSE
;
3401 /*candidate must have a super set of target's special constraints*/
3402 tmask
= tinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3403 cmask
= cinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3405 if (cinfo
->constraints
) {
3406 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3407 MonoClass
*cc
= *candidate_class
;
3408 MonoType
*cc_byval_arg
= m_class_get_byval_arg (cc
);
3410 if (mono_type_is_reference (cc_byval_arg
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc
))
3411 class_constraint_satisfied
= TRUE
;
3412 else if (!mono_type_is_reference (cc_byval_arg
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc
))
3413 valuetype_constraint_satisfied
= TRUE
;
3416 class_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) != 0;
3417 valuetype_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0;
3419 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) && !class_constraint_satisfied
)
3421 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) && !valuetype_constraint_satisfied
)
3423 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) && !((cmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) ||
3424 valuetype_constraint_satisfied
)) {
3429 /*candidate type constraints must be a superset of target's*/
3430 if (tinfo
->constraints
) {
3431 MonoClass
**target_class
;
3432 for (target_class
= tinfo
->constraints
; *target_class
; ++target_class
) {
3433 MonoClass
*tc
= *target_class
;
3434 MonoType
*tc_byval_arg
= m_class_get_byval_arg (tc
);
3437 * A constraint from @target might inflate into @candidate itself and in that case we don't need
3438 * check it's constraints since it satisfy the constraint by itself.
3440 if (mono_metadata_type_equal (tc_byval_arg
, candidate_byval_arg
))
3443 if (!cinfo
->constraints
)
3446 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3447 MonoClass
*cc
= *candidate_class
;
3449 if (mono_class_is_assignable_from_internal (tc
, cc
))
3453 * This happens when we have the following:
3455 * Bar<K> where K : IFace
3456 * Foo<T, U> where T : U where U : IFace
3458 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
3461 if (mono_type_is_generic_argument (m_class_get_byval_arg (cc
))) {
3462 if (mono_gparam_is_assignable_from (target
, cc
))
3466 if (!*candidate_class
)
3471 /*candidate itself must have a constraint that satisfy target*/
3472 if (cinfo
->constraints
) {
3473 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3474 MonoClass
*cc
= *candidate_class
;
3475 if (mono_class_is_assignable_from_internal (target
, cc
))
3483 * mono_class_is_assignable_from_internal:
3484 * \param klass the class to be assigned to
3485 * \param oklass the source class
3487 * \returns TRUE if an instance of class \p oklass can be assigned to an
3488 * instance of class \p klass
3491 mono_class_is_assignable_from_internal (MonoClass
*klass
, MonoClass
*oklass
)
3493 gboolean result
= FALSE
;
3495 mono_class_is_assignable_from_checked (klass
, oklass
, &result
, error
);
3496 mono_error_cleanup (error
);
3501 * mono_class_is_assignable_from:
3502 * \param klass the class to be assigned to
3503 * \param oklass the source class
3505 * \returns TRUE if an instance of class \p oklass can be assigned to an
3506 * instance of class \p klass
3509 mono_class_is_assignable_from (MonoClass
*klass
, MonoClass
*oklass
)
3512 MONO_ENTER_GC_UNSAFE
;
3513 result
= mono_class_is_assignable_from_internal (klass
, oklass
);
3514 MONO_EXIT_GC_UNSAFE
;
3519 * mono_class_is_assignable_from_checked:
3520 * \param klass the class to be assigned to
3521 * \param oklass the source class
3522 * \param result set if there was no error
3523 * \param error set if there was an error
3525 * Sets \p result to TRUE if an instance of class \p oklass can be assigned to
3526 * an instance of class \p klass or FALSE if it cannot. On error, no \p error
3527 * is set and \p result is not valid.
3530 mono_class_is_assignable_from_checked (MonoClass
*klass
, MonoClass
*oklass
, gboolean
*result
, MonoError
*error
)
3532 MONO_REQ_GC_UNSAFE_MODE
;
3534 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
3535 if (!m_class_is_inited (klass
))
3536 mono_class_init_internal (klass
);
3538 if (!m_class_is_inited (oklass
))
3539 mono_class_init_internal (oklass
);
3541 if (mono_class_has_failure (klass
) || mono_class_has_failure (oklass
)) {
3546 MonoType
*klass_byval_arg
= m_class_get_byval_arg (klass
);
3547 MonoType
*oklass_byval_arg
= m_class_get_byval_arg (oklass
);
3549 if (mono_type_is_generic_argument (klass_byval_arg
)) {
3550 if (!mono_type_is_generic_argument (oklass_byval_arg
)) {
3554 *result
= mono_gparam_is_assignable_from (klass
, oklass
);
3558 /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
3559 * has a constraint which is a class type:
3562 * class G<T1, T2> where T1 : T2 where T2 : Foo { }
3564 * In this case, Foo is assignable from T1.
3566 if (mono_type_is_generic_argument (oklass_byval_arg
)) {
3567 MonoGenericParam
*gparam
= oklass_byval_arg
->data
.generic_param
;
3568 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
3572 for (i
= 0; constraints
[i
]; ++i
) {
3573 if (mono_class_is_assignable_from_internal (klass
, constraints
[i
])) {
3580 *result
= mono_class_has_parent (oklass
, klass
);
3584 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3586 /* interface_offsets might not be set for dynamic classes */
3587 if (mono_class_get_ref_info_handle (oklass
) && !m_class_get_interface_bitmap (oklass
)) {
3589 * oklass might be a generic type parameter but they have
3590 * interface_offsets set.
3592 gboolean assign_result
= mono_reflection_call_is_assignable_to (oklass
, klass
, error
);
3593 return_if_nok (error
);
3594 *result
= assign_result
;
3597 if (!m_class_get_interface_bitmap (oklass
)) {
3598 /* Happens with generic instances of not-yet created dynamic types */
3602 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass
, m_class_get_interface_id (klass
))) {
3607 if (m_class_is_array_special_interface (klass
) && m_class_get_rank (oklass
) == 1) {
3608 if (mono_class_is_gtd (klass
)) {
3609 /* klass is an array special gtd like
3610 * IList`1<>, and oklass is X[] for some X.
3611 * Moreover we know that X isn't !0 (the gparam
3612 * of IList`1) because in that case we would
3613 * have returned TRUE for
3614 * MONO_CLASS_IMPLEMENTS_INTERFACE, above.
3619 // FIXME: IEnumerator`1 should not be an array special interface.
3620 // The correct fix is to make
3621 // ((IEnumerable<U>) (new T[] {...})).GetEnumerator()
3622 // return an IEnumerator<U> (like .NET does) instead of IEnumerator<T>
3623 // and to stop marking IEnumerable`1 as an array_special_interface.
3624 if (mono_class_get_generic_type_definition (klass
) == mono_defaults
.generic_ienumerator_class
) {
3629 //XXX we could offset this by having the cast target computed at JIT time
3630 //XXX we could go even further and emit a wrapper that would do the extra type check
3631 MonoClass
*iface_klass
= mono_class_from_mono_type_internal (mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0]);
3632 MonoClass
*obj_klass
= m_class_get_cast_class (oklass
); //This gets us the cast class of element type of the array
3634 // If the target we're trying to cast to is a valuetype, we must account of weird valuetype equivalences such as IntEnum <> int or uint <> int
3635 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
3636 if (!mono_class_is_nullable (iface_klass
)) {
3637 if (m_class_is_valuetype (iface_klass
))
3638 iface_klass
= m_class_get_cast_class (iface_klass
);
3640 //array covariant casts only operates on scalar to scalar
3641 //This is so int[] can't be casted to IComparable<int>[]
3642 if (!(m_class_is_valuetype (obj_klass
) && !m_class_is_valuetype (iface_klass
)) && mono_class_is_assignable_from_internal (iface_klass
, obj_klass
)) {
3649 if (mono_class_has_variant_generic_params (klass
)) {
3651 mono_class_setup_interfaces (oklass
, error
);
3652 return_if_nok (error
);
3654 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
3655 for (i
= 0; i
< m_class_get_interface_offsets_count (oklass
); ++i
) {
3656 MonoClass
*iface
= m_class_get_interfaces_packed (oklass
) [i
];
3658 if (mono_class_is_variant_compatible (klass
, iface
, FALSE
)) {
3666 } else if (m_class_is_delegate (klass
)) {
3667 if (mono_class_has_variant_generic_params (klass
) && mono_class_is_variant_compatible (klass
, oklass
, FALSE
)) {
3671 }else if (m_class_get_rank (klass
)) {
3672 MonoClass
*eclass
, *eoclass
;
3674 if (m_class_get_rank (oklass
) != m_class_get_rank (klass
)) {
3679 /* vectors vs. one dimensional arrays */
3680 if (oklass_byval_arg
->type
!= klass_byval_arg
->type
) {
3685 eclass
= m_class_get_cast_class (klass
);
3686 eoclass
= m_class_get_cast_class (oklass
);
3689 * a is b does not imply a[] is b[] when a is a valuetype, and
3690 * b is a reference type.
3693 if (m_class_is_valuetype (eoclass
)) {
3694 if ((eclass
== mono_defaults
.enum_class
) ||
3695 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
3696 (eclass
== mono_defaults
.object_class
)) {
3702 mono_class_is_assignable_from_checked (eclass
, eoclass
, result
, error
);
3704 } else if (mono_class_is_nullable (klass
)) {
3705 if (mono_class_is_nullable (oklass
))
3706 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), m_class_get_cast_class (oklass
), result
, error
);
3708 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), oklass
, result
, error
);
3710 } else if (klass
== mono_defaults
.object_class
) {
3715 *result
= mono_class_has_parent (oklass
, klass
);
3718 /*Check if @oklass is variant compatible with @klass.*/
3720 mono_class_is_variant_compatible_slow (MonoClass
*klass
, MonoClass
*oklass
)
3723 MonoType
**klass_argv
, **oklass_argv
;
3724 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3725 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3727 /*Viable candidates are instances of the same generic interface*/
3728 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3731 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3732 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3734 for (j
= 0; j
< container
->type_argc
; ++j
) {
3735 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3736 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3738 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
))
3742 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3743 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3745 if (param1_class
!= param2_class
) {
3746 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3747 if (!mono_class_is_assignable_from_slow (param1_class
, param2_class
))
3749 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3750 if (!mono_class_is_assignable_from_slow (param2_class
, param1_class
))
3758 /*Check if @candidate implements the interface @target*/
3760 mono_class_implement_interface_slow (MonoClass
*target
, MonoClass
*candidate
)
3764 gboolean is_variant
= mono_class_has_variant_generic_params (target
);
3766 if (is_variant
&& MONO_CLASS_IS_INTERFACE_INTERNAL (candidate
)) {
3767 if (mono_class_is_variant_compatible_slow (target
, candidate
))
3772 if (candidate
== target
)
3775 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
3776 if (image_is_dynamic (m_class_get_image (candidate
)) && !m_class_was_typebuilder (candidate
)) {
3777 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info_raw (candidate
); /* FIXME use handles */
3779 if (tb
&& tb
->interfaces
) {
3780 for (j
= mono_array_length_internal (tb
->interfaces
) - 1; j
>= 0; --j
) {
3781 MonoReflectionType
*iface
= mono_array_get_internal (tb
->interfaces
, MonoReflectionType
*, j
);
3782 MonoClass
*iface_class
;
3784 /* we can't realize the type here since it can do pretty much anything. */
3787 iface_class
= mono_class_from_mono_type_internal (iface
->type
);
3788 if (iface_class
== target
)
3790 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, iface_class
))
3792 if (mono_class_implement_interface_slow (target
, iface_class
))
3797 /*setup_interfaces don't mono_class_init_internal anything*/
3798 /*FIXME this doesn't handle primitive type arrays.
3799 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
3800 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
3802 mono_class_setup_interfaces (candidate
, error
);
3803 if (!mono_error_ok (error
)) {
3804 mono_error_cleanup (error
);
3808 int candidate_interface_count
= m_class_get_interface_count (candidate
);
3809 MonoClass
**candidate_interfaces
= m_class_get_interfaces (candidate
);
3810 for (i
= 0; i
< candidate_interface_count
; ++i
) {
3811 if (candidate_interfaces
[i
] == target
)
3814 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, candidate_interfaces
[i
]))
3817 if (mono_class_implement_interface_slow (target
, candidate_interfaces
[i
]))
3821 candidate
= m_class_get_parent (candidate
);
3822 } while (candidate
);
3828 * Check if @oklass can be assigned to @klass.
3829 * This function does the same as mono_class_is_assignable_from_internal but is safe to be used from mono_class_init_internal context.
3832 mono_class_is_assignable_from_slow (MonoClass
*target
, MonoClass
*candidate
)
3834 if (candidate
== target
)
3836 if (target
== mono_defaults
.object_class
)
3839 if (mono_class_has_parent (candidate
, target
))
3842 /*If target is not an interface there is no need to check them.*/
3843 if (MONO_CLASS_IS_INTERFACE_INTERNAL (target
))
3844 return mono_class_implement_interface_slow (target
, candidate
);
3846 if (m_class_is_delegate (target
) && mono_class_has_variant_generic_params (target
))
3847 return mono_class_is_variant_compatible (target
, candidate
, FALSE
);
3849 if (m_class_get_rank (target
)) {
3850 MonoClass
*eclass
, *eoclass
;
3852 if (m_class_get_rank (target
) != m_class_get_rank (candidate
))
3855 /* vectors vs. one dimensional arrays */
3856 if (m_class_get_byval_arg (target
)->type
!= m_class_get_byval_arg (candidate
)->type
)
3859 eclass
= m_class_get_cast_class (target
);
3860 eoclass
= m_class_get_cast_class (candidate
);
3863 * a is b does not imply a[] is b[] when a is a valuetype, and
3864 * b is a reference type.
3867 if (m_class_is_valuetype (eoclass
)) {
3868 if ((eclass
== mono_defaults
.enum_class
) ||
3869 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
3870 (eclass
== mono_defaults
.object_class
))
3874 return mono_class_is_assignable_from_slow (eclass
, eoclass
);
3876 /*FIXME properly handle nullables */
3877 /*FIXME properly handle (M)VAR */
3882 * mono_generic_param_get_base_type:
3884 * Return the base type of the given generic parameter from its constraints.
3886 * Could be another generic parameter, or it could be Object or ValueType.
3889 mono_generic_param_get_base_type (MonoClass
*klass
)
3891 MonoType
*type
= m_class_get_byval_arg (klass
);
3892 g_assert (mono_type_is_generic_argument (type
));
3894 MonoGenericParam
*gparam
= type
->data
.generic_param
;
3896 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
3898 MonoClass
*base_class
= mono_defaults
.object_class
;
3902 for (i
= 0; constraints
[i
]; ++i
) {
3903 MonoClass
*constraint
= constraints
[i
];
3905 if (MONO_CLASS_IS_INTERFACE_INTERNAL (constraint
))
3908 MonoType
*constraint_type
= m_class_get_byval_arg (constraint
);
3909 if (mono_type_is_generic_argument (constraint_type
)) {
3910 MonoGenericParam
*constraint_param
= constraint_type
->data
.generic_param
;
3911 MonoGenericParamInfo
*constraint_info
= mono_generic_param_info (constraint_param
);
3912 if ((constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0 &&
3913 (constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) == 0)
3917 base_class
= constraint
;
3922 if (base_class
== mono_defaults
.object_class
)
3924 MonoGenericParamInfo
*gparam_info
= mono_generic_param_info (gparam
);
3925 if ((gparam_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0) {
3926 base_class
= mono_class_get_valuetype_class ();
3934 * mono_class_get_cctor:
3935 * \param klass A MonoClass pointer
3937 * \returns The static constructor of \p klass if it exists, NULL otherwise.
3940 mono_class_get_cctor (MonoClass
*klass
)
3942 MonoMethod
*result
= NULL
;
3944 MonoCachedClassInfo cached_info
;
3946 if (image_is_dynamic (m_class_get_image (klass
))) {
3948 * has_cctor is not set for these classes because mono_class_init_internal () is
3951 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
3952 mono_error_assert_msg_ok (error
, "Could not lookup class cctor in dynamic image");
3956 mono_class_init_internal (klass
);
3958 if (!m_class_has_cctor (klass
))
3961 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
3962 result
= mono_class_get_inflated_method (klass
, mono_class_get_cctor (mono_class_get_generic_class (klass
)->container_class
), error
);
3963 mono_error_assert_msg_ok (error
, "Could not lookup inflated class cctor"); /* FIXME do proper error handling */
3967 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
3968 result
= mono_get_method_checked (m_class_get_image (klass
), cached_info
.cctor_token
, klass
, NULL
, error
);
3969 mono_error_assert_msg_ok (error
, "Could not lookup class cctor from cached metadata");
3973 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
3974 mono_error_assert_msg_ok (error
, "Could not lookup class cctor");
3979 * mono_class_get_finalizer:
3980 * \param klass: The MonoClass pointer
3982 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
3985 mono_class_get_finalizer (MonoClass
*klass
)
3987 MonoCachedClassInfo cached_info
;
3989 if (!m_class_is_inited (klass
))
3990 mono_class_init_internal (klass
);
3991 if (!mono_class_has_finalizer (klass
))
3994 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
3996 MonoMethod
*result
= mono_get_method_checked (cached_info
.finalize_image
, cached_info
.finalize_token
, NULL
, NULL
, error
);
3997 mono_error_assert_msg_ok (error
, "Could not lookup finalizer from cached metadata");
4000 mono_class_setup_vtable (klass
);
4001 return m_class_get_vtable (klass
) [mono_class_get_object_finalize_slot ()];
4006 * mono_class_needs_cctor_run:
4007 * \param klass the MonoClass pointer
4008 * \param caller a MonoMethod describing the caller
4010 * Determines whenever the class has a static constructor and whenever it
4011 * needs to be called when executing CALLER.
4014 mono_class_needs_cctor_run (MonoClass
*klass
, MonoMethod
*caller
)
4018 method
= mono_class_get_cctor (klass
);
4020 return (method
== caller
) ? FALSE
: TRUE
;
4026 * mono_class_array_element_size:
4029 * \returns The number of bytes an element of type \p klass uses when stored into an array.
4032 mono_class_array_element_size (MonoClass
*klass
)
4034 MonoType
*type
= m_class_get_byval_arg (klass
);
4037 switch (type
->type
) {
4040 case MONO_TYPE_BOOLEAN
:
4044 case MONO_TYPE_CHAR
:
4053 case MONO_TYPE_CLASS
:
4054 case MONO_TYPE_STRING
:
4055 case MONO_TYPE_OBJECT
:
4056 case MONO_TYPE_SZARRAY
:
4057 case MONO_TYPE_ARRAY
:
4058 return TARGET_SIZEOF_VOID_P
;
4063 case MONO_TYPE_VALUETYPE
:
4064 if (m_class_is_enumtype (type
->data
.klass
)) {
4065 type
= mono_class_enum_basetype_internal (type
->data
.klass
);
4066 klass
= m_class_get_element_class (klass
);
4069 return mono_class_value_size (klass
, NULL
);
4070 case MONO_TYPE_GENERICINST
:
4071 type
= m_class_get_byval_arg (type
->data
.generic_class
->container_class
);
4074 case MONO_TYPE_MVAR
: {
4077 return mono_type_size (type
, &align
);
4079 case MONO_TYPE_VOID
:
4083 g_error ("unknown type 0x%02x in mono_class_array_element_size", type
->type
);
4089 * mono_array_element_size:
4090 * \param ac pointer to a \c MonoArrayClass
4092 * \returns The size of single array element.
4094 * LOCKING: Acquires the loader lock.
4097 mono_array_element_size (MonoClass
*ac
)
4099 g_assert (m_class_get_rank (ac
));
4100 if (G_UNLIKELY (!m_class_is_size_inited (ac
))) {
4101 mono_class_setup_fields (ac
);
4103 return m_class_get_sizes (ac
).element_size
;
4110 mono_ldtoken (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4111 MonoGenericContext
*context
)
4114 gpointer res
= mono_ldtoken_checked (image
, token
, handle_class
, context
, error
);
4115 mono_error_assert_ok (error
);
4120 mono_ldtoken_checked (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4121 MonoGenericContext
*context
, MonoError
*error
)
4125 if (image_is_dynamic (image
)) {
4126 MonoClass
*tmp_handle_class
;
4127 gpointer obj
= mono_lookup_dynamic_token_class (image
, token
, TRUE
, &tmp_handle_class
, context
, error
);
4129 mono_error_assert_ok (error
);
4130 g_assert (tmp_handle_class
);
4132 *handle_class
= tmp_handle_class
;
4134 if (tmp_handle_class
== mono_defaults
.typehandle_class
)
4135 return m_class_get_byval_arg ((MonoClass
*)obj
);
4140 switch (token
& 0xff000000) {
4141 case MONO_TOKEN_TYPE_DEF
:
4142 case MONO_TOKEN_TYPE_REF
:
4143 case MONO_TOKEN_TYPE_SPEC
: {
4146 *handle_class
= mono_defaults
.typehandle_class
;
4147 type
= mono_type_get_checked (image
, token
, context
, error
);
4151 mono_class_init_internal (mono_class_from_mono_type_internal (type
));
4152 /* We return a MonoType* as handle */
4155 case MONO_TOKEN_FIELD_DEF
: {
4157 guint32 type
= mono_metadata_typedef_from_field (image
, mono_metadata_token_index (token
));
4159 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4163 *handle_class
= mono_defaults
.fieldhandle_class
;
4164 klass
= mono_class_get_and_inflate_typespec_checked (image
, MONO_TOKEN_TYPE_DEF
| type
, context
, error
);
4168 mono_class_init_internal (klass
);
4169 return mono_class_get_field (klass
, token
);
4171 case MONO_TOKEN_METHOD_DEF
:
4172 case MONO_TOKEN_METHOD_SPEC
: {
4174 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4176 *handle_class
= mono_defaults
.methodhandle_class
;
4182 case MONO_TOKEN_MEMBER_REF
: {
4183 guint32 cols
[MONO_MEMBERREF_SIZE
];
4185 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
4186 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
4187 mono_metadata_decode_blob_size (sig
, &sig
);
4188 if (*sig
== 0x6) { /* it's a field */
4190 MonoClassField
*field
;
4191 field
= mono_field_from_token_checked (image
, token
, &klass
, context
, error
);
4193 *handle_class
= mono_defaults
.fieldhandle_class
;
4197 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4199 *handle_class
= mono_defaults
.methodhandle_class
;
4204 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4210 mono_lookup_dynamic_token (MonoImage
*image
, guint32 token
, MonoGenericContext
*context
, MonoError
*error
)
4212 MonoClass
*handle_class
;
4214 return mono_reflection_lookup_dynamic_token (image
, token
, TRUE
, &handle_class
, context
, error
);
4218 mono_lookup_dynamic_token_class (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
, MonoError
*error
)
4220 return mono_reflection_lookup_dynamic_token (image
, token
, valid_token
, handle_class
, context
, error
);
4223 static MonoGetCachedClassInfo get_cached_class_info
= NULL
;
4226 mono_install_get_cached_class_info (MonoGetCachedClassInfo func
)
4228 get_cached_class_info
= func
;
4232 mono_class_get_cached_class_info (MonoClass
*klass
, MonoCachedClassInfo
*res
)
4234 if (!get_cached_class_info
)
4237 return get_cached_class_info (klass
, res
);
4241 mono_install_get_class_from_name (MonoGetClassFromName func
)
4243 get_class_from_name
= func
;
4247 * mono_class_get_image:
4249 * Use this method to get the \c MonoImage* where this class came from.
4251 * \returns The image where this class is defined.
4254 mono_class_get_image (MonoClass
*klass
)
4256 return m_class_get_image (klass
);
4260 * mono_class_get_element_class:
4261 * \param klass the \c MonoClass to act on
4263 * Use this function to get the element class of an array.
4265 * \returns The element class of an array.
4268 mono_class_get_element_class (MonoClass
*klass
)
4271 MONO_ENTER_GC_UNSAFE
;
4272 result
= m_class_get_element_class (klass
);
4273 MONO_EXIT_GC_UNSAFE
;
4278 * mono_class_is_valuetype:
4279 * \param klass the \c MonoClass to act on
4281 * Use this method to determine if the provided \c MonoClass* represents a value type,
4282 * or a reference type.
4284 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
4287 mono_class_is_valuetype (MonoClass
*klass
)
4290 MONO_ENTER_GC_UNSAFE
;
4291 result
= m_class_is_valuetype (klass
);
4292 MONO_EXIT_GC_UNSAFE
;
4297 * mono_class_is_enum:
4298 * \param klass the \c MonoClass to act on
4300 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
4302 * \returns TRUE if the \c MonoClass represents an enumeration.
4305 mono_class_is_enum (MonoClass
*klass
)
4308 MONO_ENTER_GC_UNSAFE
;
4309 result
= m_class_is_enumtype (klass
);
4310 MONO_EXIT_GC_UNSAFE
;
4315 * mono_class_enum_basetype_internal:
4316 * \param klass the \c MonoClass to act on
4318 * Use this function to get the underlying type for an enumeration value.
4320 * \returns The underlying type representation for an enumeration.
4323 mono_class_enum_basetype_internal (MonoClass
*klass
)
4325 if (m_class_get_element_class (klass
) == klass
)
4326 /* SRE or broken types */
4328 return m_class_get_byval_arg (m_class_get_element_class (klass
));
4332 * mono_class_enum_basetype:
4333 * \param klass the \c MonoClass to act on
4335 * Use this function to get the underlying type for an enumeration value.
4337 * \returns The underlying type representation for an enumeration.
4340 mono_class_enum_basetype (MonoClass
*klass
)
4343 MONO_ENTER_GC_UNSAFE
;
4344 res
= mono_class_enum_basetype_internal (klass
);
4345 MONO_EXIT_GC_UNSAFE
;
4350 * mono_class_get_parent
4351 * \param klass the \c MonoClass to act on
4353 * \returns The parent class for this class.
4356 mono_class_get_parent (MonoClass
*klass
)
4359 MONO_ENTER_GC_UNSAFE
;
4360 result
= m_class_get_parent (klass
);
4361 MONO_EXIT_GC_UNSAFE
;
4366 * mono_class_get_nesting_type:
4367 * \param klass the \c MonoClass to act on
4369 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
4371 * If the return is NULL, this indicates that this class is not nested.
4373 * \returns The container type where this type is nested or NULL if this type is not a nested type.
4376 mono_class_get_nesting_type (MonoClass
*klass
)
4378 return m_class_get_nested_in (klass
);
4382 * mono_class_get_rank:
4383 * \param klass the MonoClass to act on
4385 * \returns The rank for the array (the number of dimensions).
4388 mono_class_get_rank (MonoClass
*klass
)
4390 return m_class_get_rank (klass
);
4394 * mono_class_get_name
4395 * \param klass the \c MonoClass to act on
4397 * \returns The name of the class.
4400 mono_class_get_name (MonoClass
*klass
)
4403 MONO_ENTER_GC_UNSAFE
;
4404 result
= m_class_get_name (klass
);
4405 MONO_EXIT_GC_UNSAFE
;
4410 * mono_class_get_namespace:
4411 * \param klass the \c MonoClass to act on
4413 * \returns The namespace of the class.
4416 mono_class_get_namespace (MonoClass
*klass
)
4419 MONO_ENTER_GC_UNSAFE
;
4420 result
= m_class_get_name_space (klass
);
4421 MONO_EXIT_GC_UNSAFE
;
4426 * mono_class_get_type:
4427 * \param klass the \c MonoClass to act on
4429 * This method returns the internal \c MonoType representation for the class.
4431 * \returns The \c MonoType from the class.
4434 mono_class_get_type (MonoClass
*klass
)
4436 return m_class_get_byval_arg (klass
);
4440 * mono_class_get_type_token:
4441 * \param klass the \c MonoClass to act on
4443 * This method returns type token for the class.
4445 * \returns The type token for the class.
4448 mono_class_get_type_token (MonoClass
*klass
)
4450 return m_class_get_type_token (klass
);
4454 * mono_class_get_byref_type:
4455 * \param klass the \c MonoClass to act on
4460 mono_class_get_byref_type (MonoClass
*klass
)
4462 return m_class_get_this_arg (klass
);
4466 * mono_class_num_fields:
4467 * \param klass the \c MonoClass to act on
4469 * \returns The number of static and instance fields in the class.
4472 mono_class_num_fields (MonoClass
*klass
)
4474 return mono_class_get_field_count (klass
);
4478 * mono_class_num_methods:
4479 * \param klass the \c MonoClass to act on
4481 * \returns The number of methods in the class.
4484 mono_class_num_methods (MonoClass
*klass
)
4486 return mono_class_get_method_count (klass
);
4490 * mono_class_num_properties
4491 * \param klass the \c MonoClass to act on
4493 * \returns The number of properties in the class.
4496 mono_class_num_properties (MonoClass
*klass
)
4498 mono_class_setup_properties (klass
);
4500 return mono_class_get_property_info (klass
)->count
;
4504 * mono_class_num_events:
4505 * \param klass the \c MonoClass to act on
4507 * \returns The number of events in the class.
4510 mono_class_num_events (MonoClass
*klass
)
4512 mono_class_setup_events (klass
);
4514 return mono_class_get_event_info (klass
)->count
;
4518 * mono_class_get_fields:
4519 * \param klass the \c MonoClass to act on
4521 * This routine is an iterator routine for retrieving the fields in a class.
4523 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4524 * iterate over all of the elements. When no more values are
4525 * available, the return value is NULL.
4527 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
4530 mono_class_get_fields (MonoClass
* klass
, gpointer
*iter
)
4532 MonoClassField
*result
;
4533 MONO_ENTER_GC_UNSAFE
;
4534 result
= mono_class_get_fields_internal (klass
, iter
);
4535 MONO_EXIT_GC_UNSAFE
;
4540 mono_class_get_fields_internal (MonoClass
*klass
, gpointer
*iter
)
4542 MonoClassField
* field
;
4546 mono_class_setup_fields (klass
);
4547 if (mono_class_has_failure (klass
))
4549 /* start from the first */
4550 if (mono_class_get_field_count (klass
)) {
4551 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
4552 *iter
= &klass_fields
[0];
4553 return &klass_fields
[0];
4559 field
= (MonoClassField
*)*iter
;
4561 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
4569 * mono_class_get_methods:
4570 * \param klass the \c MonoClass to act on
4572 * This routine is an iterator routine for retrieving the fields in a class.
4574 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4575 * iterate over all of the elements. When no more values are
4576 * available, the return value is NULL.
4578 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
4581 mono_class_get_methods (MonoClass
* klass
, gpointer
*iter
)
4583 MonoMethod
** method
;
4587 mono_class_setup_methods (klass
);
4589 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
4591 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
4592 * FIXME we should better report this error to the caller
4596 /* start from the first */
4597 if (mono_class_get_method_count (klass
)) {
4598 *iter
= &klass_methods
[0];
4599 return klass_methods
[0];
4605 method
= (MonoMethod
**)*iter
;
4607 if (method
< &m_class_get_methods (klass
) [mono_class_get_method_count (klass
)]) {
4615 * mono_class_get_properties:
4616 * \param klass the \c MonoClass to act on
4618 * This routine is an iterator routine for retrieving the properties in a class.
4620 * You must pass a gpointer that points to zero and is treated as an opaque handle to
4621 * iterate over all of the elements. When no more values are
4622 * available, the return value is NULL.
4624 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
4627 mono_class_get_properties (MonoClass
* klass
, gpointer
*iter
)
4629 MonoProperty
* property
;
4633 mono_class_setup_properties (klass
);
4634 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4635 /* start from the first */
4637 *iter
= &info
->properties
[0];
4638 return (MonoProperty
*)*iter
;
4644 property
= (MonoProperty
*)*iter
;
4646 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4647 if (property
< &info
->properties
[info
->count
]) {
4649 return (MonoProperty
*)*iter
;
4655 * mono_class_get_events:
4656 * \param klass the \c MonoClass to act on
4658 * This routine is an iterator routine for retrieving the properties in a class.
4660 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4661 * iterate over all of the elements. When no more values are
4662 * available, the return value is NULL.
4664 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
4667 mono_class_get_events (MonoClass
* klass
, gpointer
*iter
)
4673 mono_class_setup_events (klass
);
4674 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4675 /* start from the first */
4677 *iter
= &info
->events
[0];
4678 return (MonoEvent
*)*iter
;
4684 event
= (MonoEvent
*)*iter
;
4686 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4687 if (event
< &info
->events
[info
->count
]) {
4689 return (MonoEvent
*)*iter
;
4695 * mono_class_get_interfaces
4696 * \param klass the \c MonoClass to act on
4698 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
4700 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4701 * iterate over all of the elements. When no more values are
4702 * available, the return value is NULL.
4704 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
4707 mono_class_get_interfaces (MonoClass
* klass
, gpointer
*iter
)
4714 if (!m_class_is_inited (klass
))
4715 mono_class_init_internal (klass
);
4716 if (!m_class_is_interfaces_inited (klass
)) {
4717 mono_class_setup_interfaces (klass
, error
);
4718 if (!mono_error_ok (error
)) {
4719 mono_error_cleanup (error
);
4723 /* start from the first */
4724 if (m_class_get_interface_count (klass
)) {
4725 *iter
= &m_class_get_interfaces (klass
) [0];
4726 return m_class_get_interfaces (klass
) [0];
4732 iface
= (MonoClass
**)*iter
;
4734 if (iface
< &m_class_get_interfaces (klass
) [m_class_get_interface_count (klass
)]) {
4742 * mono_class_get_nested_types
4743 * \param klass the \c MonoClass to act on
4745 * This routine is an iterator routine for retrieving the nested types of a class.
4746 * This works only if \p klass is non-generic, or a generic type definition.
4748 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4749 * iterate over all of the elements. When no more values are
4750 * available, the return value is NULL.
4752 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
4755 mono_class_get_nested_types (MonoClass
* klass
, gpointer
*iter
)
4761 if (!m_class_is_nested_classes_inited (klass
))
4762 mono_class_setup_nested_types (klass
);
4765 GList
*nested_classes
= mono_class_get_nested_classes_property (klass
);
4766 /* start from the first */
4767 if (nested_classes
) {
4768 *iter
= nested_classes
;
4769 return (MonoClass
*)nested_classes
->data
;
4771 /* no nested types */
4775 item
= (GList
*)*iter
;
4779 return (MonoClass
*)item
->data
;
4786 * mono_class_is_delegate
4787 * \param klass the \c MonoClass to act on
4789 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
4792 mono_class_is_delegate (MonoClass
*klass
)
4795 MONO_ENTER_GC_UNSAFE
;
4796 result
= m_class_is_delegate (klass
);
4797 MONO_EXIT_GC_UNSAFE
;
4802 * mono_class_implements_interface
4803 * \param klass The MonoClass to act on
4804 * \param interface The interface to check if \p klass implements.
4806 * \returns TRUE if \p klass implements \p interface.
4809 mono_class_implements_interface (MonoClass
* klass
, MonoClass
* iface
)
4811 return mono_class_is_assignable_from_internal (iface
, klass
);
4815 * mono_field_get_name:
4816 * \param field the \c MonoClassField to act on
4818 * \returns The name of the field.
4821 mono_field_get_name (MonoClassField
*field
)
4827 * mono_field_get_type_internal:
4828 * \param field the \c MonoClassField to act on
4829 * \returns \c MonoType of the field.
4832 mono_field_get_type_internal (MonoClassField
*field
)
4834 MonoType
*type
= field
->type
;
4839 type
= mono_field_get_type_checked (field
, error
);
4840 if (!mono_error_ok (error
)) {
4841 mono_trace_warning (MONO_TRACE_TYPE
, "Could not load field's type due to %s", mono_error_get_message (error
));
4842 mono_error_cleanup (error
);
4848 * mono_field_get_type:
4849 * \param field the \c MonoClassField to act on
4850 * \returns \c MonoType of the field.
4853 mono_field_get_type (MonoClassField
*field
)
4855 MonoType
*type
= field
->type
;
4859 MONO_ENTER_GC_UNSAFE
;
4860 type
= mono_field_get_type_internal (field
);
4861 MONO_EXIT_GC_UNSAFE
;
4866 * mono_field_get_type_checked:
4867 * \param field the \c MonoClassField to act on
4868 * \param error used to return any error found while retrieving \p field type
4870 * \returns \c MonoType of the field.
4873 mono_field_get_type_checked (MonoClassField
*field
, MonoError
*error
)
4876 MonoType
*type
= field
->type
;
4879 mono_field_resolve_type (field
, error
);
4884 * mono_field_get_parent:
4885 * \param field the \c MonoClassField to act on
4887 * \returns \c MonoClass where the field was defined.
4890 mono_field_get_parent (MonoClassField
*field
)
4892 return field
->parent
;
4896 * mono_field_get_flags;
4897 * \param field the \c MonoClassField to act on
4899 * The metadata flags for a field are encoded using the
4900 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
4902 * \returns The flags for the field.
4905 mono_field_get_flags (MonoClassField
*field
)
4908 return mono_field_resolve_flags (field
);
4909 return field
->type
->attrs
;
4913 * mono_field_get_offset:
4914 * \param field the \c MonoClassField to act on
4916 * \returns The field offset.
4919 mono_field_get_offset (MonoClassField
*field
)
4921 mono_class_setup_fields(field
->parent
);
4922 return field
->offset
;
4926 mono_field_get_rva (MonoClassField
*field
)
4930 MonoClass
*klass
= field
->parent
;
4931 MonoFieldDefaultValue
*def_values
;
4933 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
);
4935 def_values
= mono_class_get_field_def_values (klass
);
4937 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
4939 mono_class_set_field_def_values (klass
, def_values
);
4942 field_index
= mono_field_get_index (field
);
4944 if (!def_values
[field_index
].data
&& !image_is_dynamic (m_class_get_image (klass
))) {
4945 int first_field_idx
= mono_class_get_first_field_idx (klass
);
4946 mono_metadata_field_info (m_class_get_image (field
->parent
), first_field_idx
+ field_index
, NULL
, &rva
, NULL
);
4948 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field
), m_class_get_name (field
->parent
));
4949 def_values
[field_index
].data
= mono_image_rva_map (m_class_get_image (field
->parent
), rva
);
4952 return def_values
[field_index
].data
;
4956 * mono_field_get_data:
4957 * \param field the \c MonoClassField to act on
4959 * \returns A pointer to the metadata constant value or to the field
4960 * data if it has an RVA flag.
4963 mono_field_get_data (MonoClassField
*field
)
4965 if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
) {
4966 MonoTypeEnum def_type
;
4968 return mono_class_get_field_default_value (field
, &def_type
);
4969 } else if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
4970 return mono_field_get_rva (field
);
4977 * mono_property_get_name:
4978 * \param prop the \c MonoProperty to act on
4979 * \returns The name of the property
4982 mono_property_get_name (MonoProperty
*prop
)
4988 * mono_property_get_set_method
4989 * \param prop the \c MonoProperty to act on.
4990 * \returns The setter method of the property, a \c MonoMethod.
4993 mono_property_get_set_method (MonoProperty
*prop
)
4999 * mono_property_get_get_method
5000 * \param prop the MonoProperty to act on.
5001 * \returns The getter method of the property (A \c MonoMethod)
5004 mono_property_get_get_method (MonoProperty
*prop
)
5010 * mono_property_get_parent:
5011 * \param prop the \c MonoProperty to act on.
5012 * \returns The \c MonoClass where the property was defined.
5015 mono_property_get_parent (MonoProperty
*prop
)
5017 return prop
->parent
;
5021 * mono_property_get_flags:
5022 * \param prop the \c MonoProperty to act on.
5024 * The metadata flags for a property are encoded using the
5025 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5027 * \returns The flags for the property.
5030 mono_property_get_flags (MonoProperty
*prop
)
5036 * mono_event_get_name:
5037 * \param event the MonoEvent to act on
5038 * \returns The name of the event.
5041 mono_event_get_name (MonoEvent
*event
)
5047 * mono_event_get_add_method:
5048 * \param event The \c MonoEvent to act on.
5049 * \returns The \c add method for the event, a \c MonoMethod.
5052 mono_event_get_add_method (MonoEvent
*event
)
5058 * mono_event_get_remove_method:
5059 * \param event The \c MonoEvent to act on.
5060 * \returns The \c remove method for the event, a \c MonoMethod.
5063 mono_event_get_remove_method (MonoEvent
*event
)
5065 return event
->remove
;
5069 * mono_event_get_raise_method:
5070 * \param event The \c MonoEvent to act on.
5071 * \returns The \c raise method for the event, a \c MonoMethod.
5074 mono_event_get_raise_method (MonoEvent
*event
)
5076 return event
->raise
;
5080 * mono_event_get_parent:
5081 * \param event the MonoEvent to act on.
5082 * \returns The \c MonoClass where the event is defined.
5085 mono_event_get_parent (MonoEvent
*event
)
5087 return event
->parent
;
5091 * mono_event_get_flags
5092 * \param event the \c MonoEvent to act on.
5094 * The metadata flags for an event are encoded using the
5095 * \c EVENT_* constants. See the \c tabledefs.h file for details.
5097 * \returns The flags for the event.
5100 mono_event_get_flags (MonoEvent
*event
)
5102 return event
->attrs
;
5106 * mono_class_get_method_from_name:
5107 * \param klass where to look for the method
5108 * \param name name of the method
5109 * \param param_count number of parameters. -1 for any number.
5111 * Obtains a \c MonoMethod with a given name and number of parameters.
5112 * It only works if there are no multiple signatures for any given method name.
5115 mono_class_get_method_from_name (MonoClass
*klass
, const char *name
, int param_count
)
5118 MONO_ENTER_GC_UNSAFE
;
5120 result
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, 0, error
);
5121 mono_error_cleanup (error
);
5122 MONO_EXIT_GC_UNSAFE
;
5127 mono_find_method_in_metadata (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5129 MonoImage
*klass_image
= m_class_get_image (klass
);
5130 MonoMethod
*res
= NULL
;
5133 /* Search directly in the metadata to avoid calling setup_methods () */
5134 int first_idx
= mono_class_get_first_method_idx (klass
);
5135 int mcount
= mono_class_get_method_count (klass
);
5136 for (i
= 0; i
< mcount
; ++i
) {
5138 guint32 cols
[MONO_METHOD_SIZE
];
5140 MonoMethodSignature
*sig
;
5142 /* first_idx points into the methodptr table */
5143 mono_metadata_decode_table_row (klass_image
, MONO_TABLE_METHOD
, first_idx
+ i
, cols
, MONO_METHOD_SIZE
);
5145 if (!strcmp (mono_metadata_string_heap (klass_image
, cols
[MONO_METHOD_NAME
]), name
)) {
5146 method
= mono_get_method_checked (klass_image
, MONO_TOKEN_METHOD_DEF
| (first_idx
+ i
+ 1), klass
, NULL
, error
);
5148 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5151 if (param_count
== -1) {
5155 sig
= mono_method_signature_checked (method
, error
);
5157 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5160 if (sig
->param_count
== param_count
) {
5171 * mono_class_get_method_from_name_flags:
5172 * \param klass where to look for the method
5173 * \param name_space name of the method
5174 * \param param_count number of parameters. -1 for any number.
5175 * \param flags flags which must be set in the method
5177 * Obtains a \c MonoMethod with a given name and number of parameters.
5178 * It only works if there are no multiple signatures for any given method name.
5181 mono_class_get_method_from_name_flags (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5184 MONO_ENTER_GC_UNSAFE
;
5186 method
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, flags
, error
);
5187 mono_error_cleanup (error
);
5188 MONO_EXIT_GC_UNSAFE
;
5193 * mono_class_get_method_from_name_checked:
5194 * \param klass where to look for the method
5195 * \param name_space name of the method
5196 * \param param_count number of parameters. -1 for any number.
5197 * \param flags flags which must be set in the method
5200 * Obtains a \c MonoMethod with a given name and number of parameters.
5201 * It only works if there are no multiple signatures for any given method name.
5204 mono_class_get_method_from_name_checked (MonoClass
*klass
, const char *name
,
5205 int param_count
, int flags
, MonoError
*error
)
5207 MonoMethod
*res
= NULL
;
5210 mono_class_init_internal (klass
);
5212 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
5213 res
= mono_class_get_method_from_name_checked (mono_class_get_generic_class (klass
)->container_class
, name
, param_count
, flags
, error
);
5216 res
= mono_class_inflate_generic_method_full_checked (res
, klass
, mono_class_get_context (klass
), error
);
5221 if (m_class_get_methods (klass
) || !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
5222 mono_class_setup_methods (klass
);
5224 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
5225 See mono/tests/array_load_exception.il
5226 FIXME we should better report this error to the caller
5228 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
5231 int mcount
= mono_class_get_method_count (klass
);
5232 for (i
= 0; i
< mcount
; ++i
) {
5233 MonoMethod
*method
= klass_methods
[i
];
5235 if (method
->name
[0] == name
[0] &&
5236 !strcmp (name
, method
->name
) &&
5237 (param_count
== -1 || mono_method_signature_internal (method
)->param_count
== param_count
) &&
5238 ((method
->flags
& flags
) == flags
)) {
5245 res
= mono_find_method_in_metadata (klass
, name
, param_count
, flags
);
5252 mono_class_has_failure (const MonoClass
*klass
)
5254 g_assert (klass
!= NULL
);
5255 return m_class_has_failure ((MonoClass
*)klass
) != 0;
5260 * mono_class_set_type_load_failure:
5261 * \param klass class in which the failure was detected
5262 * \param fmt \c printf -style error message string.
5264 * Collect detected failure informaion in the class for later processing.
5265 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
5266 * Note that only the first failure is kept.
5268 * LOCKING: Acquires the loader lock.
5270 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
5273 mono_class_set_type_load_failure (MonoClass
*klass
, const char * fmt
, ...)
5275 ERROR_DECL (prepare_error
);
5278 if (mono_class_has_failure (klass
))
5281 va_start (args
, fmt
);
5282 mono_error_vset_type_load_class (prepare_error
, klass
, fmt
, args
);
5285 MonoErrorBoxed
*box
= mono_error_box (prepare_error
, m_class_get_image (klass
));
5286 mono_error_cleanup (prepare_error
);
5287 return mono_class_set_failure (klass
, box
);
5291 * mono_class_get_exception_for_failure:
5292 * \param klass class in which the failure was detected
5294 * \returns a constructed MonoException than the caller can then throw
5295 * using mono_raise_exception - or NULL if no failure is present (or
5296 * doesn't result in an exception).
5299 mono_class_get_exception_for_failure (MonoClass
*klass
)
5301 if (!mono_class_has_failure (klass
))
5303 ERROR_DECL (unboxed_error
);
5304 mono_error_set_for_class_failure (unboxed_error
, klass
);
5305 return mono_error_convert_to_exception (unboxed_error
);
5309 is_nesting_type (MonoClass
*outer_klass
, MonoClass
*inner_klass
)
5311 outer_klass
= mono_class_get_generic_type_definition (outer_klass
);
5312 inner_klass
= mono_class_get_generic_type_definition (inner_klass
);
5314 if (outer_klass
== inner_klass
)
5316 inner_klass
= m_class_get_nested_in (inner_klass
);
5317 } while (inner_klass
);
5322 mono_class_get_generic_type_definition (MonoClass
*klass
)
5324 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5325 return gklass
? gklass
->container_class
: klass
;
5329 * Check if @klass is a subtype of @parent ignoring generic instantiations.
5331 * Generic instantiations are ignored for all super types of @klass.
5333 * Visibility checks ignoring generic instantiations.
5336 mono_class_has_parent_and_ignore_generics (MonoClass
*klass
, MonoClass
*parent
)
5339 klass
= mono_class_get_generic_type_definition (klass
);
5340 parent
= mono_class_get_generic_type_definition (parent
);
5341 mono_class_setup_supertypes (klass
);
5343 for (i
= 0; i
< m_class_get_idepth (klass
); ++i
) {
5344 if (parent
== mono_class_get_generic_type_definition (m_class_get_supertypes (klass
) [i
]))
5350 * Subtype can only access parent members with family protection if the site object
5351 * is subclass of Subtype. For example:
5352 * class A { protected int x; }
5354 * void valid_access () {
5358 * void invalid_access () {
5365 is_valid_family_access (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
*context_klass
)
5367 if (MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5368 /* Can happen with default interface methods */
5369 if (!mono_class_implements_interface (access_klass
, member_klass
))
5372 if (!mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
))
5376 if (context_klass
== NULL
)
5378 /*if access_klass is not member_klass context_klass must be type compat*/
5379 if (access_klass
!= member_klass
&& !mono_class_has_parent_and_ignore_generics (context_klass
, access_klass
))
5385 can_access_internals (MonoAssembly
*accessing
, MonoAssembly
* accessed
)
5388 if (accessing
== accessed
)
5390 if (!accessed
|| !accessing
)
5393 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
5394 * anywhere so untrusted friends are not safe to access platform's code internals */
5395 if (mono_security_core_clr_enabled ()) {
5396 if (!mono_security_core_clr_can_access_internals (accessing
->image
, accessed
->image
))
5400 mono_assembly_load_friends (accessed
);
5401 for (tmp
= accessed
->friend_assembly_names
; tmp
; tmp
= tmp
->next
) {
5402 MonoAssemblyName
*friend_
= (MonoAssemblyName
*)tmp
->data
;
5403 /* Be conservative with checks */
5406 if (g_ascii_strcasecmp (accessing
->aname
.name
, friend_
->name
))
5408 if (friend_
->public_key_token
[0]) {
5409 if (!accessing
->aname
.public_key_token
[0])
5411 if (!mono_public_tokens_are_equal (friend_
->public_key_token
, accessing
->aname
.public_key_token
))
5420 * If klass is a generic type or if it is derived from a generic type, return the
5421 * MonoClass of the generic definition
5422 * Returns NULL if not found
5425 get_generic_definition_class (MonoClass
*klass
)
5428 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5429 if (gklass
&& gklass
->container_class
)
5430 return gklass
->container_class
;
5431 klass
= m_class_get_parent (klass
);
5437 can_access_instantiation (MonoClass
*access_klass
, MonoGenericInst
*ginst
)
5440 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
5441 MonoType
*type
= ginst
->type_argv
[i
];
5442 switch (type
->type
) {
5443 case MONO_TYPE_SZARRAY
:
5444 if (!can_access_type (access_klass
, type
->data
.klass
))
5447 case MONO_TYPE_ARRAY
:
5448 if (!can_access_type (access_klass
, type
->data
.array
->eklass
))
5452 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
->data
.type
)))
5455 case MONO_TYPE_CLASS
:
5456 case MONO_TYPE_VALUETYPE
:
5457 case MONO_TYPE_GENERICINST
:
5458 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
)))
5468 can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
)
5472 if (access_klass
== member_klass
)
5475 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5476 MonoAssembly
*member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5478 if (access_klass_assembly
&& m_class_get_image (access_klass
)->assembly
->corlib_internal
)
5481 if (m_class_get_element_class (access_klass
) && !m_class_is_enumtype (access_klass
)) {
5482 access_klass
= m_class_get_element_class (access_klass
);
5483 access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5486 if (m_class_get_element_class (member_klass
) && !m_class_is_enumtype (member_klass
)) {
5487 member_klass
= m_class_get_element_class (member_klass
);
5488 member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5491 access_level
= mono_class_get_flags (member_klass
) & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5493 if (mono_type_is_generic_argument (m_class_get_byval_arg (member_klass
)))
5496 if (mono_class_is_ginst (member_klass
) && !can_access_instantiation (access_klass
, mono_class_get_generic_class (member_klass
)->context
.class_inst
))
5499 if (is_nesting_type (access_klass
, member_klass
) || (m_class_get_nested_in (access_klass
) && is_nesting_type (m_class_get_nested_in (access_klass
), member_klass
)))
5502 /*Non nested type with nested visibility. We just fail it.*/
5503 if (access_level
>= TYPE_ATTRIBUTE_NESTED_PRIVATE
&& access_level
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
&& m_class_get_nested_in (member_klass
) == NULL
)
5506 MonoClass
*member_klass_nested_in
= m_class_get_nested_in (member_klass
);
5507 switch (access_level
) {
5508 case TYPE_ATTRIBUTE_NOT_PUBLIC
:
5509 return can_access_internals (access_klass_assembly
, member_klass_assembly
);
5511 case TYPE_ATTRIBUTE_PUBLIC
:
5514 case TYPE_ATTRIBUTE_NESTED_PUBLIC
:
5515 return member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5517 case TYPE_ATTRIBUTE_NESTED_PRIVATE
:
5518 return is_nesting_type (member_klass
, access_klass
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5520 case TYPE_ATTRIBUTE_NESTED_FAMILY
:
5521 return mono_class_has_parent_and_ignore_generics (access_klass
, m_class_get_nested_in (member_klass
));
5523 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY
:
5524 return can_access_internals (access_klass_assembly
, member_klass_assembly
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5526 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM
:
5527 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) &&
5528 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5530 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
:
5531 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) ||
5532 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5537 /* FIXME: check visibility of type, too */
5539 can_access_member (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
* context_klass
, int access_level
)
5541 MonoClass
*member_generic_def
;
5542 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5543 if (access_klass_assembly
&& access_klass_assembly
->corlib_internal
)
5546 MonoGenericClass
*access_gklass
= mono_class_try_get_generic_class (access_klass
);
5547 if (((access_gklass
&& access_gklass
->container_class
) ||
5548 mono_class_is_gtd (access_klass
)) &&
5549 (member_generic_def
= get_generic_definition_class (member_klass
))) {
5550 MonoClass
*access_container
;
5552 if (mono_class_is_gtd (access_klass
))
5553 access_container
= access_klass
;
5555 access_container
= access_gklass
->container_class
;
5557 if (can_access_member (access_container
, member_generic_def
, context_klass
, access_level
))
5561 MonoImage
*member_klass_image
= m_class_get_image (member_klass
);
5562 /* Partition I 8.5.3.2 */
5563 /* the access level values are the same for fields and methods */
5564 switch (access_level
) {
5565 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED
:
5566 /* same compilation unit */
5567 return m_class_get_image (access_klass
) == member_klass_image
;
5568 case FIELD_ATTRIBUTE_PRIVATE
:
5569 return access_klass
== member_klass
;
5570 case FIELD_ATTRIBUTE_FAM_AND_ASSEM
:
5571 if (is_valid_family_access (access_klass
, member_klass
, context_klass
) &&
5572 can_access_internals (access_klass_assembly
, member_klass_image
->assembly
))
5575 case FIELD_ATTRIBUTE_ASSEMBLY
:
5576 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5577 case FIELD_ATTRIBUTE_FAMILY
:
5578 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5581 case FIELD_ATTRIBUTE_FAM_OR_ASSEM
:
5582 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5584 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5585 case FIELD_ATTRIBUTE_PUBLIC
:
5592 * mono_method_can_access_field:
5593 * \param method Method that will attempt to access the field
5594 * \param field the field to access
5596 * Used to determine if a method is allowed to access the specified field.
5598 * \returns TRUE if the given \p method is allowed to access the \p field while following
5599 * the accessibility rules of the CLI.
5602 mono_method_can_access_field (MonoMethod
*method
, MonoClassField
*field
)
5604 /* FIXME: check all overlapping fields */
5605 int can
= can_access_member (method
->klass
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5607 MonoClass
*nested
= m_class_get_nested_in (method
->klass
);
5609 can
= can_access_member (nested
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5612 nested
= m_class_get_nested_in (nested
);
5619 mono_method_get_method_definition (MonoMethod
*method
)
5621 while (method
->is_inflated
)
5622 method
= ((MonoMethodInflated
*)method
)->declaring
;
5627 * mono_method_can_access_method:
5628 * \param method Method that will attempt to access the other method
5629 * \param called the method that we want to probe for accessibility.
5631 * Used to determine if the \p method is allowed to access the specified \p called method.
5633 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
5634 * the accessibility rules of the CLI.
5637 mono_method_can_access_method (MonoMethod
*method
, MonoMethod
*called
)
5639 method
= mono_method_get_method_definition (method
);
5640 called
= mono_method_get_method_definition (called
);
5641 return mono_method_can_access_method_full (method
, called
, NULL
);
5645 * mono_method_can_access_method_full:
5646 * @method: The caller method
5647 * @called: The called method
5648 * @context_klass: The static type on stack of the owner @called object used
5650 * This function must be used with instance calls, as they have more strict family accessibility.
5651 * It can be used with static methods, but context_klass should be NULL.
5653 * Returns: TRUE if caller have proper visibility and acessibility to @called
5656 mono_method_can_access_method_full (MonoMethod
*method
, MonoMethod
*called
, MonoClass
*context_klass
)
5658 /* Wrappers are except from access checks */
5659 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| called
->wrapper_type
!= MONO_WRAPPER_NONE
)
5662 MonoClass
*access_class
= method
->klass
;
5663 MonoClass
*member_class
= called
->klass
;
5664 int can
= can_access_member (access_class
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5666 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5668 can
= can_access_member (nested
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5671 nested
= m_class_get_nested_in (nested
);
5678 can
= can_access_type (access_class
, member_class
);
5680 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5682 can
= can_access_type (nested
, member_class
);
5685 nested
= m_class_get_nested_in (nested
);
5692 if (called
->is_inflated
) {
5693 MonoMethodInflated
* infl
= (MonoMethodInflated
*)called
;
5694 if (infl
->context
.method_inst
&& !can_access_instantiation (access_class
, infl
->context
.method_inst
))
5703 * mono_method_can_access_field_full:
5704 * @method: The caller method
5705 * @field: The accessed field
5706 * @context_klass: The static type on stack of the owner @field object used
5708 * This function must be used with instance fields, as they have more strict family accessibility.
5709 * It can be used with static fields, but context_klass should be NULL.
5711 * Returns: TRUE if caller have proper visibility and acessibility to @field
5714 mono_method_can_access_field_full (MonoMethod
*method
, MonoClassField
*field
, MonoClass
*context_klass
)
5716 MonoClass
*access_class
= method
->klass
;
5717 MonoClass
*member_class
= field
->parent
;
5718 /* FIXME: check all overlapping fields */
5719 int can
= can_access_member (access_class
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5721 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5723 can
= can_access_member (nested
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5726 nested
= m_class_get_nested_in (nested
);
5733 can
= can_access_type (access_class
, member_class
);
5735 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5737 can
= can_access_type (nested
, member_class
);
5740 nested
= m_class_get_nested_in (nested
);
5750 * mono_class_can_access_class:
5751 * @source_class: The source class
5752 * @target_class: The accessed class
5754 * This function returns is @target_class is visible to @source_class
5756 * Returns: TRUE if source have proper visibility and acessibility to target
5759 mono_class_can_access_class (MonoClass
*source_class
, MonoClass
*target_class
)
5761 return can_access_type (source_class
, target_class
);
5765 * mono_type_is_valid_enum_basetype:
5766 * \param type The MonoType to check
5767 * \returns TRUE if the type can be used as the basetype of an enum
5769 gboolean
mono_type_is_valid_enum_basetype (MonoType
* type
) {
5770 switch (type
->type
) {
5773 case MONO_TYPE_BOOLEAN
:
5776 case MONO_TYPE_CHAR
:
5790 * mono_class_is_valid_enum:
5791 * \param klass An enum class to be validated
5793 * This method verify the required properties an enum should have.
5795 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
5796 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
5797 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
5799 * \returns TRUE if the informed enum class is valid
5802 mono_class_is_valid_enum (MonoClass
*klass
)
5804 MonoClassField
* field
;
5805 gpointer iter
= NULL
;
5806 gboolean found_base_field
= FALSE
;
5808 g_assert (m_class_is_enumtype (klass
));
5809 MonoClass
*klass_parent
= m_class_get_parent (klass
);
5810 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
5811 if (!klass_parent
|| strcmp (m_class_get_name (klass_parent
), "Enum") || strcmp (m_class_get_name_space (klass_parent
), "System") ) {
5815 if (!mono_class_is_auto_layout (klass
))
5818 while ((field
= mono_class_get_fields_internal (klass
, &iter
))) {
5819 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
5820 if (found_base_field
)
5822 found_base_field
= TRUE
;
5823 if (!mono_type_is_valid_enum_basetype (field
->type
))
5828 if (!found_base_field
)
5831 if (mono_class_get_method_count (klass
) > 0)
5838 mono_generic_class_is_generic_type_definition (MonoGenericClass
*gklass
)
5840 return gklass
->context
.class_inst
== mono_class_get_generic_container (gklass
->container_class
)->context
.class_inst
;
5844 mono_field_resolve_type (MonoClassField
*field
, MonoError
*error
)
5846 MonoClass
*klass
= field
->parent
;
5847 MonoImage
*image
= m_class_get_image (klass
);
5848 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
5850 int field_idx
= field
- m_class_get_fields (klass
);
5855 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
5856 MonoType
*gtype
= mono_field_get_type_checked (gfield
, error
);
5857 if (!mono_error_ok (error
)) {
5858 char *full_name
= mono_type_get_full_name (gtd
);
5859 mono_class_set_type_load_failure (klass
, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name
, gfield
->name
, field_idx
, mono_error_get_message (error
));
5863 ftype
= mono_class_inflate_generic_type_no_copy (image
, gtype
, mono_class_get_context (klass
), error
);
5864 if (!mono_error_ok (error
)) {
5865 char *full_name
= mono_type_get_full_name (klass
);
5866 mono_class_set_type_load_failure (klass
, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name
, field
->name
, field_idx
, mono_error_get_message (error
));
5871 guint32 cols
[MONO_FIELD_SIZE
];
5872 MonoGenericContainer
*container
= NULL
;
5873 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
5875 /*FIXME, in theory we do not lazy load SRE fields*/
5876 g_assert (!image_is_dynamic (image
));
5878 if (mono_class_is_gtd (klass
)) {
5879 container
= mono_class_get_generic_container (klass
);
5881 container
= mono_class_get_generic_container (gtd
);
5882 g_assert (container
);
5885 /* first_field_idx and idx points into the fieldptr table */
5886 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
5888 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
)) {
5889 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
5893 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
5895 mono_metadata_decode_value (sig
, &sig
);
5896 /* FIELD signature == 0x06 */
5897 g_assert (*sig
== 0x06);
5899 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
5901 char *full_name
= mono_type_get_full_name (klass
);
5902 mono_class_set_type_load_failure (klass
, "Could not load type of field '%s:%s' (%d) due to: %s", full_name
, field
->name
, field_idx
, mono_error_get_message (error
));
5906 mono_memory_barrier ();
5907 field
->type
= ftype
;
5911 mono_field_resolve_flags (MonoClassField
*field
)
5913 MonoClass
*klass
= field
->parent
;
5914 MonoImage
*image
= m_class_get_image (klass
);
5915 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
5916 int field_idx
= field
- m_class_get_fields (klass
);
5919 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
5920 return mono_field_get_flags (gfield
);
5922 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
5924 /*FIXME, in theory we do not lazy load SRE fields*/
5925 g_assert (!image_is_dynamic (image
));
5927 return mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_FLAGS
);
5932 * mono_class_get_fields_lazy:
5933 * \param klass the MonoClass to act on
5935 * This routine is an iterator routine for retrieving the fields in a class.
5936 * Only minimal information about fields are loaded. Accessors must be used
5937 * for all MonoClassField returned.
5939 * You must pass a gpointer that points to zero and is treated as an opaque handle to
5940 * iterate over all of the elements. When no more values are
5941 * available, the return value is NULL.
5943 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
5946 mono_class_get_fields_lazy (MonoClass
* klass
, gpointer
*iter
)
5948 MonoClassField
* field
;
5952 mono_class_setup_basic_field_info (klass
);
5953 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
5956 /* start from the first */
5957 if (mono_class_get_field_count (klass
)) {
5958 *iter
= &klass_fields
[0];
5959 return (MonoClassField
*)*iter
;
5965 field
= (MonoClassField
*)*iter
;
5967 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
5969 return (MonoClassField
*)*iter
;
5975 mono_class_full_name (MonoClass
*klass
)
5977 return mono_type_full_name (m_class_get_byval_arg (klass
));
5980 /* Declare all shared lazy type lookup functions */
5981 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle
, "System.Runtime.InteropServices", "SafeHandle")
5984 * mono_method_get_base_method:
5985 * \param method a method
5986 * \param definition if true, get the definition
5987 * \param error set on failure
5989 * Given a virtual method associated with a subclass, return the corresponding
5990 * method from an ancestor. If \p definition is FALSE, returns the method in the
5991 * superclass of the given method. If \p definition is TRUE, return the method
5992 * in the ancestor class where it was first declared. The type arguments will
5993 * be inflated in the ancestor classes. If the method is not associated with a
5994 * class, or isn't virtual, returns the method itself. On failure returns NULL
5995 * and sets \p error.
5998 mono_method_get_base_method (MonoMethod
*method
, gboolean definition
, MonoError
*error
)
6000 MonoClass
*klass
, *parent
;
6001 MonoGenericContext
*generic_inst
= NULL
;
6002 MonoMethod
*result
= NULL
;
6005 if (method
->klass
== NULL
)
6008 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
6009 MONO_CLASS_IS_INTERFACE_INTERNAL (method
->klass
) ||
6010 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
6013 slot
= mono_method_get_vtable_slot (method
);
6017 klass
= method
->klass
;
6018 if (mono_class_is_ginst (klass
)) {
6019 generic_inst
= mono_class_get_context (klass
);
6020 klass
= mono_class_get_generic_class (klass
)->container_class
;
6025 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6026 for (parent
= m_class_get_parent (klass
); parent
!= NULL
; parent
= m_class_get_parent (parent
)) {
6027 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6028 or klass is the generic container class and generic_inst is the instantiation.
6030 when we go to the parent, if the parent is an open constructed type, we need to
6031 replace the type parameters by the definitions from the generic_inst, and then take it
6032 apart again into the klass and the generic_inst.
6034 For cases like this:
6035 class C<T> : B<T, int> {
6036 public override void Foo () { ... }
6038 class B<U,V> : A<HashMap<U,V>> {
6039 public override void Foo () { ... }
6042 public virtual void Foo () { ... }
6045 if at each iteration the parent isn't open, we can skip inflating it. if at some
6046 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6049 MonoGenericContext
*parent_inst
= NULL
;
6050 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (parent
))) {
6051 parent
= mono_class_inflate_generic_class_checked (parent
, generic_inst
, error
);
6052 return_val_if_nok (error
, NULL
);
6054 if (mono_class_is_ginst (parent
)) {
6055 parent_inst
= mono_class_get_context (parent
);
6056 parent
= mono_class_get_generic_class (parent
)->container_class
;
6059 mono_class_setup_vtable (parent
);
6060 if (m_class_get_vtable_size (parent
) <= slot
)
6063 generic_inst
= parent_inst
;
6066 klass
= m_class_get_parent (klass
);
6069 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (klass
))) {
6070 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6071 return_val_if_nok (error
, NULL
);
6073 generic_inst
= NULL
;
6075 if (mono_class_is_ginst (klass
)) {
6076 generic_inst
= mono_class_get_context (klass
);
6077 klass
= mono_class_get_generic_class (klass
)->container_class
;
6083 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6084 return_val_if_nok (error
, NULL
);
6087 if (klass
== method
->klass
)
6090 /*This is possible if definition == FALSE.
6091 * Do it here to be really sure we don't read invalid memory.
6093 if (slot
>= m_class_get_vtable_size (klass
))
6096 mono_class_setup_vtable (klass
);
6098 result
= m_class_get_vtable (klass
) [slot
];
6099 if (result
== NULL
) {
6100 /* It is an abstract method */
6101 gboolean found
= FALSE
;
6102 gpointer iter
= NULL
;
6103 while ((result
= mono_class_get_methods (klass
, &iter
))) {
6104 if (result
->slot
== slot
) {
6109 /* found might be FALSE if we looked in an abstract class
6110 * that doesn't override an abstract method of its
6112 * abstract class Base {
6113 * public abstract void Foo ();
6115 * abstract class Derived : Base { }
6116 * class Child : Derived {
6117 * public override void Foo () { }
6120 * if m was Child.Foo and we ask for the base method,
6121 * then we get here with klass == Derived and found == FALSE
6123 /* but it shouldn't be the case that if we're looking
6124 * for the definition and didn't find a result; the
6125 * loop above should've taken us as far as we could
6127 g_assert (!(definition
&& !found
));
6132 g_assert (result
!= NULL
);