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
);
69 mono_class_from_name_checked_aux (MonoImage
*image
, const char* name_space
, const char *name
, GHashTable
* visited_images
, gboolean case_sensitive
, MonoError
*error
);
71 GENERATE_GET_CLASS_WITH_CACHE (valuetype
, "System", "ValueType")
72 GENERATE_TRY_GET_CLASS_WITH_CACHE (handleref
, "System.Runtime.InteropServices", "HandleRef")
74 // define to print types whenever custom modifiers are appended during inflation
75 #undef DEBUG_INFLATE_CMODS
79 mono_method_get_image (MonoMethod
*method
)
81 return m_class_get_image (method
->klass
);
85 * mono_class_from_typeref:
86 * \param image a MonoImage
87 * \param type_token a TypeRef token
89 * Creates the \c MonoClass* structure representing the type defined by
90 * the typeref token valid inside \p image.
91 * \returns The \c MonoClass* representing the typeref token, or NULL if it could
95 mono_class_from_typeref (MonoImage
*image
, guint32 type_token
)
98 MonoClass
*klass
= mono_class_from_typeref_checked (image
, type_token
, error
);
99 g_assert (is_ok (error
)); /*FIXME proper error handling*/
104 * mono_class_from_typeref_checked:
105 * \param image a MonoImage
106 * \param type_token a TypeRef token
107 * \param error error return code, if any.
109 * Creates the \c MonoClass* structure representing the type defined by
110 * the typeref token valid inside \p image.
112 * \returns The \c MonoClass* representing the typeref token, NULL if it could
113 * not be loaded with the \p error value filled with the information about the
117 mono_class_from_typeref_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
119 guint32 cols
[MONO_TYPEREF_SIZE
];
120 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
122 const char *name
, *nspace
;
123 MonoClass
*res
= NULL
;
128 if (!mono_verifier_verify_typeref_row (image
, (type_token
& 0xffffff) - 1, error
))
131 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
133 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
134 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
136 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
137 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
138 case MONO_RESOLUTION_SCOPE_MODULE
:
140 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
141 This is not the observed behavior of existing implementations.
142 The defacto behavior is that it's just a typedef in disguise.
144 /* a typedef in disguise */
145 res
= mono_class_from_name_checked (image
, nspace
, name
, error
);
148 case MONO_RESOLUTION_SCOPE_MODULEREF
:
149 module
= mono_image_load_module_checked (image
, idx
, error
);
151 res
= mono_class_from_name_checked (module
, nspace
, name
, error
);
154 case MONO_RESOLUTION_SCOPE_TYPEREF
: {
155 MonoClass
*enclosing
;
158 if (idx
== mono_metadata_token_index (type_token
)) {
159 mono_error_set_bad_image (error
, image
, "Image with self-referencing typeref token %08x.", type_token
);
163 enclosing
= mono_class_from_typeref_checked (image
, MONO_TOKEN_TYPE_REF
| idx
, error
);
164 return_val_if_nok (error
, NULL
);
166 GList
*nested_classes
= mono_class_get_nested_classes_property (enclosing
);
167 if (m_class_is_nested_classes_inited (enclosing
) && nested_classes
) {
168 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
169 for (tmp
= nested_classes
; tmp
; tmp
= tmp
->next
) {
170 res
= (MonoClass
*)tmp
->data
;
171 if (strcmp (m_class_get_name (res
), name
) == 0)
175 MonoImage
*enclosing_image
= m_class_get_image (enclosing
);
176 guint32 enclosing_type_token
= m_class_get_type_token (enclosing
);
177 /* Don't call mono_class_init_internal as we might've been called by it recursively */
178 int i
= mono_metadata_nesting_typedef (enclosing_image
, enclosing_type_token
, 1);
180 guint32 class_nested
= mono_metadata_decode_row_col (&enclosing_image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, MONO_NESTED_CLASS_NESTED
);
181 guint32 string_offset
= mono_metadata_decode_row_col (&enclosing_image
->tables
[MONO_TABLE_TYPEDEF
], class_nested
- 1, MONO_TYPEDEF_NAME
);
182 const char *nname
= mono_metadata_string_heap (enclosing_image
, string_offset
);
184 if (strcmp (nname
, name
) == 0)
185 return mono_class_create_from_typedef (enclosing_image
, MONO_TOKEN_TYPE_DEF
| class_nested
, error
);
187 i
= mono_metadata_nesting_typedef (enclosing_image
, enclosing_type_token
, i
+ 1);
190 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx
, nspace
, name
, image
->name
);
193 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
197 if (idx
> image
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
) {
198 mono_error_set_bad_image (error
, image
, "Image with invalid assemblyref token %08x.", idx
);
202 if (!image
->references
|| !image
->references
[idx
- 1])
203 mono_assembly_load_reference (image
, idx
- 1);
204 g_assert (image
->references
[idx
- 1]);
206 /* If the assembly did not load, register this as a type load exception */
207 if (image
->references
[idx
- 1] == REFERENCE_MISSING
){
208 MonoAssemblyName aname
;
211 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
212 human_name
= mono_stringify_assembly_name (&aname
);
213 gboolean refonly
= FALSE
;
215 refonly
= mono_asmctx_get_kind (&image
->assembly
->context
) == MONO_ASMCTX_REFONLY
;
216 mono_error_set_simple_file_not_found (error
, human_name
, refonly
);
221 res
= mono_class_from_name_checked (image
->references
[idx
- 1]->image
, nspace
, name
, error
);
224 /* Generic case, should be avoided for when a better error is possible. */
225 if (!res
&& is_ok (error
)) {
226 char *name
= mono_class_name_from_token (image
, type_token
);
227 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
228 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
);
235 mono_image_memdup (MonoImage
*image
, void *data
, guint size
)
237 void *res
= mono_image_alloc (image
, size
);
238 memcpy (res
, data
, size
);
242 /* Copy everything mono_metadata_free_array free. */
244 mono_dup_array_type (MonoImage
*image
, MonoArrayType
*a
)
247 a
= (MonoArrayType
*)mono_image_memdup (image
, a
, sizeof (MonoArrayType
));
249 a
->sizes
= (int *)mono_image_memdup (image
, a
->sizes
, a
->numsizes
* sizeof (int));
251 a
->lobounds
= (int *)mono_image_memdup (image
, a
->lobounds
, a
->numlobounds
* sizeof (int));
253 a
= (MonoArrayType
*)g_memdup (a
, sizeof (MonoArrayType
));
255 a
->sizes
= (int *)g_memdup (a
->sizes
, a
->numsizes
* sizeof (int));
257 a
->lobounds
= (int *)g_memdup (a
->lobounds
, a
->numlobounds
* sizeof (int));
262 /* Copy everything mono_metadata_free_method_signature free. */
264 mono_metadata_signature_deep_dup (MonoImage
*image
, MonoMethodSignature
*sig
)
268 sig
= mono_metadata_signature_dup_full (image
, sig
);
270 sig
->ret
= mono_metadata_type_dup (image
, sig
->ret
);
271 for (i
= 0; i
< sig
->param_count
; ++i
)
272 sig
->params
[i
] = mono_metadata_type_dup (image
, sig
->params
[i
]);
278 _mono_type_get_assembly_name (MonoClass
*klass
, GString
*str
)
280 MonoAssembly
*ta
= m_class_get_image (klass
)->assembly
;
283 name
= mono_stringify_assembly_name (&ta
->aname
);
284 g_string_append_printf (str
, ", %s", name
);
289 mono_type_name_check_byref (MonoType
*type
, GString
*str
)
292 g_string_append_c (str
, '&');
296 * mono_identifier_escape_type_name_chars:
297 * \param str a destination string
298 * \param identifier an IDENTIFIER in internal form
302 * The displayed form of the identifier is appended to str.
304 * The displayed form of an identifier has the characters ,+&*[]\
305 * that have special meaning in type names escaped with a preceeding
306 * backslash (\) character.
309 mono_identifier_escape_type_name_chars (GString
* str
, const char* identifier
)
315 // reserve space for common case: there will be no escaped characters.
316 g_string_set_size(str
, n
+ strlen(identifier
));
317 g_string_set_size(str
, n
);
319 for (const char* s
= identifier
; *s
!= 0 ; s
++) {
328 g_string_append_c (str
, '\\');
329 g_string_append_c (str
, *s
);
332 g_string_append_c (str
, *s
);
340 mono_type_get_name_recurse (MonoType
*type
, GString
*str
, gboolean is_recursed
,
341 MonoTypeNameFormat format
)
345 switch (type
->type
) {
346 case MONO_TYPE_ARRAY
: {
347 int i
, rank
= type
->data
.array
->rank
;
348 MonoTypeNameFormat nested_format
;
350 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
351 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
353 mono_type_get_name_recurse (
354 m_class_get_byval_arg (type
->data
.array
->eklass
), str
, FALSE
, nested_format
);
355 g_string_append_c (str
, '[');
357 g_string_append_c (str
, '*');
358 for (i
= 1; i
< rank
; i
++)
359 g_string_append_c (str
, ',');
360 g_string_append_c (str
, ']');
362 mono_type_name_check_byref (type
, str
);
364 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
365 _mono_type_get_assembly_name (type
->data
.array
->eklass
, str
);
368 case MONO_TYPE_SZARRAY
: {
369 MonoTypeNameFormat nested_format
;
371 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
372 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
374 mono_type_get_name_recurse (
375 m_class_get_byval_arg (type
->data
.klass
), str
, FALSE
, nested_format
);
376 g_string_append (str
, "[]");
378 mono_type_name_check_byref (type
, str
);
380 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
381 _mono_type_get_assembly_name (type
->data
.klass
, str
);
384 case MONO_TYPE_PTR
: {
385 MonoTypeNameFormat nested_format
;
387 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
388 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
390 mono_type_get_name_recurse (
391 type
->data
.type
, str
, FALSE
, nested_format
);
392 g_string_append_c (str
, '*');
394 mono_type_name_check_byref (type
, str
);
396 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
397 _mono_type_get_assembly_name (mono_class_from_mono_type_internal (type
->data
.type
), str
);
402 if (!mono_generic_param_name (type
->data
.generic_param
))
403 g_string_append_printf (str
, "%s%d", type
->type
== MONO_TYPE_VAR
? "!" : "!!", type
->data
.generic_param
->num
);
405 g_string_append (str
, mono_generic_param_name (type
->data
.generic_param
));
407 mono_type_name_check_byref (type
, str
);
411 klass
= mono_class_from_mono_type_internal (type
);
412 if (m_class_get_nested_in (klass
)) {
413 mono_type_get_name_recurse (
414 m_class_get_byval_arg (m_class_get_nested_in (klass
)), str
, TRUE
, format
);
415 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
416 g_string_append_c (str
, '.');
418 g_string_append_c (str
, '+');
419 } else if (*m_class_get_name_space (klass
)) {
420 const char *klass_name_space
= m_class_get_name_space (klass
);
421 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
422 g_string_append (str
, klass_name_space
);
424 mono_identifier_escape_type_name_chars (str
, klass_name_space
);
425 g_string_append_c (str
, '.');
427 const char *klass_name
= m_class_get_name (klass
);
428 if (format
== MONO_TYPE_NAME_FORMAT_IL
) {
429 const char *s
= strchr (klass_name
, '`');
430 gssize len
= s
? (s
- klass_name
) : (gssize
)strlen (klass_name
);
431 g_string_append_len (str
, klass_name
, len
);
433 mono_identifier_escape_type_name_chars (str
, klass_name
);
437 if (mono_class_is_ginst (klass
)) {
438 MonoGenericClass
*gclass
= mono_class_get_generic_class (klass
);
439 MonoGenericInst
*inst
= gclass
->context
.class_inst
;
440 MonoTypeNameFormat nested_format
;
443 nested_format
= format
== MONO_TYPE_NAME_FORMAT_FULL_NAME
?
444 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
: format
;
446 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
447 g_string_append_c (str
, '<');
449 g_string_append_c (str
, '[');
450 for (i
= 0; i
< inst
->type_argc
; i
++) {
451 MonoType
*t
= inst
->type_argv
[i
];
454 g_string_append_c (str
, ',');
455 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
456 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
457 g_string_append_c (str
, '[');
458 mono_type_get_name_recurse (inst
->type_argv
[i
], str
, FALSE
, nested_format
);
459 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
460 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
461 g_string_append_c (str
, ']');
463 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
464 g_string_append_c (str
, '>');
466 g_string_append_c (str
, ']');
467 } else if (mono_class_is_gtd (klass
) &&
468 (format
!= MONO_TYPE_NAME_FORMAT_FULL_NAME
) &&
469 (format
!= MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)) {
472 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
473 g_string_append_c (str
, '<');
475 g_string_append_c (str
, '[');
476 for (i
= 0; i
< mono_class_get_generic_container (klass
)->type_argc
; i
++) {
478 g_string_append_c (str
, ',');
479 g_string_append (str
, mono_generic_container_get_param_info (mono_class_get_generic_container (klass
), i
)->name
);
481 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
482 g_string_append_c (str
, '>');
484 g_string_append_c (str
, ']');
487 mono_type_name_check_byref (type
, str
);
489 if ((format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
490 (type
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
491 _mono_type_get_assembly_name (klass
, str
);
497 * mono_type_get_name_full:
499 * \param format the format for the return string.
502 * \returns The string representation in a number of formats:
504 * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
505 * returned in the format required by \c System.Reflection, this is the
506 * inverse of mono_reflection_parse_type().
508 * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
509 * be used by the IL assembler.
511 * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
513 * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
516 mono_type_get_name_full (MonoType
*type
, MonoTypeNameFormat format
)
520 result
= g_string_new ("");
522 mono_type_get_name_recurse (type
, result
, FALSE
, format
);
524 return g_string_free (result
, FALSE
);
528 * mono_type_get_full_name:
529 * \param class a class
531 * \returns The string representation for type as required by System.Reflection.
532 * The inverse of mono_reflection_parse_type().
535 mono_type_get_full_name (MonoClass
*klass
)
537 return mono_type_get_name_full (m_class_get_byval_arg (klass
), MONO_TYPE_NAME_FORMAT_REFLECTION
);
541 * mono_type_get_name:
543 * \returns The string representation for type as it would be represented in IL code.
546 mono_type_get_name (MonoType
*type
)
548 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_IL
);
552 * mono_type_get_underlying_type:
554 * \returns The \c MonoType for the underlying integer type if \p type
555 * is an enum and byref is false, otherwise the type itself.
558 mono_type_get_underlying_type (MonoType
*type
)
560 if (type
->type
== MONO_TYPE_VALUETYPE
&& m_class_is_enumtype (type
->data
.klass
) && !type
->byref
)
561 return mono_class_enum_basetype_internal (type
->data
.klass
);
562 if (type
->type
== MONO_TYPE_GENERICINST
&& m_class_is_enumtype (type
->data
.generic_class
->container_class
) && !type
->byref
)
563 return mono_class_enum_basetype_internal (type
->data
.generic_class
->container_class
);
568 * mono_class_is_open_constructed_type:
571 * \returns TRUE if type represents a generics open constructed type.
572 * IOW, not all type parameters required for the instantiation have
573 * been provided or it's a generic type definition.
575 * An open constructed type means it's a non realizable type. Not to
576 * be mixed up with an abstract type - we can't cast or dispatch to
577 * an open type, for example.
580 mono_class_is_open_constructed_type (MonoType
*t
)
586 case MONO_TYPE_SZARRAY
:
587 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t
->data
.klass
));
588 case MONO_TYPE_ARRAY
:
589 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t
->data
.array
->eklass
));
591 return mono_class_is_open_constructed_type (t
->data
.type
);
592 case MONO_TYPE_GENERICINST
:
593 return t
->data
.generic_class
->context
.class_inst
->is_open
;
594 case MONO_TYPE_CLASS
:
595 case MONO_TYPE_VALUETYPE
:
596 return mono_class_is_gtd (t
->data
.klass
);
603 This is a simple function to catch the most common bad instances of generic types.
604 Specially those that might lead to further failures in the runtime.
607 mono_type_is_valid_generic_argument (MonoType
*type
)
609 switch (type
->type
) {
611 case MONO_TYPE_TYPEDBYREF
:
613 case MONO_TYPE_VALUETYPE
:
614 return !m_class_is_byreflike (type
->data
.klass
);
621 can_inflate_gparam_with (MonoGenericParam
*gparam
, MonoType
*type
)
623 if (!mono_type_is_valid_generic_argument (type
))
626 /* Avoid inflating gparams with valuetype constraints with ref types during gsharing */
627 MonoGenericParamInfo
*info
= mono_generic_param_info (gparam
);
628 if (info
&& (info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
)) {
629 if (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
) {
630 MonoGenericParam
*inst_gparam
= type
->data
.generic_param
;
631 if (inst_gparam
->gshared_constraint
&& inst_gparam
->gshared_constraint
->type
== MONO_TYPE_OBJECT
)
640 inflate_generic_custom_modifiers (MonoImage
*image
, const MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
);
643 inflate_generic_type (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
645 gboolean changed
= FALSE
;
648 /* C++/CLI (and some Roslyn tests) constructs method signatures like:
649 * void .CL1`1.Test(!0 modopt(System.Nullable`1<!0>))
650 * where !0 has a custom modifier which itself mentions the type variable.
651 * So we need to potentially inflate the modifiers.
653 if (type
->has_cmods
) {
654 MonoType
*new_type
= inflate_generic_custom_modifiers (image
, type
, context
, error
);
655 return_val_if_nok (error
, NULL
);
656 if (new_type
!= NULL
) {
662 switch (type
->type
) {
663 case MONO_TYPE_MVAR
: {
665 int num
= mono_type_get_generic_param_num (type
);
666 MonoGenericInst
*inst
= context
->method_inst
;
673 MonoGenericParam
*gparam
= type
->data
.generic_param
;
674 if (num
>= inst
->type_argc
) {
675 const char *pname
= mono_generic_param_name (gparam
);
676 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
677 num
, pname
? pname
: "", inst
->type_argc
);
681 if (!can_inflate_gparam_with (gparam
, inst
->type_argv
[num
])) {
682 const char *pname
= mono_generic_param_name (gparam
);
683 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded with type 0x%x",
684 num
, pname
? pname
: "", inst
->type_argv
[num
]->type
);
688 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
689 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
690 * ->byref and ->attrs from @type are propagated to the returned type.
692 nt
= mono_metadata_type_dup_with_cmods (image
, inst
->type_argv
[num
], type
);
693 nt
->byref
= type
->byref
;
694 nt
->attrs
= type
->attrs
;
697 case MONO_TYPE_VAR
: {
699 int num
= mono_type_get_generic_param_num (type
);
700 MonoGenericInst
*inst
= context
->class_inst
;
707 MonoGenericParam
*gparam
= type
->data
.generic_param
;
708 if (num
>= inst
->type_argc
) {
709 const char *pname
= mono_generic_param_name (gparam
);
710 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
711 num
, pname
? pname
: "", inst
->type_argc
);
714 if (!can_inflate_gparam_with (gparam
, inst
->type_argv
[num
])) {
715 const char *pname
= mono_generic_param_name (gparam
);
716 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded with type 0x%x",
717 num
, pname
? pname
: "", inst
->type_argv
[num
]->type
);
721 #ifdef DEBUG_INFLATE_CMODS
722 gboolean append_cmods
;
723 append_cmods
= FALSE
;
724 if (type
->has_cmods
&& inst
->type_argv
[num
]->has_cmods
) {
725 char *tname
= mono_type_full_name (type
);
726 char *vname
= mono_type_full_name (inst
->type_argv
[num
]);
727 printf ("\n\n\tsubstitution for '%s' with '%s' yields...\n", tname
, vname
);
734 nt
= mono_metadata_type_dup_with_cmods (image
, inst
->type_argv
[num
], type
);
735 nt
->byref
= type
->byref
|| inst
->type_argv
[num
]->byref
;
736 nt
->attrs
= type
->attrs
;
737 #ifdef DEBUG_INFLATE_CMODS
739 char *ntname
= mono_type_full_name (nt
);
740 printf ("\tyields '%s'\n\n\n", ntname
);
746 case MONO_TYPE_SZARRAY
: {
747 MonoClass
*eclass
= type
->data
.klass
;
748 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (eclass
), context
, error
);
749 if ((!inflated
&& !changed
) || !is_ok (error
))
753 nt
= mono_metadata_type_dup (image
, type
);
754 nt
->data
.klass
= mono_class_from_mono_type_internal (inflated
);
755 mono_metadata_free_type (inflated
);
758 case MONO_TYPE_ARRAY
: {
759 MonoClass
*eclass
= type
->data
.array
->eklass
;
760 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (eclass
), context
, error
);
761 if ((!inflated
&& !changed
) || !is_ok (error
))
765 nt
= mono_metadata_type_dup (image
, type
);
766 nt
->data
.array
->eklass
= mono_class_from_mono_type_internal (inflated
);
767 mono_metadata_free_type (inflated
);
770 case MONO_TYPE_GENERICINST
: {
771 MonoGenericClass
*gclass
= type
->data
.generic_class
;
772 MonoGenericInst
*inst
;
774 if (!gclass
->context
.class_inst
->is_open
) {
781 inst
= mono_metadata_inflate_generic_inst (gclass
->context
.class_inst
, context
, error
);
782 return_val_if_nok (error
, NULL
);
784 if (inst
!= gclass
->context
.class_inst
)
785 gclass
= mono_metadata_lookup_generic_class (gclass
->container_class
, inst
, gclass
->is_dynamic
);
787 if (gclass
== type
->data
.generic_class
) {
794 nt
= mono_metadata_type_dup (image
, type
);
795 nt
->data
.generic_class
= gclass
;
798 case MONO_TYPE_CLASS
:
799 case MONO_TYPE_VALUETYPE
: {
800 MonoClass
*klass
= type
->data
.klass
;
801 MonoGenericContainer
*container
= mono_class_try_get_generic_container (klass
);
802 MonoGenericInst
*inst
;
803 MonoGenericClass
*gclass
= NULL
;
813 /* We can't use context->class_inst directly, since it can have more elements */
814 inst
= mono_metadata_inflate_generic_inst (container
->context
.class_inst
, context
, error
);
815 return_val_if_nok (error
, NULL
);
817 if (inst
== container
->context
.class_inst
) {
824 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, image_is_dynamic (m_class_get_image (klass
)));
826 nt
= mono_metadata_type_dup (image
, type
);
827 nt
->type
= MONO_TYPE_GENERICINST
;
828 nt
->data
.generic_class
= gclass
;
831 case MONO_TYPE_PTR
: {
832 MonoType
*nt
, *inflated
= inflate_generic_type (image
, type
->data
.type
, context
, error
);
833 if ((!inflated
&& !changed
) || !is_ok (error
))
835 if (!inflated
&& changed
)
837 nt
= mono_metadata_type_dup (image
, type
);
838 nt
->data
.type
= inflated
;
851 inflate_generic_custom_modifiers (MonoImage
*image
, const MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
853 MonoType
*result
= NULL
;
854 g_assert (type
->has_cmods
);
855 int count
= mono_type_custom_modifier_count (type
);
856 gboolean changed
= FALSE
;
858 /* Try not to blow up the stack. See comment on MONO_MAX_EXPECTED_CMODS. */
859 g_assert (count
< MONO_MAX_EXPECTED_CMODS
);
860 size_t aggregate_size
= mono_sizeof_aggregate_modifiers (count
);
861 MonoAggregateModContainer
*candidate_mods
= g_alloca (aggregate_size
);
862 memset (candidate_mods
, 0, aggregate_size
);
863 candidate_mods
->count
= count
;
865 for (int i
= 0; i
< count
; ++i
) {
867 MonoType
*cmod_old
= mono_type_get_custom_modifier (type
, i
, &required
, error
);
868 goto_if_nok (error
, leave
);
869 MonoType
*cmod_new
= inflate_generic_type (NULL
, cmod_old
, context
, error
);
870 goto_if_nok (error
, leave
);
873 candidate_mods
->modifiers
[i
].required
= required
;
874 candidate_mods
->modifiers
[i
].type
= cmod_new
;
878 /* if we're going to make a new type, fill in any modifiers that weren't affected by inflation with copies of the original values. */
879 for (int i
= 0; i
< count
; ++i
) {
880 if (candidate_mods
->modifiers
[i
].type
== NULL
) {
881 candidate_mods
->modifiers
[i
].type
= mono_metadata_type_dup (NULL
, mono_type_get_custom_modifier (type
, i
, NULL
, error
));
883 /* it didn't error in the first loop, so should be ok now, too */
884 mono_error_assert_ok (error
);
888 #ifdef DEBUG_INFLATE_CMODS
890 char *full_name
= mono_type_full_name ((MonoType
*)type
);
891 printf ("\n\n\tcustom modifier on '%s' affected by subsititution\n\n\n", full_name
);
896 MonoType
*new_type
= g_alloca (mono_sizeof_type_with_mods (count
, TRUE
));
897 /* first init just the non-modifier portion of new_type before populating the
899 memcpy (new_type
, type
, MONO_SIZEOF_TYPE
);
900 mono_type_with_mods_init (new_type
, count
, TRUE
);
901 mono_type_set_amods (new_type
, mono_metadata_get_canonical_aggregate_modifiers (candidate_mods
));
902 result
= mono_metadata_type_dup (image
, new_type
);
906 for (int i
= 0; i
< count
; ++i
) {
907 if (candidate_mods
->modifiers
[i
].type
)
908 mono_metadata_free_type (candidate_mods
->modifiers
[i
].type
);
915 mono_generic_class_get_context (MonoGenericClass
*gclass
)
917 return &gclass
->context
;
921 mono_class_get_context (MonoClass
*klass
)
923 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
924 return gklass
? mono_generic_class_get_context (gklass
) : NULL
;
928 * mono_class_inflate_generic_type_with_mempool:
929 * @mempool: a mempool
931 * @context: a generics context
932 * @error: error context
934 * The same as mono_class_inflate_generic_type, but allocates the MonoType
935 * from mempool if it is non-NULL. If it is NULL, the MonoType is
936 * allocated on the heap and is owned by the caller.
937 * The returned type can potentially be the same as TYPE, so it should not be
938 * modified by the caller, and it should be freed using mono_metadata_free_type ().
941 mono_class_inflate_generic_type_with_mempool (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
943 MonoType
*inflated
= NULL
;
947 inflated
= inflate_generic_type (image
, type
, context
, error
);
948 return_val_if_nok (error
, NULL
);
951 MonoType
*shared
= mono_metadata_get_shared_type (type
);
953 if (shared
&& !type
->has_cmods
) {
956 return mono_metadata_type_dup (image
, type
);
960 UnlockedIncrement (&mono_stats
.inflated_type_count
);
965 * mono_class_inflate_generic_type:
967 * \param context a generics context
968 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
970 * If \p type is a generic type and \p context is not NULL, instantiate it using the
971 * generics context \p context.
973 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
974 * on the heap and is owned by the caller. Returns NULL on error.
977 mono_class_inflate_generic_type (MonoType
*type
, MonoGenericContext
*context
)
981 result
= mono_class_inflate_generic_type_checked (type
, context
, error
);
982 mono_error_cleanup (error
);
987 * mono_class_inflate_generic_type:
989 * @context: a generics context
990 * @error: error context to use
992 * If @type is a generic type and @context is not NULL, instantiate it using the
993 * generics context @context.
995 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
996 * on the heap and is owned by the caller.
999 mono_class_inflate_generic_type_checked (MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
1001 return mono_class_inflate_generic_type_with_mempool (NULL
, type
, context
, error
);
1005 * mono_class_inflate_generic_type_no_copy:
1007 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
1011 mono_class_inflate_generic_type_no_copy (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
1013 MonoType
*inflated
= NULL
;
1017 inflated
= inflate_generic_type (image
, type
, context
, error
);
1018 return_val_if_nok (error
, NULL
);
1024 UnlockedIncrement (&mono_stats
.inflated_type_count
);
1029 * mono_class_inflate_generic_class:
1031 * Inflate the class @gklass with @context. Set @error on failure.
1034 mono_class_inflate_generic_class_checked (MonoClass
*gklass
, MonoGenericContext
*context
, MonoError
*error
)
1039 inflated
= mono_class_inflate_generic_type_checked (m_class_get_byval_arg (gklass
), context
, error
);
1040 return_val_if_nok (error
, NULL
);
1042 res
= mono_class_from_mono_type_internal (inflated
);
1043 mono_metadata_free_type (inflated
);
1048 static MonoGenericContext
1049 inflate_generic_context (MonoGenericContext
*context
, MonoGenericContext
*inflate_with
, MonoError
*error
)
1051 MonoGenericInst
*class_inst
= NULL
;
1052 MonoGenericInst
*method_inst
= NULL
;
1053 MonoGenericContext res
= { NULL
, NULL
};
1057 if (context
->class_inst
) {
1058 class_inst
= mono_metadata_inflate_generic_inst (context
->class_inst
, inflate_with
, error
);
1063 if (context
->method_inst
) {
1064 method_inst
= mono_metadata_inflate_generic_inst (context
->method_inst
, inflate_with
, error
);
1069 res
.class_inst
= class_inst
;
1070 res
.method_inst
= method_inst
;
1076 * mono_class_inflate_generic_method:
1077 * \param method a generic method
1078 * \param context a generics context
1080 * Instantiate the generic method \p method using the generics context \p context.
1082 * \returns The new instantiated method
1085 mono_class_inflate_generic_method (MonoMethod
*method
, MonoGenericContext
*context
)
1089 MonoMethod
*res
= mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
1090 mono_error_assert_msg_ok (error
, "Could not inflate generic method");
1095 mono_class_inflate_generic_method_checked (MonoMethod
*method
, MonoGenericContext
*context
, MonoError
*error
)
1097 return mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
1101 * mono_class_inflate_generic_method_full_checked:
1102 * Instantiate method \p method with the generic context \p context.
1103 * On failure returns NULL and sets \p error.
1105 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1106 * Use mono_method_signature_internal () and mono_method_get_header () to get the correct values.
1109 mono_class_inflate_generic_method_full_checked (MonoMethod
*method
, MonoClass
*klass_hint
, MonoGenericContext
*context
, MonoError
*error
)
1112 MonoMethodInflated
*iresult
, *cached
;
1113 MonoMethodSignature
*sig
;
1114 MonoGenericContext tmp_context
;
1118 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1119 while (method
->is_inflated
) {
1120 MonoGenericContext
*method_context
= mono_method_get_context (method
);
1121 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1123 tmp_context
= inflate_generic_context (method_context
, context
, error
);
1124 return_val_if_nok (error
, NULL
);
1126 context
= &tmp_context
;
1128 if (mono_metadata_generic_context_equal (method_context
, context
))
1131 method
= imethod
->declaring
;
1135 * A method only needs to be inflated if the context has argument for which it is
1138 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1139 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1142 if (!((method
->is_generic
&& context
->method_inst
) ||
1143 (mono_class_is_gtd (method
->klass
) && context
->class_inst
)))
1146 iresult
= g_new0 (MonoMethodInflated
, 1);
1147 iresult
->context
= *context
;
1148 iresult
->declaring
= method
;
1150 if (!context
->method_inst
&& method
->is_generic
)
1151 iresult
->context
.method_inst
= mono_method_get_generic_container (method
)->context
.method_inst
;
1153 if (!context
->class_inst
) {
1154 g_assert (!mono_class_is_ginst (iresult
->declaring
->klass
));
1155 if (mono_class_is_gtd (iresult
->declaring
->klass
))
1156 iresult
->context
.class_inst
= mono_class_get_generic_container (iresult
->declaring
->klass
)->context
.class_inst
;
1158 /* This can happen with some callers like mono_object_get_virtual_method_internal () */
1159 if (!mono_class_is_gtd (iresult
->declaring
->klass
) && !mono_class_is_ginst (iresult
->declaring
->klass
))
1160 iresult
->context
.class_inst
= NULL
;
1162 MonoImageSet
*set
= mono_metadata_get_image_set_for_method (iresult
);
1165 mono_image_set_lock (set
);
1166 cached
= (MonoMethodInflated
*)g_hash_table_lookup (set
->gmethod_cache
, iresult
);
1167 mono_image_set_unlock (set
);
1171 return (MonoMethod
*)cached
;
1174 UnlockedIncrement (&mono_stats
.inflated_method_count
);
1176 UnlockedAdd (&mono_inflated_methods_size
, sizeof (MonoMethodInflated
));
1178 sig
= mono_method_signature_internal (method
);
1180 char *name
= mono_type_get_full_name (method
->klass
);
1181 mono_error_set_bad_image (error
, mono_method_get_image (method
), "Could not resolve signature of method %s:%s", name
, method
->name
);
1187 memcpy (&iresult
->method
.pinvoke
, method
, sizeof (MonoMethodPInvoke
));
1189 memcpy (&iresult
->method
.method
, method
, sizeof (MonoMethod
));
1192 result
= (MonoMethod
*) iresult
;
1193 result
->is_inflated
= TRUE
;
1194 result
->is_generic
= FALSE
;
1195 result
->sre_method
= FALSE
;
1196 result
->signature
= NULL
;
1198 if (method
->wrapper_type
) {
1199 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)method
;
1200 MonoMethodWrapper
*resw
= (MonoMethodWrapper
*)result
;
1201 int len
= GPOINTER_TO_INT (((void**)mw
->method_data
) [0]);
1203 resw
->method_data
= (void **)g_malloc (sizeof (gpointer
) * (len
+ 1));
1204 memcpy (resw
->method_data
, mw
->method_data
, sizeof (gpointer
) * (len
+ 1));
1207 if (iresult
->context
.method_inst
) {
1208 MonoGenericInst
*method_inst
= iresult
->context
.method_inst
;
1209 /* Set the generic_container of the result to the generic_container of method */
1210 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
1212 if (generic_container
&& method_inst
== generic_container
->context
.method_inst
) {
1213 result
->is_generic
= 1;
1214 mono_method_set_generic_container (result
, generic_container
);
1217 /* Check that the method is not instantiated with any invalid types */
1218 for (int i
= 0; i
< method_inst
->type_argc
; i
++) {
1219 if (!mono_type_is_valid_generic_argument (method_inst
->type_argv
[i
])) {
1220 mono_error_set_bad_image (error
, mono_method_get_image (method
), "MVAR %d cannot be expanded with type 0x%x",
1221 i
, method_inst
->type_argv
[i
]->type
);
1228 MonoGenericClass
*gklass_hint
= mono_class_try_get_generic_class (klass_hint
);
1229 if (gklass_hint
&& (gklass_hint
->container_class
!= method
->klass
|| gklass_hint
->context
.class_inst
!= context
->class_inst
))
1233 if (mono_class_is_gtd (method
->klass
))
1234 result
->klass
= klass_hint
;
1236 if (!result
->klass
) {
1237 MonoType
*inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (method
->klass
), context
, error
);
1241 result
->klass
= inflated
? mono_class_from_mono_type_internal (inflated
) : method
->klass
;
1243 mono_metadata_free_type (inflated
);
1247 * FIXME: This should hold, but it doesn't:
1249 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1250 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1251 * g_assert (result->is_generic);
1254 * Fixing this here causes other things to break, hence a very
1255 * ugly hack in mini-trampolines.c - see
1256 * is_generic_method_definition().
1260 mono_image_set_lock (set
);
1261 cached
= (MonoMethodInflated
*)g_hash_table_lookup (set
->gmethod_cache
, iresult
);
1263 g_hash_table_insert (set
->gmethod_cache
, iresult
, iresult
);
1264 iresult
->owner
= set
;
1267 mono_image_set_unlock (set
);
1269 return (MonoMethod
*)cached
;
1277 * mono_get_inflated_method:
1279 * Obsolete. We keep it around since it's mentioned in the public API.
1282 mono_get_inflated_method (MonoMethod
*method
)
1288 * mono_method_get_context_general:
1290 * @uninflated: handle uninflated methods?
1292 * Returns the generic context of a method or NULL if it doesn't have
1293 * one. For an inflated method that's the context stored in the
1294 * method. Otherwise it's in the method's generic container or in the
1295 * generic container of the method's class.
1298 mono_method_get_context_general (MonoMethod
*method
, gboolean uninflated
)
1300 if (method
->is_inflated
) {
1301 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1302 return &imethod
->context
;
1306 if (method
->is_generic
)
1307 return &(mono_method_get_generic_container (method
)->context
);
1308 if (mono_class_is_gtd (method
->klass
))
1309 return &mono_class_get_generic_container (method
->klass
)->context
;
1314 * mono_method_get_context:
1317 * Returns the generic context for method if it's inflated, otherwise
1321 mono_method_get_context (MonoMethod
*method
)
1323 return mono_method_get_context_general (method
, FALSE
);
1327 * mono_method_get_generic_container:
1329 * Returns the generic container of METHOD, which should be a generic method definition.
1330 * Returns NULL if METHOD is not a generic method definition.
1331 * LOCKING: Acquires the loader lock.
1333 MonoGenericContainer
*
1334 mono_method_get_generic_container (MonoMethod
*method
)
1336 MonoGenericContainer
*container
;
1338 if (!method
->is_generic
)
1341 container
= (MonoGenericContainer
*)mono_image_property_lookup (mono_method_get_image (method
), method
, MONO_METHOD_PROP_GENERIC_CONTAINER
);
1342 g_assert (container
);
1348 * mono_method_set_generic_container:
1350 * Sets the generic container of METHOD to CONTAINER.
1351 * LOCKING: Acquires the image lock.
1354 mono_method_set_generic_container (MonoMethod
*method
, MonoGenericContainer
* container
)
1356 g_assert (method
->is_generic
);
1358 mono_image_property_insert (mono_method_get_image (method
), method
, MONO_METHOD_PROP_GENERIC_CONTAINER
, container
);
1362 * mono_class_find_enum_basetype:
1363 * \param class The enum class
1365 * Determine the basetype of an enum by iterating through its fields. We do this
1366 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1369 mono_class_find_enum_basetype (MonoClass
*klass
, MonoError
*error
)
1371 MonoGenericContainer
*container
= NULL
;
1372 MonoImage
*image
= m_class_get_image (klass
);
1373 const int top
= mono_class_get_field_count (klass
);
1374 int i
, first_field_idx
;
1376 g_assert (m_class_is_enumtype (klass
));
1380 container
= mono_class_try_get_generic_container (klass
);
1381 if (mono_class_is_ginst (klass
)) {
1382 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1384 container
= mono_class_get_generic_container (gklass
);
1385 g_assert (container
);
1389 * Fetch all the field information.
1391 first_field_idx
= mono_class_get_first_field_idx (klass
);
1392 for (i
= 0; i
< top
; i
++){
1394 guint32 cols
[MONO_FIELD_SIZE
];
1395 int idx
= first_field_idx
+ i
;
1398 /* first_field_idx and idx points into the fieldptr table */
1399 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
1401 if (cols
[MONO_FIELD_FLAGS
] & FIELD_ATTRIBUTE_STATIC
) //no need to decode static fields
1404 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
))
1407 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
1408 mono_metadata_decode_value (sig
, &sig
);
1409 /* FIELD signature == 0x06 */
1411 mono_error_set_bad_image (error
, image
, "Invalid field signature %x, expected 0x6 but got %x", cols
[MONO_FIELD_SIGNATURE
], *sig
);
1415 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
1419 if (mono_class_is_ginst (klass
)) {
1420 //FIXME do we leak here?
1421 ftype
= mono_class_inflate_generic_type_checked (ftype
, mono_class_get_context (klass
), error
);
1424 ftype
->attrs
= cols
[MONO_FIELD_FLAGS
];
1429 mono_error_set_type_load_class (error
, klass
, "Could not find base type");
1436 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1439 mono_type_has_exceptions (MonoType
*type
)
1441 switch (type
->type
) {
1442 case MONO_TYPE_CLASS
:
1443 case MONO_TYPE_VALUETYPE
:
1444 case MONO_TYPE_SZARRAY
:
1445 return mono_class_has_failure (type
->data
.klass
);
1446 case MONO_TYPE_ARRAY
:
1447 return mono_class_has_failure (type
->data
.array
->eklass
);
1448 case MONO_TYPE_GENERICINST
:
1449 return mono_class_has_failure (mono_class_create_generic_inst (type
->data
.generic_class
));
1456 mono_error_set_for_class_failure (MonoError
*oerror
, const MonoClass
*klass
)
1458 g_assert (mono_class_has_failure (klass
));
1459 MonoErrorBoxed
*box
= mono_class_get_exception_data ((MonoClass
*)klass
);
1460 mono_error_set_from_boxed (oerror
, box
);
1466 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1470 mono_class_alloc (MonoClass
*klass
, int size
)
1472 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1474 return mono_image_set_alloc (gklass
->owner
, size
);
1476 return mono_image_alloc (m_class_get_image (klass
), size
);
1480 (mono_class_alloc0
) (MonoClass
*klass
, int size
)
1484 res
= mono_class_alloc (klass
, size
);
1485 memset (res
, 0, size
);
1489 #define mono_class_new0(klass,struct_type, n_structs) \
1490 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1493 * mono_class_set_failure_causedby_class:
1494 * \param klass the class that is failing
1495 * \param caused_by the class that caused the failure
1496 * \param msg Why \p klass is failing.
1498 * If \p caused_by has a failure, sets a TypeLoadException failure on
1499 * \p klass with message "\p msg, due to: {\p caused_by message}".
1501 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1504 mono_class_set_type_load_failure_causedby_class (MonoClass
*klass
, const MonoClass
*caused_by
, const gchar
* msg
)
1506 if (mono_class_has_failure (caused_by
)) {
1507 ERROR_DECL (cause_error
);
1508 mono_error_set_for_class_failure (cause_error
, caused_by
);
1509 mono_class_set_type_load_failure (klass
, "%s, due to: %s", msg
, mono_error_get_message (cause_error
));
1510 mono_error_cleanup (cause_error
);
1519 * mono_type_get_basic_type_from_generic:
1522 * Returns a closed type corresponding to the possibly open type
1526 mono_type_get_basic_type_from_generic (MonoType
*type
)
1528 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1529 if (!type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
) &&
1530 (!type
->data
.generic_param
->gshared_constraint
|| type
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_OBJECT
))
1531 return mono_get_object_type ();
1536 * mono_class_get_method_by_index:
1538 * Returns klass->methods [index], initializing klass->methods if neccesary.
1540 * LOCKING: Acquires the loader lock.
1543 mono_class_get_method_by_index (MonoClass
*klass
, int index
)
1547 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1548 /* Avoid calling setup_methods () if possible */
1549 if (gklass
&& !m_class_get_methods (klass
)) {
1552 m
= mono_class_inflate_generic_method_full_checked (
1553 m_class_get_methods (gklass
->container_class
) [index
], klass
, mono_class_get_context (klass
), error
);
1554 g_assert (is_ok (error
)); /* FIXME don't swallow the error */
1556 * If setup_methods () is called later for this class, no duplicates are created,
1557 * since inflate_generic_method guarantees that only one instance of a method
1558 * is created for each context.
1561 mono_class_setup_methods (klass);
1562 g_assert (m == klass->methods [index]);
1566 mono_class_setup_methods (klass
);
1567 if (mono_class_has_failure (klass
)) /*FIXME do proper error handling*/
1569 g_assert (index
>= 0 && index
< mono_class_get_method_count (klass
));
1570 return m_class_get_methods (klass
) [index
];
1575 * mono_class_get_inflated_method:
1576 * \param klass an inflated class
1577 * \param method a method of \p klass's generic definition
1578 * \param error set on error
1580 * Given an inflated class \p klass and a method \p method which should be a
1581 * method of \p klass's generic definition, return the inflated method
1582 * corresponding to \p method.
1584 * On failure sets \p error and returns NULL.
1587 mono_class_get_inflated_method (MonoClass
*klass
, MonoMethod
*method
, MonoError
*error
)
1589 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1592 g_assert (method
->klass
== gklass
);
1594 mono_class_setup_methods (gklass
);
1595 if (mono_class_has_failure (gklass
)) {
1596 mono_error_set_for_class_failure (error
, gklass
);
1600 MonoMethod
**gklass_methods
= m_class_get_methods (gklass
);
1601 mcount
= mono_class_get_method_count (gklass
);
1602 for (i
= 0; i
< mcount
; ++i
) {
1603 if (gklass_methods
[i
] == method
) {
1604 MonoMethod
*inflated_method
= NULL
;
1605 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
1606 if (klass_methods
) {
1607 inflated_method
= klass_methods
[i
];
1609 inflated_method
= mono_class_inflate_generic_method_full_checked (gklass_methods
[i
], klass
, mono_class_get_context (klass
), error
);
1610 return_val_if_nok (error
, NULL
);
1612 g_assert (inflated_method
);
1613 return inflated_method
;
1617 g_assert_not_reached ();
1621 * mono_class_get_vtable_entry:
1623 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
1624 * LOCKING: Acquires the loader lock.
1627 mono_class_get_vtable_entry (MonoClass
*klass
, int offset
)
1631 if (m_class_get_rank (klass
) == 1) {
1632 MonoClass
*klass_parent
= m_class_get_parent (klass
);
1634 * szarrays do not overwrite any methods of Array, so we can avoid
1635 * initializing their vtables in some cases.
1637 mono_class_setup_vtable (klass_parent
);
1638 if (offset
< m_class_get_vtable_size (klass_parent
))
1639 return m_class_get_vtable (klass_parent
) [offset
];
1642 if (mono_class_is_ginst (klass
)) {
1644 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1645 mono_class_setup_vtable (gklass
);
1646 m
= m_class_get_vtable (gklass
) [offset
];
1648 m
= mono_class_inflate_generic_method_full_checked (m
, klass
, mono_class_get_context (klass
), error
);
1649 g_assert (is_ok (error
)); /* FIXME don't swallow this error */
1651 mono_class_setup_vtable (klass
);
1652 if (mono_class_has_failure (klass
))
1654 m
= m_class_get_vtable (klass
) [offset
];
1661 * mono_class_get_vtable_size:
1663 * Return the vtable size for KLASS.
1666 mono_class_get_vtable_size (MonoClass
*klass
)
1668 mono_class_setup_vtable (klass
);
1670 return m_class_get_vtable_size (klass
);
1674 collect_implemented_interfaces_aux (MonoClass
*klass
, GPtrArray
**res
, GHashTable
**ifaces
, MonoError
*error
)
1679 mono_class_setup_interfaces (klass
, error
);
1680 return_if_nok (error
);
1682 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
1683 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
1684 ic
= klass_interfaces
[i
];
1687 *res
= g_ptr_array_new ();
1688 if (*ifaces
== NULL
)
1689 *ifaces
= g_hash_table_new (NULL
, NULL
);
1690 if (g_hash_table_lookup (*ifaces
, ic
))
1692 /* A gparam is not an implemented interface for the purposes of
1693 * mono_class_get_implemented_interfaces */
1694 if (mono_class_is_gparam (ic
))
1696 g_ptr_array_add (*res
, ic
);
1697 g_hash_table_insert (*ifaces
, ic
, ic
);
1698 mono_class_init_internal (ic
);
1699 if (mono_class_has_failure (ic
)) {
1700 mono_error_set_type_load_class (error
, ic
, "Error Loading class");
1704 collect_implemented_interfaces_aux (ic
, res
, ifaces
, error
);
1705 return_if_nok (error
);
1710 mono_class_get_implemented_interfaces (MonoClass
*klass
, MonoError
*error
)
1712 GPtrArray
*res
= NULL
;
1713 GHashTable
*ifaces
= NULL
;
1715 collect_implemented_interfaces_aux (klass
, &res
, &ifaces
, error
);
1717 g_hash_table_destroy (ifaces
);
1718 if (!is_ok (error
)) {
1720 g_ptr_array_free (res
, TRUE
);
1726 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
1728 mono_class_interface_offset (MonoClass
*klass
, MonoClass
*itf
)
1731 MonoClass
**klass_interfaces_packed
= m_class_get_interfaces_packed (klass
);
1732 for (i
= m_class_get_interface_offsets_count (klass
) -1 ; i
>= 0 ; i
-- ){
1733 MonoClass
*result
= klass_interfaces_packed
[i
];
1734 if (m_class_get_interface_id(result
) == m_class_get_interface_id(itf
)) {
1735 return m_class_get_interface_offsets_packed (klass
) [i
];
1742 * mono_class_interface_offset_with_variance:
1744 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
1745 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
1747 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
1749 * FIXME figure out MS disambiguation rules and fix this function.
1752 mono_class_interface_offset_with_variance (MonoClass
*klass
, MonoClass
*itf
, gboolean
*non_exact_match
)
1754 int i
= mono_class_interface_offset (klass
, itf
);
1755 *non_exact_match
= FALSE
;
1759 int klass_interface_offsets_count
= m_class_get_interface_offsets_count (klass
);
1761 if (m_class_is_array_special_interface (itf
) && m_class_get_rank (klass
) < 2) {
1762 MonoClass
*gtd
= mono_class_get_generic_type_definition (itf
);
1765 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1766 if (mono_class_is_variant_compatible (itf
, m_class_get_interfaces_packed (klass
) [i
], FALSE
)) {
1768 *non_exact_match
= TRUE
;
1774 return m_class_get_interface_offsets_packed (klass
) [found
];
1776 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1777 if (mono_class_get_generic_type_definition (m_class_get_interfaces_packed (klass
) [i
]) == gtd
) {
1779 *non_exact_match
= TRUE
;
1787 return m_class_get_interface_offsets_packed (klass
) [found
];
1790 if (!mono_class_has_variant_generic_params (itf
))
1793 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1794 if (mono_class_is_variant_compatible (itf
, m_class_get_interfaces_packed (klass
) [i
], FALSE
)) {
1795 *non_exact_match
= TRUE
;
1796 return m_class_get_interface_offsets_packed (klass
) [i
];
1805 * mono_method_get_vtable_slot:
1807 * Returns method->slot, computing it if neccesary. Return -1 on failure.
1808 * LOCKING: Acquires the loader lock.
1810 * FIXME Use proper MonoError machinery here.
1813 mono_method_get_vtable_slot (MonoMethod
*method
)
1815 if (method
->slot
== -1) {
1816 mono_class_setup_vtable (method
->klass
);
1817 if (mono_class_has_failure (method
->klass
))
1819 if (method
->slot
== -1) {
1823 if (!mono_class_is_ginst (method
->klass
)) {
1824 g_assert (method
->is_inflated
);
1825 return mono_method_get_vtable_slot (((MonoMethodInflated
*)method
)->declaring
);
1828 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
1829 g_assert (mono_class_is_ginst (method
->klass
));
1830 gklass
= mono_class_get_generic_class (method
->klass
)->container_class
;
1831 mono_class_setup_methods (method
->klass
);
1832 MonoMethod
**klass_methods
= m_class_get_methods (method
->klass
);
1833 g_assert (klass_methods
);
1834 mcount
= mono_class_get_method_count (method
->klass
);
1835 for (i
= 0; i
< mcount
; ++i
) {
1836 if (klass_methods
[i
] == method
)
1839 g_assert (i
< mcount
);
1840 g_assert (m_class_get_methods (gklass
));
1841 method
->slot
= m_class_get_methods (gklass
) [i
]->slot
;
1843 g_assert (method
->slot
!= -1);
1845 return method
->slot
;
1849 * mono_method_get_vtable_index:
1850 * \param method a method
1852 * Returns the index into the runtime vtable to access the method or,
1853 * in the case of a virtual generic method, the virtual generic method
1854 * thunk. Returns -1 on failure.
1856 * FIXME Use proper MonoError machinery here.
1859 mono_method_get_vtable_index (MonoMethod
*method
)
1861 if (method
->is_inflated
&& (method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
1862 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
1863 if (imethod
->declaring
->is_generic
)
1864 return mono_method_get_vtable_slot (imethod
->declaring
);
1866 return mono_method_get_vtable_slot (method
);
1870 * mono_class_has_finalizer:
1872 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
1875 * LOCKING: Acquires the loader lock;
1878 mono_class_has_finalizer (MonoClass
*klass
)
1880 if (!m_class_is_has_finalize_inited (klass
))
1881 mono_class_setup_has_finalizer (klass
);
1883 return m_class_has_finalize (klass
);
1887 mono_is_corlib_image (MonoImage
*image
)
1889 return image
== mono_defaults
.corlib
;
1893 /** Is klass a Nullable<T> ginst? */
1895 mono_class_is_nullable (MonoClass
*klass
)
1897 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1898 return gklass
&& gklass
->container_class
== mono_defaults
.generic_nullable_class
;
1901 /** if klass is T? return T */
1903 mono_class_get_nullable_param_internal (MonoClass
*klass
)
1905 g_assert (mono_class_is_nullable (klass
));
1906 return mono_class_from_mono_type_internal (mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0]);
1910 mono_class_get_nullable_param (MonoClass
*klass
)
1912 MonoClass
*result
= NULL
;
1913 MONO_ENTER_GC_UNSAFE
;
1914 result
= mono_class_get_nullable_param_internal (klass
);
1915 MONO_EXIT_GC_UNSAFE
;
1920 mono_type_is_primitive (MonoType
*type
)
1922 return (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_R8
) ||
1923 type
-> type
== MONO_TYPE_I
|| type
->type
== MONO_TYPE_U
;
1927 get_image_for_container (MonoGenericContainer
*container
)
1930 if (container
->is_anonymous
) {
1931 result
= container
->owner
.image
;
1934 if (container
->is_method
) {
1935 MonoMethod
*method
= container
->owner
.method
;
1936 g_assert_checked (method
);
1937 klass
= method
->klass
;
1939 klass
= container
->owner
.klass
;
1941 g_assert_checked (klass
);
1942 result
= m_class_get_image (klass
);
1949 mono_get_image_for_generic_param (MonoGenericParam
*param
)
1951 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
1952 g_assert_checked (container
);
1953 return get_image_for_container (container
);
1956 // Make a string in the designated image consisting of a single integer.
1957 #define INT_STRING_SIZE 16
1959 mono_make_generic_name_string (MonoImage
*image
, int num
)
1961 char *name
= (char *)mono_image_alloc0 (image
, INT_STRING_SIZE
);
1962 g_snprintf (name
, INT_STRING_SIZE
, "%d", num
);
1967 * mono_class_from_generic_parameter:
1968 * \param param Parameter to find/construct a class for.
1969 * \param arg2 Is ignored.
1970 * \param arg3 Is ignored.
1973 mono_class_from_generic_parameter (MonoGenericParam
*param
, MonoImage
*arg2 G_GNUC_UNUSED
, gboolean arg3 G_GNUC_UNUSED
)
1975 return mono_class_create_generic_parameter (param
);
1979 * mono_ptr_class_get:
1982 mono_ptr_class_get (MonoType
*type
)
1984 return mono_class_create_ptr (type
);
1988 * mono_class_from_mono_type:
1989 * \param type describes the type to return
1990 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
1993 mono_class_from_mono_type (MonoType
*type
)
1996 MONO_ENTER_GC_UNSAFE
;
1997 result
= mono_class_from_mono_type_internal (type
);
1998 MONO_EXIT_GC_UNSAFE
;
2003 mono_class_from_mono_type_internal (MonoType
*type
)
2006 switch (type
->type
) {
2007 case MONO_TYPE_OBJECT
:
2008 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.object_class
;
2009 case MONO_TYPE_VOID
:
2010 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.void_class
;
2011 case MONO_TYPE_BOOLEAN
:
2012 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.boolean_class
;
2013 case MONO_TYPE_CHAR
:
2014 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.char_class
;
2016 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.sbyte_class
;
2018 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.byte_class
;
2020 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int16_class
;
2022 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint16_class
;
2024 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int32_class
;
2026 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint32_class
;
2028 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int_class
;
2030 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint_class
;
2032 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int64_class
;
2034 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint64_class
;
2036 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.single_class
;
2038 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.double_class
;
2039 case MONO_TYPE_STRING
:
2040 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.string_class
;
2041 case MONO_TYPE_TYPEDBYREF
:
2042 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.typed_reference_class
;
2043 case MONO_TYPE_ARRAY
:
2044 return mono_class_create_bounded_array (type
->data
.array
->eklass
, type
->data
.array
->rank
, TRUE
);
2046 return mono_class_create_ptr (type
->data
.type
);
2047 case MONO_TYPE_FNPTR
:
2048 return mono_class_create_fnptr (type
->data
.method
);
2049 case MONO_TYPE_SZARRAY
:
2050 return mono_class_create_array (type
->data
.klass
, 1);
2051 case MONO_TYPE_CLASS
:
2052 case MONO_TYPE_VALUETYPE
:
2053 return type
->data
.klass
;
2054 case MONO_TYPE_GENERICINST
:
2055 return mono_class_create_generic_inst (type
->data
.generic_class
);
2056 case MONO_TYPE_MVAR
:
2058 return mono_class_create_generic_parameter (type
->data
.generic_param
);
2060 g_warning ("mono_class_from_mono_type_internal: implement me 0x%02x\n", type
->type
);
2061 g_assert_not_reached ();
2064 // Yes, this returns NULL, even if it is documented as not doing so, but there
2065 // is no way for the code to make it this far, due to the assert above.
2070 * mono_type_retrieve_from_typespec
2071 * \param image context where the image is created
2072 * \param type_spec typespec token
2073 * \param context the generic context used to evaluate generic instantiations in
2076 mono_type_retrieve_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, gboolean
*did_inflate
, MonoError
*error
)
2078 MonoType
*t
= mono_type_create_from_typespec_checked (image
, type_spec
, error
);
2080 *did_inflate
= FALSE
;
2085 if (context
&& (context
->class_inst
|| context
->method_inst
)) {
2086 MonoType
*inflated
= inflate_generic_type (NULL
, t
, context
, error
);
2088 if (!is_ok (error
)) {
2094 *did_inflate
= TRUE
;
2101 * mono_class_create_from_typespec
2102 * \param image context where the image is created
2103 * \param type_spec typespec token
2104 * \param context the generic context used to evaluate generic instantiations in
2107 mono_class_create_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, MonoError
*error
)
2110 gboolean inflated
= FALSE
;
2111 MonoType
*t
= mono_type_retrieve_from_typespec (image
, type_spec
, context
, &inflated
, error
);
2112 return_val_if_nok (error
, NULL
);
2113 ret
= mono_class_from_mono_type_internal (t
);
2115 mono_metadata_free_type (t
);
2120 * mono_bounded_array_class_get:
2121 * \param element_class element class
2122 * \param rank the dimension of the array class
2123 * \param bounded whenever the array has non-zero bounds
2124 * \returns A class object describing the array with element type \p element_type and
2125 * dimension \p rank.
2128 mono_bounded_array_class_get (MonoClass
*eclass
, guint32 rank
, gboolean bounded
)
2130 return mono_class_create_bounded_array (eclass
, rank
, bounded
);
2134 * mono_array_class_get:
2135 * \param element_class element class
2136 * \param rank the dimension of the array class
2137 * \returns A class object describing the array with element type \p element_type and
2138 * dimension \p rank.
2141 mono_array_class_get (MonoClass
*eclass
, guint32 rank
)
2143 return mono_class_create_array (eclass
, rank
);
2147 * mono_class_instance_size:
2148 * \param klass a class
2150 * Use to get the size of a class in bytes.
2152 * \returns The size of an object instance
2155 mono_class_instance_size (MonoClass
*klass
)
2157 if (!m_class_is_size_inited (klass
))
2158 mono_class_init_internal (klass
);
2160 return m_class_get_instance_size (klass
);
2164 * mono_class_min_align:
2165 * \param klass a class
2167 * Use to get the computed minimum alignment requirements for the specified class.
2169 * Returns: minimum alignment requirements
2172 mono_class_min_align (MonoClass
*klass
)
2174 if (!m_class_is_size_inited (klass
))
2175 mono_class_init_internal (klass
);
2177 return m_class_get_min_align (klass
);
2181 * mono_class_data_size:
2182 * \param klass a class
2184 * \returns The size of the static class data
2187 mono_class_data_size (MonoClass
*klass
)
2189 if (!m_class_is_inited (klass
))
2190 mono_class_init_internal (klass
);
2191 /* This can happen with dynamically created types */
2192 if (!m_class_is_fields_inited (klass
))
2193 mono_class_setup_fields (klass
);
2195 /* in arrays, sizes.class_size is unioned with element_size
2196 * and arrays have no static fields
2198 if (m_class_get_rank (klass
))
2200 return m_class_get_sizes (klass
).class_size
;
2204 * Auxiliary routine to mono_class_get_field
2206 * Takes a field index instead of a field token.
2208 static MonoClassField
*
2209 mono_class_get_field_idx (MonoClass
*klass
, int idx
)
2211 mono_class_setup_fields (klass
);
2212 if (mono_class_has_failure (klass
))
2216 int first_field_idx
= mono_class_get_first_field_idx (klass
);
2217 int fcount
= mono_class_get_field_count (klass
);
2218 MonoImage
*klass_image
= m_class_get_image (klass
);
2219 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
2220 if (klass_image
->uncompressed_metadata
) {
2222 * first_field_idx points to the FieldPtr table, while idx points into the
2223 * Field table, so we have to do a search.
2225 /*FIXME this is broken for types with multiple fields with the same name.*/
2226 const char *name
= mono_metadata_string_heap (klass_image
, mono_metadata_decode_row_col (&klass_image
->tables
[MONO_TABLE_FIELD
], idx
, MONO_FIELD_NAME
));
2229 for (i
= 0; i
< fcount
; ++i
)
2230 if (mono_field_get_name (&klass_fields
[i
]) == name
)
2231 return &klass_fields
[i
];
2232 g_assert_not_reached ();
2235 if ((idx
>= first_field_idx
) && (idx
< first_field_idx
+ fcount
)){
2236 return &klass_fields
[idx
- first_field_idx
];
2240 klass
= m_class_get_parent (klass
);
2246 * mono_class_get_field:
2247 * \param class the class to lookup the field.
2248 * \param field_token the field token
2250 * \returns A \c MonoClassField representing the type and offset of
2251 * the field, or a NULL value if the field does not belong to this
2255 mono_class_get_field (MonoClass
*klass
, guint32 field_token
)
2257 int idx
= mono_metadata_token_index (field_token
);
2259 g_assert (mono_metadata_token_code (field_token
) == MONO_TOKEN_FIELD_DEF
);
2261 return mono_class_get_field_idx (klass
, idx
- 1);
2265 * mono_class_get_field_from_name:
2266 * \param klass the class to lookup the field.
2267 * \param name the field name
2269 * Search the class \p klass and its parents for a field with the name \p name.
2271 * \returns The \c MonoClassField pointer of the named field or NULL
2274 mono_class_get_field_from_name (MonoClass
*klass
, const char *name
)
2276 MonoClassField
*result
;
2277 MONO_ENTER_GC_UNSAFE
;
2278 result
= mono_class_get_field_from_name_full (klass
, name
, NULL
);
2279 MONO_EXIT_GC_UNSAFE
;
2284 * mono_class_get_field_from_name_full:
2285 * \param klass the class to lookup the field.
2286 * \param name the field name
2287 * \param type the type of the fields. This optional.
2289 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
2291 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
2292 * of its generic type definition.
2294 * \returns The MonoClassField pointer of the named field or NULL
2297 mono_class_get_field_from_name_full (MonoClass
*klass
, const char *name
, MonoType
*type
)
2299 MONO_REQ_GC_UNSAFE_MODE
;
2303 mono_class_setup_fields (klass
);
2304 if (mono_class_has_failure (klass
))
2308 int fcount
= mono_class_get_field_count (klass
);
2309 for (i
= 0; i
< fcount
; ++i
) {
2310 MonoClassField
*field
= &m_class_get_fields (klass
) [i
];
2312 if (strcmp (name
, mono_field_get_name (field
)) != 0)
2316 MonoType
*field_type
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
)->type
;
2317 if (!mono_metadata_type_equal_full (type
, field_type
, TRUE
))
2322 klass
= m_class_get_parent (klass
);
2328 * mono_class_get_field_token:
2329 * \param field the field we need the token of
2331 * Get the token of a field. Note that the tokesn is only valid for the image
2332 * the field was loaded from. Don't use this function for fields in dynamic types.
2334 * \returns The token representing the field in the image it was loaded from.
2337 mono_class_get_field_token (MonoClassField
*field
)
2339 MonoClass
*klass
= field
->parent
;
2342 mono_class_setup_fields (klass
);
2345 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
2348 int first_field_idx
= mono_class_get_first_field_idx (klass
);
2349 int fcount
= mono_class_get_field_count (klass
);
2350 for (i
= 0; i
< fcount
; ++i
) {
2351 if (&klass_fields
[i
] == field
) {
2352 int idx
= first_field_idx
+ i
+ 1;
2354 if (m_class_get_image (klass
)->uncompressed_metadata
)
2355 idx
= mono_metadata_translate_token_index (m_class_get_image (klass
), MONO_TABLE_FIELD
, idx
);
2356 return mono_metadata_make_token (MONO_TABLE_FIELD
, idx
);
2359 klass
= m_class_get_parent (klass
);
2362 g_assert_not_reached ();
2367 mono_field_get_index (MonoClassField
*field
)
2369 int index
= field
- m_class_get_fields (field
->parent
);
2370 g_assert (index
>= 0 && index
< mono_class_get_field_count (field
->parent
));
2376 * mono_class_get_field_default_value:
2378 * Return the default value of the field as a pointer into the metadata blob.
2381 mono_class_get_field_default_value (MonoClassField
*field
, MonoTypeEnum
*def_type
)
2384 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
2386 MonoClass
*klass
= field
->parent
;
2387 MonoFieldDefaultValue
*def_values
;
2389 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
);
2391 def_values
= mono_class_get_field_def_values (klass
);
2393 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
2395 mono_class_set_field_def_values (klass
, def_values
);
2398 field_index
= mono_field_get_index (field
);
2400 if (!def_values
[field_index
].data
) {
2401 MonoImage
*field_parent_image
= m_class_get_image (field
->parent
);
2402 cindex
= mono_metadata_get_constant_index (field_parent_image
, mono_class_get_field_token (field
), 0);
2406 g_assert (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
));
2408 mono_metadata_decode_row (&field_parent_image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
2409 def_values
[field_index
].def_type
= (MonoTypeEnum
)constant_cols
[MONO_CONSTANT_TYPE
];
2410 mono_memory_barrier ();
2411 def_values
[field_index
].data
= (const char *)mono_metadata_blob_heap (field_parent_image
, constant_cols
[MONO_CONSTANT_VALUE
]);
2414 *def_type
= def_values
[field_index
].def_type
;
2415 return def_values
[field_index
].data
;
2419 mono_property_get_index (MonoProperty
*prop
)
2421 MonoClassPropertyInfo
*info
= mono_class_get_property_info (prop
->parent
);
2422 int index
= prop
- info
->properties
;
2424 g_assert (index
>= 0 && index
< info
->count
);
2430 * mono_class_get_property_default_value:
2432 * Return the default value of the field as a pointer into the metadata blob.
2435 mono_class_get_property_default_value (MonoProperty
*property
, MonoTypeEnum
*def_type
)
2438 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
2439 MonoClass
*klass
= property
->parent
;
2440 MonoImage
*klass_image
= m_class_get_image (klass
);
2442 g_assert (property
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
);
2444 * We don't cache here because it is not used by C# so it's quite rare, but
2445 * we still do the lookup in klass->ext because that is where the data
2446 * is stored for dynamic assemblies.
2449 if (image_is_dynamic (klass_image
)) {
2450 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
2451 int prop_index
= mono_property_get_index (property
);
2452 if (info
->def_values
&& info
->def_values
[prop_index
].data
) {
2453 *def_type
= info
->def_values
[prop_index
].def_type
;
2454 return info
->def_values
[prop_index
].data
;
2458 cindex
= mono_metadata_get_constant_index (klass_image
, mono_class_get_property_token (property
), 0);
2462 mono_metadata_decode_row (&klass_image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
2463 *def_type
= (MonoTypeEnum
)constant_cols
[MONO_CONSTANT_TYPE
];
2464 return (const char *)mono_metadata_blob_heap (klass_image
, constant_cols
[MONO_CONSTANT_VALUE
]);
2468 * mono_class_get_event_token:
2471 mono_class_get_event_token (MonoEvent
*event
)
2473 MonoClass
*klass
= event
->parent
;
2477 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
2479 for (i
= 0; i
< info
->count
; ++i
) {
2480 if (&info
->events
[i
] == event
)
2481 return mono_metadata_make_token (MONO_TABLE_EVENT
, info
->first
+ i
+ 1);
2484 klass
= m_class_get_parent (klass
);
2487 g_assert_not_reached ();
2492 mono_class_get_property_from_name_internal (MonoClass
*klass
, const char *name
)
2494 MONO_REQ_GC_UNSAFE_MODE
;
2497 gpointer iter
= NULL
;
2498 while ((p
= mono_class_get_properties (klass
, &iter
))) {
2499 if (! strcmp (name
, p
->name
))
2502 klass
= m_class_get_parent (klass
);
2508 * mono_class_get_property_token:
2509 * \param prop MonoProperty to query
2511 * \returns The ECMA token for the specified property.
2514 mono_class_get_property_token (MonoProperty
*prop
)
2516 MonoClass
*klass
= prop
->parent
;
2520 gpointer iter
= NULL
;
2521 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
2522 while ((p
= mono_class_get_properties (klass
, &iter
))) {
2523 if (&info
->properties
[i
] == prop
)
2524 return mono_metadata_make_token (MONO_TABLE_PROPERTY
, info
->first
+ i
+ 1);
2528 klass
= m_class_get_parent (klass
);
2531 g_assert_not_reached ();
2536 * mono_class_name_from_token:
2539 mono_class_name_from_token (MonoImage
*image
, guint32 type_token
)
2541 const char *name
, *nspace
;
2542 if (image_is_dynamic (image
))
2543 return g_strdup_printf ("DynamicType 0x%08x", type_token
);
2545 switch (type_token
& 0xff000000){
2546 case MONO_TOKEN_TYPE_DEF
: {
2547 guint32 cols
[MONO_TYPEDEF_SIZE
];
2548 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2549 guint tidx
= mono_metadata_token_index (type_token
);
2551 if (tidx
> tt
->rows
)
2552 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2554 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
2555 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2556 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2557 if (strlen (nspace
) == 0)
2558 return g_strdup_printf ("%s", name
);
2560 return g_strdup_printf ("%s.%s", nspace
, name
);
2563 case MONO_TOKEN_TYPE_REF
: {
2565 guint32 cols
[MONO_TYPEREF_SIZE
];
2566 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2567 guint tidx
= mono_metadata_token_index (type_token
);
2570 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2572 if (!mono_verifier_verify_typeref_row (image
, tidx
- 1, error
)) {
2573 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (error
));
2574 mono_error_cleanup (error
);
2578 mono_metadata_decode_row (t
, tidx
-1, cols
, MONO_TYPEREF_SIZE
);
2579 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
2580 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
2581 if (strlen (nspace
) == 0)
2582 return g_strdup_printf ("%s", name
);
2584 return g_strdup_printf ("%s.%s", nspace
, name
);
2587 case MONO_TOKEN_TYPE_SPEC
:
2588 return g_strdup_printf ("Typespec 0x%08x", type_token
);
2590 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2595 mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
)
2597 if (image_is_dynamic (image
))
2598 return g_strdup_printf ("DynamicAssembly %s", image
->name
);
2600 switch (type_token
& 0xff000000){
2601 case MONO_TOKEN_TYPE_DEF
:
2602 if (image
->assembly
)
2603 return mono_stringify_assembly_name (&image
->assembly
->aname
);
2604 else if (image
->assembly_name
)
2605 return g_strdup (image
->assembly_name
);
2606 return g_strdup_printf ("%s", image
->name
? image
->name
: "[Could not resolve assembly name");
2607 case MONO_TOKEN_TYPE_REF
: {
2609 MonoAssemblyName aname
;
2610 guint32 cols
[MONO_TYPEREF_SIZE
];
2611 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2612 guint32 idx
= mono_metadata_token_index (type_token
);
2615 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2617 if (!mono_verifier_verify_typeref_row (image
, idx
- 1, error
)) {
2618 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (error
));
2619 mono_error_cleanup (error
);
2622 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPEREF_SIZE
);
2624 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
2625 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
2626 case MONO_RESOLUTION_SCOPE_MODULE
:
2628 return g_strdup ("");
2629 case MONO_RESOLUTION_SCOPE_MODULEREF
:
2631 return g_strdup ("");
2632 case MONO_RESOLUTION_SCOPE_TYPEREF
:
2634 return g_strdup ("");
2635 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
2636 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
2637 return mono_stringify_assembly_name (&aname
);
2639 g_assert_not_reached ();
2643 case MONO_TOKEN_TYPE_SPEC
:
2645 return g_strdup ("");
2647 g_assert_not_reached ();
2654 * mono_class_get_full:
2655 * \param image the image where the class resides
2656 * \param type_token the token for the class
2657 * \param context the generic context used to evaluate generic instantiations in
2658 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
2659 * \returns The \c MonoClass that represents \p type_token in \p image
2662 mono_class_get_full (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
)
2666 klass
= mono_class_get_checked (image
, type_token
, error
);
2668 if (klass
&& context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
2669 klass
= mono_class_inflate_generic_class_checked (klass
, context
, error
);
2671 mono_error_assert_ok (error
);
2677 mono_class_get_and_inflate_typespec_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
2682 klass
= mono_class_get_checked (image
, type_token
, error
);
2684 if (klass
&& context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
2685 klass
= mono_class_inflate_generic_class_checked (klass
, context
, error
);
2690 * mono_class_get_checked:
2691 * \param image the image where the class resides
2692 * \param type_token the token for the class
2693 * \param error error object to return any error
2695 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
2698 mono_class_get_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
2700 MonoClass
*klass
= NULL
;
2704 if (image_is_dynamic (image
)) {
2705 int table
= mono_metadata_token_table (type_token
);
2707 if (table
!= MONO_TABLE_TYPEDEF
&& table
!= MONO_TABLE_TYPEREF
&& table
!= MONO_TABLE_TYPESPEC
) {
2708 mono_error_set_bad_image (error
, image
,"Bad token table for dynamic image: %x", table
);
2711 klass
= (MonoClass
*)mono_lookup_dynamic_token (image
, type_token
, NULL
, error
);
2715 switch (type_token
& 0xff000000){
2716 case MONO_TOKEN_TYPE_DEF
:
2717 klass
= mono_class_create_from_typedef (image
, type_token
, error
);
2719 case MONO_TOKEN_TYPE_REF
:
2720 klass
= mono_class_from_typeref_checked (image
, type_token
, error
);
2722 case MONO_TOKEN_TYPE_SPEC
:
2723 klass
= mono_class_create_from_typespec (image
, type_token
, NULL
, error
);
2726 mono_error_set_bad_image (error
, image
, "Unknown type token %x", type_token
& 0xff000000);
2730 /* Generic case, should be avoided for when a better error is possible. */
2731 if (!klass
&& is_ok (error
)) {
2732 char *name
= mono_class_name_from_token (image
, type_token
);
2733 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
2734 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
);
2742 * mono_type_get_checked:
2743 * \param image the image where the type resides
2744 * \param type_token the token for the type
2745 * \param context the generic context used to evaluate generic instantiations in
2746 * \param error Error handling context
2748 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
2750 * \returns The MonoType that represents \p type_token in \p image
2753 mono_type_get_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
2755 MonoType
*type
= NULL
;
2756 gboolean inflated
= FALSE
;
2760 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
2761 if (image_is_dynamic (image
)) {
2762 MonoClass
*klass
= (MonoClass
*)mono_lookup_dynamic_token (image
, type_token
, context
, error
);
2763 return_val_if_nok (error
, NULL
);
2764 return m_class_get_byval_arg (klass
);
2767 if ((type_token
& 0xff000000) != MONO_TOKEN_TYPE_SPEC
) {
2768 MonoClass
*klass
= mono_class_get_checked (image
, type_token
, error
);
2772 if (m_class_has_failure (klass
)) {
2773 mono_error_set_for_class_failure (error
, klass
);
2776 return m_class_get_byval_arg (klass
);
2779 type
= mono_type_retrieve_from_typespec (image
, type_token
, context
, &inflated
, error
);
2786 MonoType
*tmp
= type
;
2787 type
= m_class_get_byval_arg (mono_class_from_mono_type_internal (type
));
2788 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
2789 * A MonoClass::_byval_arg of a generic type definion has type CLASS.
2790 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with _byval_arg.
2792 * The long term solution is to chaise this places and make then set MonoType::type correctly.
2794 if (type
->type
!= tmp
->type
)
2797 mono_metadata_free_type (tmp
);
2804 * \param image image where the class token will be looked up.
2805 * \param type_token a type token from the image
2806 * \returns the \c MonoClass with the given \p type_token on the \p image
2809 mono_class_get (MonoImage
*image
, guint32 type_token
)
2813 MonoClass
*result
= mono_class_get_checked (image
, type_token
, error
);
2814 mono_error_assert_ok (error
);
2819 * mono_image_init_name_cache:
2821 * Initializes the class name cache stored in image->name_cache.
2823 * LOCKING: Acquires the corresponding image lock.
2826 mono_image_init_name_cache (MonoImage
*image
)
2828 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2829 guint32 cols
[MONO_TYPEDEF_SIZE
];
2832 guint32 i
, visib
, nspace_index
;
2833 GHashTable
*name_cache2
, *nspace_table
, *the_name_cache
;
2835 if (image
->name_cache
)
2838 the_name_cache
= g_hash_table_new (g_str_hash
, g_str_equal
);
2840 if (image_is_dynamic (image
)) {
2841 mono_image_lock (image
);
2842 if (image
->name_cache
) {
2843 /* Somebody initialized it before us */
2844 g_hash_table_destroy (the_name_cache
);
2846 mono_atomic_store_release (&image
->name_cache
, the_name_cache
);
2848 mono_image_unlock (image
);
2852 /* Temporary hash table to avoid lookups in the nspace_table */
2853 name_cache2
= g_hash_table_new (NULL
, NULL
);
2855 for (i
= 1; i
<= t
->rows
; ++i
) {
2856 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
2857 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
2859 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
2860 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
2862 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
2864 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2865 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2867 nspace_index
= cols
[MONO_TYPEDEF_NAMESPACE
];
2868 nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
2869 if (!nspace_table
) {
2870 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2871 g_hash_table_insert (the_name_cache
, (char*)nspace
, nspace_table
);
2872 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
2875 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (i
));
2878 /* Load type names from EXPORTEDTYPES table */
2880 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
2881 guint32 cols
[MONO_EXP_TYPE_SIZE
];
2884 for (i
= 0; i
< t
->rows
; ++i
) {
2885 mono_metadata_decode_row (t
, i
, cols
, MONO_EXP_TYPE_SIZE
);
2887 guint32 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
2888 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_EXP_TYPE
)
2892 name
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAME
]);
2893 nspace
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAMESPACE
]);
2895 nspace_index
= cols
[MONO_EXP_TYPE_NAMESPACE
];
2896 nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
2897 if (!nspace_table
) {
2898 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2899 g_hash_table_insert (the_name_cache
, (char*)nspace
, nspace_table
);
2900 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
2903 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE
, i
+ 1)));
2907 g_hash_table_destroy (name_cache2
);
2909 mono_image_lock (image
);
2910 if (image
->name_cache
) {
2911 /* Somebody initialized it before us */
2912 g_hash_table_destroy (the_name_cache
);
2914 mono_atomic_store_release (&image
->name_cache
, the_name_cache
);
2916 mono_image_unlock (image
);
2919 /*FIXME Only dynamic assemblies should allow this operation.*/
2921 * mono_image_add_to_name_cache:
2924 mono_image_add_to_name_cache (MonoImage
*image
, const char *nspace
,
2925 const char *name
, guint32 index
)
2927 GHashTable
*nspace_table
;
2928 GHashTable
*name_cache
;
2931 mono_image_init_name_cache (image
);
2932 mono_image_lock (image
);
2934 name_cache
= image
->name_cache
;
2935 if (!(nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache
, nspace
))) {
2936 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2937 g_hash_table_insert (name_cache
, (char *)nspace
, (char *)nspace_table
);
2940 if ((old_index
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, (char*) name
))))
2941 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index
, image
->name
, nspace
, name
);
2943 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (index
));
2945 mono_image_unlock (image
);
2954 find_all_nocase (gpointer key
, gpointer value
, gpointer user_data
)
2956 char *name
= (char*)key
;
2957 FindAllUserData
*data
= (FindAllUserData
*)user_data
;
2958 if (mono_utf8_strcasecmp (name
, (char*)data
->key
) == 0)
2959 data
->values
= g_slist_prepend (data
->values
, value
);
2968 find_nocase (gpointer key
, gpointer value
, gpointer user_data
)
2970 char *name
= (char*)key
;
2971 FindUserData
*data
= (FindUserData
*)user_data
;
2973 if (!data
->value
&& (mono_utf8_strcasecmp (name
, (char*)data
->key
) == 0))
2974 data
->value
= value
;
2978 * mono_class_from_name_case:
2979 * \param image The MonoImage where the type is looked up in
2980 * \param name_space the type namespace
2981 * \param name the type short name.
2982 * \deprecated use the mono_class_from_name_case_checked variant instead.
2984 * Obtains a \c MonoClass with a given namespace and a given name which
2985 * is located in the given \c MonoImage. The namespace and name
2986 * lookups are case insensitive.
2989 mono_class_from_name_case (MonoImage
*image
, const char* name_space
, const char *name
)
2992 MonoClass
*res
= mono_class_from_name_case_checked (image
, name_space
, name
, error
);
2993 mono_error_cleanup (error
);
2999 * mono_class_from_name_case_checked:
3000 * \param image The MonoImage where the type is looked up in
3001 * \param name_space the type namespace
3002 * \param name the type short name.
3005 * Obtains a MonoClass with a given namespace and a given name which
3006 * is located in the given MonoImage. The namespace and name
3007 * lookups are case insensitive.
3009 * \returns The MonoClass if the given namespace and name were found, or NULL if it
3010 * was not found. The \p error object will contain information about the problem
3014 mono_class_from_name_case_checked (MonoImage
*image
, const char *name_space
, const char *name
, MonoError
*error
)
3017 GHashTable
*visited_images
;
3019 visited_images
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
3021 klass
= mono_class_from_name_checked_aux (image
, name_space
, name
, visited_images
, FALSE
, error
);
3023 g_hash_table_destroy (visited_images
);
3029 return_nested_in (MonoClass
*klass
, char *nested
, gboolean case_sensitive
)
3032 char *s
= strchr (nested
, '/');
3033 gpointer iter
= NULL
;
3040 while ((found
= mono_class_get_nested_types (klass
, &iter
))) {
3041 const char *name
= m_class_get_name (found
);
3044 strcmp_result
= strcmp (name
, nested
);
3046 strcmp_result
= mono_utf8_strcasecmp (name
, nested
);
3048 if (strcmp_result
== 0) {
3050 return return_nested_in (found
, s
, case_sensitive
);
3058 search_modules (MonoImage
*image
, const char *name_space
, const char *name
, gboolean case_sensitive
, MonoError
*error
)
3060 MonoTableInfo
*file_table
= &image
->tables
[MONO_TABLE_FILE
];
3061 MonoImage
*file_image
;
3068 * The EXPORTEDTYPES table only contains public types, so have to search the
3070 * Note: image->modules contains the contents of the MODULEREF table, while
3071 * the real module list is in the FILE table.
3073 for (i
= 0; i
< file_table
->rows
; i
++) {
3074 guint32 cols
[MONO_FILE_SIZE
];
3075 mono_metadata_decode_row (file_table
, i
, cols
, MONO_FILE_SIZE
);
3076 if (cols
[MONO_FILE_FLAGS
] == FILE_CONTAINS_NO_METADATA
)
3079 file_image
= mono_image_load_file_for_image_checked (image
, i
+ 1, error
);
3082 klass
= mono_class_from_name_checked (file_image
, name_space
, name
, error
);
3084 klass
= mono_class_from_name_case_checked (file_image
, name_space
, name
, error
);
3086 if (klass
|| !is_ok (error
))
3095 mono_class_from_name_checked_aux (MonoImage
*image
, const char* name_space
, const char *name
, GHashTable
* visited_images
, gboolean case_sensitive
, MonoError
*error
)
3097 GHashTable
*nspace_table
= NULL
;
3098 MonoImage
*loaded_image
= NULL
;
3107 // Checking visited images avoids stack overflows when cyclic references exist.
3108 if (g_hash_table_lookup (visited_images
, image
))
3111 g_hash_table_insert (visited_images
, image
, GUINT_TO_POINTER(1));
3113 if ((nested
= (char*)strchr (name
, '/'))) {
3114 int pos
= nested
- name
;
3115 int len
= strlen (name
);
3118 memcpy (buf
, name
, len
+ 1);
3120 nested
= buf
+ pos
+ 1;
3124 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
3125 // The AOT cache in get_class_from_name is case-sensitive, so don't bother with it for case-insensitive lookups
3126 if (get_class_from_name
&& image
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
== 0 && case_sensitive
) {
3127 gboolean res
= get_class_from_name (image
, name_space
, name
, &klass
);
3130 klass
= search_modules (image
, name_space
, name
, case_sensitive
, error
);
3135 return klass
? return_nested_in (klass
, nested
, case_sensitive
) : NULL
;
3141 mono_image_init_name_cache (image
);
3142 mono_image_lock (image
);
3144 if (case_sensitive
) {
3145 nspace_table
= (GHashTable
*)g_hash_table_lookup (image
->name_cache
, name_space
);
3148 token
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, name
));
3150 FindAllUserData all_user_data
= { name_space
, NULL
};
3151 FindUserData user_data
= { name
, NULL
};
3154 // We're forced to check all matching namespaces, not just the first one found,
3155 // because our desired type could be in any of the ones that match case-insensitively.
3156 g_hash_table_foreach (image
->name_cache
, find_all_nocase
, &all_user_data
);
3158 values
= all_user_data
.values
;
3159 while (values
&& !user_data
.value
) {
3160 nspace_table
= (GHashTable
*)values
->data
;
3161 g_hash_table_foreach (nspace_table
, find_nocase
, &user_data
);
3162 values
= values
->next
;
3165 g_slist_free (all_user_data
.values
);
3167 if (user_data
.value
)
3168 token
= GPOINTER_TO_UINT (user_data
.value
);
3171 mono_image_unlock (image
);
3173 if (!token
&& image_is_dynamic (image
) && image
->modules
) {
3174 /* Search modules as well */
3175 for (i
= 0; i
< image
->module_count
; ++i
) {
3176 MonoImage
*module
= image
->modules
[i
];
3179 klass
= mono_class_from_name_checked (module
, name_space
, name
, error
);
3181 klass
= mono_class_from_name_case_checked (module
, name_space
, name
, error
);
3183 if (klass
|| !is_ok (error
))
3189 klass
= search_modules (image
, name_space
, name
, case_sensitive
, error
);
3190 if (klass
|| !is_ok (error
))
3195 if (mono_metadata_token_table (token
) == MONO_TABLE_EXPORTEDTYPE
) {
3196 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3197 guint32 cols
[MONO_EXP_TYPE_SIZE
];
3200 idx
= mono_metadata_token_index (token
);
3202 mono_metadata_decode_row (t
, idx
- 1, cols
, MONO_EXP_TYPE_SIZE
);
3204 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
3205 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
) {
3206 loaded_image
= mono_assembly_load_module_checked (image
->assembly
, impl
>> MONO_IMPLEMENTATION_BITS
, error
);
3209 klass
= mono_class_from_name_checked_aux (loaded_image
, name_space
, name
, visited_images
, case_sensitive
, error
);
3211 return klass
? return_nested_in (klass
, nested
, case_sensitive
) : NULL
;
3213 } else if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_ASSEMBLYREF
) {
3214 guint32 assembly_idx
;
3216 assembly_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
3218 mono_assembly_load_reference (image
, assembly_idx
- 1);
3219 g_assert (image
->references
[assembly_idx
- 1]);
3220 if (image
->references
[assembly_idx
- 1] == (gpointer
)-1)
3222 klass
= mono_class_from_name_checked_aux (image
->references
[assembly_idx
- 1]->image
, name_space
, name
, visited_images
, case_sensitive
, error
);
3224 return klass
? return_nested_in (klass
, nested
, case_sensitive
) : NULL
;
3227 g_assert_not_reached ();
3231 token
= MONO_TOKEN_TYPE_DEF
| token
;
3233 klass
= mono_class_get_checked (image
, token
, error
);
3235 return return_nested_in (klass
, nested
, case_sensitive
);
3240 * mono_class_from_name_checked:
3241 * \param image The MonoImage where the type is looked up in
3242 * \param name_space the type namespace
3243 * \param name the type short name.
3245 * Obtains a MonoClass with a given namespace and a given name which
3246 * is located in the given MonoImage.
3248 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
3249 * set if the class was not found or it will return NULL and set the error if there was a loading error.
3252 mono_class_from_name_checked (MonoImage
*image
, const char* name_space
, const char *name
, MonoError
*error
)
3255 GHashTable
*visited_images
;
3257 visited_images
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
3259 klass
= mono_class_from_name_checked_aux (image
, name_space
, name
, visited_images
, TRUE
, error
);
3261 g_hash_table_destroy (visited_images
);
3267 * mono_class_from_name:
3268 * \param image The \c MonoImage where the type is looked up in
3269 * \param name_space the type namespace
3270 * \param name the type short name.
3272 * Obtains a \c MonoClass with a given namespace and a given name which
3273 * is located in the given \c MonoImage.
3275 * To reference nested classes, use the "/" character as a separator.
3276 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
3277 * inside \c Foo, like this: "class Foo { class Bar {} }".
3280 mono_class_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3283 MONO_ENTER_GC_UNSAFE
;
3286 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3287 mono_error_cleanup (error
); /* FIXME Don't swallow the error */
3288 MONO_EXIT_GC_UNSAFE
;
3293 * mono_class_load_from_name:
3294 * \param image The MonoImage where the type is looked up in
3295 * \param name_space the type namespace
3296 * \param name the type short name.
3298 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
3299 * This function should be used by the runtime for critical types to which there's no way to recover but crash
3300 * If they are missing. Thing of System.Object or System.String.
3303 mono_class_load_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3308 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3310 g_error ("Runtime critical type %s.%s not found", name_space
, name
);
3311 mono_error_assertf_ok (error
, "Could not load runtime critical type %s.%s", name_space
, name
);
3316 * mono_class_try_load_from_name:
3317 * \param image The MonoImage where the type is looked up in
3318 * \param name_space the type namespace
3319 * \param name the type short name.
3321 * This function tries to load a type, returning the class was found or NULL otherwise.
3322 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
3324 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
3325 * a type that we would otherwise assume to be available but was not due some error.
3329 mono_class_try_load_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3334 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3335 mono_error_assertf_ok (error
, "Could not load runtime critical type %s.%s", name_space
, name
);
3340 mono_interface_implements_interface (MonoClass
*interface_implementer
, MonoClass
*interface_implemented
)
3344 mono_class_setup_interfaces (interface_implementer
, error
);
3345 if (!is_ok (error
)) {
3346 mono_error_cleanup (error
);
3349 MonoClass
**klass_interfaces
= m_class_get_interfaces (interface_implementer
);
3350 for (i
= 0; i
< m_class_get_interface_count (interface_implementer
); i
++) {
3351 MonoClass
*ic
= klass_interfaces
[i
];
3352 if (mono_class_is_ginst (ic
))
3353 ic
= mono_class_get_generic_type_definition (ic
);
3354 if (ic
== interface_implemented
)
3361 mono_class_is_subclass_of_internal (MonoClass
*klass
, MonoClass
*klassc
,
3362 gboolean check_interfaces
)
3364 MONO_REQ_GC_UNSAFE_MODE
;
3365 /* FIXME test for interfaces with variant generic arguments */
3366 mono_class_init_internal (klass
);
3367 mono_class_init_internal (klassc
);
3369 if (check_interfaces
&& MONO_CLASS_IS_INTERFACE_INTERNAL (klassc
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3370 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass
, m_class_get_interface_id (klassc
)))
3372 } else if (check_interfaces
&& MONO_CLASS_IS_INTERFACE_INTERNAL (klassc
) && MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3375 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
3376 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
3377 MonoClass
*ic
= klass_interfaces
[i
];
3382 if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass
) && mono_class_has_parent (klass
, klassc
))
3387 * MS.NET thinks interfaces are a subclass of Object, so we think it as
3390 if (klassc
== mono_defaults
.object_class
)
3397 mono_type_is_generic_argument (MonoType
*type
)
3399 return type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
;
3403 mono_class_has_variant_generic_params (MonoClass
*klass
)
3406 MonoGenericContainer
*container
;
3408 if (!mono_class_is_ginst (klass
))
3411 container
= mono_class_get_generic_container (mono_class_get_generic_class (klass
)->container_class
);
3413 for (i
= 0; i
< container
->type_argc
; ++i
)
3414 if (mono_generic_container_get_param_info (container
, i
)->flags
& (MONO_GEN_PARAM_VARIANT
|MONO_GEN_PARAM_COVARIANT
))
3421 mono_gparam_is_reference_conversible (MonoClass
*target
, MonoClass
*candidate
, gboolean check_for_reference_conv
)
3423 if (target
== candidate
)
3426 if (check_for_reference_conv
&&
3427 mono_type_is_generic_argument (m_class_get_byval_arg (target
)) &&
3428 mono_type_is_generic_argument (m_class_get_byval_arg (candidate
))) {
3429 MonoGenericParam
*gparam
= m_class_get_byval_arg (candidate
)->data
.generic_param
;
3430 MonoGenericParamInfo
*pinfo
= mono_generic_param_info (gparam
);
3432 if (!pinfo
|| (pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0)
3435 if (!mono_class_is_assignable_from_internal (target
, candidate
))
3441 * @container the generic container from the GTD
3442 * @klass: the class to be assigned to
3443 * @oklass: the source class
3445 * Both @klass and @oklass must be instances of the same generic interface.
3447 * Returns: TRUE if @klass can be assigned to a @klass variable
3450 mono_class_is_variant_compatible (MonoClass
*klass
, MonoClass
*oklass
, gboolean check_for_reference_conv
)
3453 MonoType
**klass_argv
, **oklass_argv
;
3454 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3455 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3457 if (klass
== oklass
)
3460 /*Viable candidates are instances of the same generic interface*/
3461 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3464 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3465 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3467 for (j
= 0; j
< container
->type_argc
; ++j
) {
3468 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3469 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3471 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
) || (m_class_is_valuetype (param1_class
) && param1_class
!= param2_class
))
3475 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3476 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3478 if (param1_class
!= param2_class
) {
3479 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3480 if (!mono_gparam_is_reference_conversible (param1_class
, param2_class
, check_for_reference_conv
))
3482 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3483 if (!mono_gparam_is_reference_conversible (param2_class
, param1_class
, check_for_reference_conv
))
3493 mono_gparam_is_assignable_from (MonoClass
*target
, MonoClass
*candidate
)
3495 MonoGenericParam
*gparam
, *ogparam
;
3496 MonoGenericParamInfo
*tinfo
, *cinfo
;
3497 MonoClass
**candidate_class
;
3498 gboolean class_constraint_satisfied
, valuetype_constraint_satisfied
;
3501 if (target
== candidate
)
3503 MonoType
*target_byval_arg
= m_class_get_byval_arg (target
);
3504 MonoType
*candidate_byval_arg
= m_class_get_byval_arg (candidate
);
3505 if (target_byval_arg
->type
!= candidate_byval_arg
->type
)
3508 gparam
= target_byval_arg
->data
.generic_param
;
3509 ogparam
= candidate_byval_arg
->data
.generic_param
;
3510 tinfo
= mono_generic_param_info (gparam
);
3511 cinfo
= mono_generic_param_info (ogparam
);
3513 class_constraint_satisfied
= FALSE
;
3514 valuetype_constraint_satisfied
= FALSE
;
3516 /*candidate must have a super set of target's special constraints*/
3517 tmask
= tinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3518 cmask
= cinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3520 if (cinfo
->constraints
) {
3521 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3522 MonoClass
*cc
= *candidate_class
;
3523 MonoType
*cc_byval_arg
= m_class_get_byval_arg (cc
);
3525 if (mono_type_is_reference (cc_byval_arg
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc
))
3526 class_constraint_satisfied
= TRUE
;
3527 else if (!mono_type_is_reference (cc_byval_arg
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc
))
3528 valuetype_constraint_satisfied
= TRUE
;
3531 class_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) != 0;
3532 valuetype_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0;
3534 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) && !class_constraint_satisfied
)
3536 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) && !valuetype_constraint_satisfied
)
3538 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) && !((cmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) ||
3539 valuetype_constraint_satisfied
)) {
3544 /*candidate type constraints must be a superset of target's*/
3545 if (tinfo
->constraints
) {
3546 MonoClass
**target_class
;
3547 for (target_class
= tinfo
->constraints
; *target_class
; ++target_class
) {
3548 MonoClass
*tc
= *target_class
;
3549 MonoType
*tc_byval_arg
= m_class_get_byval_arg (tc
);
3552 * A constraint from @target might inflate into @candidate itself and in that case we don't need
3553 * check it's constraints since it satisfy the constraint by itself.
3555 if (mono_metadata_type_equal (tc_byval_arg
, candidate_byval_arg
))
3558 if (!cinfo
->constraints
)
3561 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3562 MonoClass
*cc
= *candidate_class
;
3564 if (mono_class_is_assignable_from_internal (tc
, cc
))
3568 * This happens when we have the following:
3570 * Bar<K> where K : IFace
3571 * Foo<T, U> where T : U where U : IFace
3573 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
3576 if (mono_type_is_generic_argument (m_class_get_byval_arg (cc
))) {
3577 if (mono_gparam_is_assignable_from (target
, cc
))
3581 if (!*candidate_class
)
3586 /*candidate itself must have a constraint that satisfy target*/
3587 if (cinfo
->constraints
) {
3588 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3589 MonoClass
*cc
= *candidate_class
;
3590 if (mono_class_is_assignable_from_internal (target
, cc
))
3598 * mono_class_is_assignable_from_internal:
3599 * \param klass the class to be assigned to
3600 * \param oklass the source class
3602 * \returns TRUE if an instance of class \p oklass can be assigned to an
3603 * instance of class \p klass
3606 mono_class_is_assignable_from_internal (MonoClass
*klass
, MonoClass
*oklass
)
3608 gboolean result
= FALSE
;
3610 mono_class_is_assignable_from_checked (klass
, oklass
, &result
, error
);
3611 mono_error_cleanup (error
);
3616 * mono_class_is_assignable_from:
3617 * \param klass the class to be assigned to
3618 * \param oklass the source class
3620 * \returns TRUE if an instance of class \p oklass can be assigned to an
3621 * instance of class \p klass
3624 mono_class_is_assignable_from (MonoClass
*klass
, MonoClass
*oklass
)
3627 MONO_ENTER_GC_UNSAFE
;
3628 result
= mono_class_is_assignable_from_internal (klass
, oklass
);
3629 MONO_EXIT_GC_UNSAFE
;
3634 * mono_class_is_assignable_from_checked:
3635 * \param klass the class to be assigned to
3636 * \param oklass the source class
3637 * \param result set if there was no error
3638 * \param error set if there was an error
3640 * Sets \p result to TRUE if an instance of class \p oklass can be assigned to
3641 * an instance of class \p klass or FALSE if it cannot. On error, no \p error
3642 * is set and \p result is not valid.
3645 mono_class_is_assignable_from_checked (MonoClass
*klass
, MonoClass
*oklass
, gboolean
*result
, MonoError
*error
)
3648 if (klass
== oklass
) {
3653 MONO_REQ_GC_UNSAFE_MODE
;
3654 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
3655 if (!m_class_is_inited (klass
))
3656 mono_class_init_internal (klass
);
3658 if (!m_class_is_inited (oklass
))
3659 mono_class_init_internal (oklass
);
3661 if (mono_class_has_failure (klass
)) {
3662 mono_error_set_for_class_failure (error
, klass
);
3667 if (mono_class_has_failure (oklass
)) {
3668 mono_error_set_for_class_failure (error
, oklass
);
3673 MonoType
*klass_byval_arg
= m_class_get_byval_arg (klass
);
3674 MonoType
*oklass_byval_arg
= m_class_get_byval_arg (oklass
);
3676 if (mono_type_is_generic_argument (klass_byval_arg
)) {
3677 if (!mono_type_is_generic_argument (oklass_byval_arg
)) {
3681 *result
= mono_gparam_is_assignable_from (klass
, oklass
);
3685 /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
3686 * has a constraint which is a class type:
3689 * class G<T1, T2> where T1 : T2 where T2 : Foo { }
3691 * In this case, Foo is assignable from T1.
3693 if (mono_type_is_generic_argument (oklass_byval_arg
)) {
3694 MonoGenericParam
*gparam
= oklass_byval_arg
->data
.generic_param
;
3695 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
3699 for (i
= 0; constraints
[i
]; ++i
) {
3700 if (mono_class_is_assignable_from_internal (klass
, constraints
[i
])) {
3707 *result
= mono_class_has_parent (oklass
, klass
);
3711 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3713 /* interface_offsets might not be set for dynamic classes */
3714 if (mono_class_get_ref_info_handle (oklass
) && !m_class_get_interface_bitmap (oklass
)) {
3716 * oklass might be a generic type parameter but they have
3717 * interface_offsets set.
3719 gboolean assign_result
= mono_reflection_call_is_assignable_to (oklass
, klass
, error
);
3720 return_if_nok (error
);
3721 *result
= assign_result
;
3724 if (!m_class_get_interface_bitmap (oklass
)) {
3725 /* Happens with generic instances of not-yet created dynamic types */
3729 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass
, m_class_get_interface_id (klass
))) {
3734 if (m_class_is_array_special_interface (klass
) && m_class_get_rank (oklass
) == 1) {
3735 if (mono_class_is_gtd (klass
)) {
3736 /* klass is an array special gtd like
3737 * IList`1<>, and oklass is X[] for some X.
3738 * Moreover we know that X isn't !0 (the gparam
3739 * of IList`1) because in that case we would
3740 * have returned TRUE for
3741 * MONO_CLASS_IMPLEMENTS_INTERFACE, above.
3746 // FIXME: IEnumerator`1 should not be an array special interface.
3747 // The correct fix is to make
3748 // ((IEnumerable<U>) (new T[] {...})).GetEnumerator()
3749 // return an IEnumerator<U> (like .NET does) instead of IEnumerator<T>
3750 // and to stop marking IEnumerable`1 as an array_special_interface.
3751 if (mono_class_get_generic_type_definition (klass
) == mono_defaults
.generic_ienumerator_class
) {
3756 //XXX we could offset this by having the cast target computed at JIT time
3757 //XXX we could go even further and emit a wrapper that would do the extra type check
3758 MonoClass
*iface_klass
= mono_class_from_mono_type_internal (mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0]);
3759 MonoClass
*obj_klass
= m_class_get_cast_class (oklass
); //This gets us the cast class of element type of the array
3761 // 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
3762 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
3763 if (!mono_class_is_nullable (iface_klass
)) {
3764 if (m_class_is_valuetype (iface_klass
))
3765 iface_klass
= m_class_get_cast_class (iface_klass
);
3767 //array covariant casts only operates on scalar to scalar
3768 //This is so int[] can't be casted to IComparable<int>[]
3769 if (!(m_class_is_valuetype (obj_klass
) && !m_class_is_valuetype (iface_klass
)) && mono_class_is_assignable_from_internal (iface_klass
, obj_klass
)) {
3776 if (mono_class_has_variant_generic_params (klass
)) {
3778 mono_class_setup_interfaces (oklass
, error
);
3779 return_if_nok (error
);
3781 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
3782 for (i
= 0; i
< m_class_get_interface_offsets_count (oklass
); ++i
) {
3783 MonoClass
*iface
= m_class_get_interfaces_packed (oklass
) [i
];
3785 if (mono_class_is_variant_compatible (klass
, iface
, FALSE
)) {
3794 } else if (m_class_is_delegate (klass
)) {
3795 if (mono_class_has_variant_generic_params (klass
) && mono_class_is_variant_compatible (klass
, oklass
, FALSE
)) {
3799 } else if (m_class_get_rank (klass
)) {
3800 MonoClass
*eclass
, *eoclass
;
3802 if (m_class_get_rank (oklass
) != m_class_get_rank (klass
)) {
3807 /* vectors vs. one dimensional arrays */
3808 if (oklass_byval_arg
->type
!= klass_byval_arg
->type
) {
3813 eclass
= m_class_get_cast_class (klass
);
3814 eoclass
= m_class_get_cast_class (oklass
);
3817 * a is b does not imply a[] is b[] when a is a valuetype, and
3818 * b is a reference type.
3821 if (m_class_is_valuetype (eoclass
)) {
3822 if ((eclass
== mono_defaults
.enum_class
) ||
3823 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
3824 (!m_class_is_valuetype (eclass
))) {
3831 * a is b does not imply a[] is b[] in the case where b is an interface and
3832 * a is a generic parameter, unless a has an additional class constraint.
3836 * class G<T> where T : I {}
3837 * class H<U> where U : class, I {}
3839 * public static void Main() {
3840 * var t = typeof(G<>).GetTypeInfo().GenericTypeParameters[0].MakeArrayType();
3841 * var i = typeof(I).MakeArrayType();
3842 * var u = typeof(H<>).GetTypeInfo().GenericTypeParameters[0].MakeArrayType();
3843 * Console.WriteLine("I[] assignable from T[] ? {0}", i.IsAssignableFrom(t));
3844 * Console.WriteLine("I[] assignable from U[] ? {0}", i.IsAssignableFrom(u));
3848 * This should print:
3849 * I[] assignable from T[] ? False
3850 * I[] assignable from U[] ? True
3853 if (MONO_CLASS_IS_INTERFACE_INTERNAL (eclass
)) {
3854 MonoType
*eoclass_byval_arg
= m_class_get_byval_arg (eoclass
);
3855 if (mono_type_is_generic_argument (eoclass_byval_arg
)) {
3856 MonoGenericParam
*eoparam
= eoclass_byval_arg
->data
.generic_param
;
3857 MonoGenericParamInfo
*eoinfo
= mono_generic_param_info (eoparam
);
3858 int eomask
= eoinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3859 // check for class constraint
3860 if ((eomask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0) {
3867 if (mono_class_is_nullable (eclass
) ^ mono_class_is_nullable (eoclass
)) {
3872 mono_class_is_assignable_from_checked (eclass
, eoclass
, result
, error
);
3874 } else if (mono_class_is_nullable (klass
)) {
3875 if (mono_class_is_nullable (oklass
))
3876 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), m_class_get_cast_class (oklass
), result
, error
);
3878 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), oklass
, result
, error
);
3880 } else if (klass
== mono_defaults
.object_class
) {
3881 if (m_class_get_class_kind (oklass
) == MONO_CLASS_POINTER
)
3888 *result
= mono_class_has_parent (oklass
, klass
);
3891 /*Check if @oklass is variant compatible with @klass.*/
3893 mono_class_is_variant_compatible_slow (MonoClass
*klass
, MonoClass
*oklass
)
3896 MonoType
**klass_argv
, **oklass_argv
;
3897 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3898 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3900 /*Viable candidates are instances of the same generic interface*/
3901 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3904 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3905 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3907 for (j
= 0; j
< container
->type_argc
; ++j
) {
3908 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3909 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3911 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
))
3915 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3916 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3918 if (param1_class
!= param2_class
) {
3919 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3920 if (!mono_class_is_assignable_from_slow (param1_class
, param2_class
))
3922 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3923 if (!mono_class_is_assignable_from_slow (param2_class
, param1_class
))
3931 /*Check if @candidate implements the interface @target*/
3933 mono_class_implement_interface_slow (MonoClass
*target
, MonoClass
*candidate
)
3937 gboolean is_variant
= mono_class_has_variant_generic_params (target
);
3939 if (is_variant
&& MONO_CLASS_IS_INTERFACE_INTERNAL (candidate
)) {
3940 if (mono_class_is_variant_compatible_slow (target
, candidate
))
3945 if (candidate
== target
)
3948 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
3949 if (image_is_dynamic (m_class_get_image (candidate
)) && !m_class_was_typebuilder (candidate
)) {
3950 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info_raw (candidate
); /* FIXME use handles */
3952 if (tb
&& tb
->interfaces
) {
3953 for (j
= mono_array_length_internal (tb
->interfaces
) - 1; j
>= 0; --j
) {
3954 MonoReflectionType
*iface
= mono_array_get_internal (tb
->interfaces
, MonoReflectionType
*, j
);
3955 MonoClass
*iface_class
;
3957 /* we can't realize the type here since it can do pretty much anything. */
3960 iface_class
= mono_class_from_mono_type_internal (iface
->type
);
3961 if (iface_class
== target
)
3963 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, iface_class
))
3965 if (mono_class_implement_interface_slow (target
, iface_class
))
3970 /*setup_interfaces don't mono_class_init_internal anything*/
3971 /*FIXME this doesn't handle primitive type arrays.
3972 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
3973 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
3975 mono_class_setup_interfaces (candidate
, error
);
3976 if (!is_ok (error
)) {
3977 mono_error_cleanup (error
);
3981 int candidate_interface_count
= m_class_get_interface_count (candidate
);
3982 MonoClass
**candidate_interfaces
= m_class_get_interfaces (candidate
);
3983 for (i
= 0; i
< candidate_interface_count
; ++i
) {
3984 if (candidate_interfaces
[i
] == target
)
3987 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, candidate_interfaces
[i
]))
3990 if (mono_class_implement_interface_slow (target
, candidate_interfaces
[i
]))
3994 candidate
= m_class_get_parent (candidate
);
3995 } while (candidate
);
4001 * Check if @oklass can be assigned to @klass.
4002 * This function does the same as mono_class_is_assignable_from_internal but is safe to be used from mono_class_init_internal context.
4005 mono_class_is_assignable_from_slow (MonoClass
*target
, MonoClass
*candidate
)
4007 if (candidate
== target
)
4009 if (target
== mono_defaults
.object_class
)
4012 if (mono_class_has_parent (candidate
, target
))
4015 /*If target is not an interface there is no need to check them.*/
4016 if (MONO_CLASS_IS_INTERFACE_INTERNAL (target
))
4017 return mono_class_implement_interface_slow (target
, candidate
);
4019 if (m_class_is_delegate (target
) && mono_class_has_variant_generic_params (target
))
4020 return mono_class_is_variant_compatible (target
, candidate
, FALSE
);
4022 if (m_class_get_rank (target
)) {
4023 MonoClass
*eclass
, *eoclass
;
4025 if (m_class_get_rank (target
) != m_class_get_rank (candidate
))
4028 /* vectors vs. one dimensional arrays */
4029 if (m_class_get_byval_arg (target
)->type
!= m_class_get_byval_arg (candidate
)->type
)
4032 eclass
= m_class_get_cast_class (target
);
4033 eoclass
= m_class_get_cast_class (candidate
);
4036 * a is b does not imply a[] is b[] when a is a valuetype, and
4037 * b is a reference type.
4040 if (m_class_is_valuetype (eoclass
)) {
4041 if ((eclass
== mono_defaults
.enum_class
) ||
4042 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
4043 (eclass
== mono_defaults
.object_class
))
4047 return mono_class_is_assignable_from_slow (eclass
, eoclass
);
4049 /*FIXME properly handle nullables */
4050 /*FIXME properly handle (M)VAR */
4055 * mono_generic_param_get_base_type:
4057 * Return the base type of the given generic parameter from its constraints.
4059 * Could be another generic parameter, or it could be Object or ValueType.
4062 mono_generic_param_get_base_type (MonoClass
*klass
)
4064 MonoType
*type
= m_class_get_byval_arg (klass
);
4065 g_assert (mono_type_is_generic_argument (type
));
4067 MonoGenericParam
*gparam
= type
->data
.generic_param
;
4069 g_assert (gparam
->owner
&& !gparam
->owner
->is_anonymous
);
4071 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
4073 MonoClass
*base_class
= mono_defaults
.object_class
;
4077 for (i
= 0; constraints
[i
]; ++i
) {
4078 MonoClass
*constraint
= constraints
[i
];
4080 if (MONO_CLASS_IS_INTERFACE_INTERNAL (constraint
))
4083 MonoType
*constraint_type
= m_class_get_byval_arg (constraint
);
4084 if (mono_type_is_generic_argument (constraint_type
)) {
4085 MonoGenericParam
*constraint_param
= constraint_type
->data
.generic_param
;
4086 MonoGenericParamInfo
*constraint_info
= mono_generic_param_info (constraint_param
);
4087 if ((constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0 &&
4088 (constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) == 0)
4092 base_class
= constraint
;
4097 if (base_class
== mono_defaults
.object_class
)
4099 MonoGenericParamInfo
*gparam_info
= mono_generic_param_info (gparam
);
4100 if ((gparam_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0) {
4101 base_class
= mono_class_get_valuetype_class ();
4109 * mono_class_get_cctor:
4110 * \param klass A MonoClass pointer
4112 * \returns The static constructor of \p klass if it exists, NULL otherwise.
4115 mono_class_get_cctor (MonoClass
*klass
)
4117 MonoMethod
*result
= NULL
;
4119 MonoCachedClassInfo cached_info
;
4121 if (image_is_dynamic (m_class_get_image (klass
))) {
4123 * has_cctor is not set for these classes because mono_class_init_internal () is
4126 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
4127 mono_error_assert_msg_ok (error
, "Could not lookup class cctor in dynamic image");
4131 mono_class_init_internal (klass
);
4133 if (!m_class_has_cctor (klass
))
4136 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
4137 result
= mono_class_get_inflated_method (klass
, mono_class_get_cctor (mono_class_get_generic_class (klass
)->container_class
), error
);
4138 mono_error_assert_msg_ok (error
, "Could not lookup inflated class cctor"); /* FIXME do proper error handling */
4142 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
4143 result
= mono_get_method_checked (m_class_get_image (klass
), cached_info
.cctor_token
, klass
, NULL
, error
);
4144 mono_error_assert_msg_ok (error
, "Could not lookup class cctor from cached metadata");
4148 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
4149 mono_error_assert_msg_ok (error
, "Could not lookup class cctor");
4154 * mono_class_get_finalizer:
4155 * \param klass: The MonoClass pointer
4157 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
4160 mono_class_get_finalizer (MonoClass
*klass
)
4162 MonoCachedClassInfo cached_info
;
4164 if (!m_class_is_inited (klass
))
4165 mono_class_init_internal (klass
);
4166 if (!mono_class_has_finalizer (klass
))
4169 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
4171 MonoMethod
*result
= mono_get_method_checked (cached_info
.finalize_image
, cached_info
.finalize_token
, NULL
, NULL
, error
);
4172 mono_error_assert_msg_ok (error
, "Could not lookup finalizer from cached metadata");
4175 mono_class_setup_vtable (klass
);
4176 return m_class_get_vtable (klass
) [mono_class_get_object_finalize_slot ()];
4181 * mono_class_needs_cctor_run:
4182 * \param klass the MonoClass pointer
4183 * \param caller a MonoMethod describing the caller
4185 * Determines whenever the class has a static constructor and whenever it
4186 * needs to be called when executing CALLER.
4189 mono_class_needs_cctor_run (MonoClass
*klass
, MonoMethod
*caller
)
4193 method
= mono_class_get_cctor (klass
);
4195 return (method
== caller
) ? FALSE
: TRUE
;
4201 * mono_class_array_element_size:
4204 * \returns The number of bytes an element of type \p klass uses when stored into an array.
4207 mono_class_array_element_size (MonoClass
*klass
)
4209 MonoType
*type
= m_class_get_byval_arg (klass
);
4212 switch (type
->type
) {
4215 case MONO_TYPE_BOOLEAN
:
4219 case MONO_TYPE_CHAR
:
4228 case MONO_TYPE_CLASS
:
4229 case MONO_TYPE_STRING
:
4230 case MONO_TYPE_OBJECT
:
4231 case MONO_TYPE_SZARRAY
:
4232 case MONO_TYPE_ARRAY
:
4233 return TARGET_SIZEOF_VOID_P
;
4238 case MONO_TYPE_VALUETYPE
:
4239 if (m_class_is_enumtype (type
->data
.klass
)) {
4240 type
= mono_class_enum_basetype_internal (type
->data
.klass
);
4241 klass
= m_class_get_element_class (klass
);
4244 return mono_class_value_size (klass
, NULL
);
4245 case MONO_TYPE_GENERICINST
:
4246 type
= m_class_get_byval_arg (type
->data
.generic_class
->container_class
);
4249 case MONO_TYPE_MVAR
: {
4252 return mono_type_size (type
, &align
);
4254 case MONO_TYPE_VOID
:
4258 g_error ("unknown type 0x%02x in mono_class_array_element_size", type
->type
);
4264 * mono_array_element_size:
4265 * \param ac pointer to a \c MonoArrayClass
4267 * \returns The size of single array element.
4269 * LOCKING: Acquires the loader lock.
4272 mono_array_element_size (MonoClass
*ac
)
4274 g_assert (m_class_get_rank (ac
));
4275 if (G_UNLIKELY (!m_class_is_size_inited (ac
))) {
4276 mono_class_setup_fields (ac
);
4278 return m_class_get_sizes (ac
).element_size
;
4285 mono_ldtoken (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4286 MonoGenericContext
*context
)
4289 gpointer res
= mono_ldtoken_checked (image
, token
, handle_class
, context
, error
);
4290 mono_error_assert_ok (error
);
4295 mono_ldtoken_checked (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4296 MonoGenericContext
*context
, MonoError
*error
)
4300 if (image_is_dynamic (image
)) {
4301 MonoClass
*tmp_handle_class
;
4302 gpointer obj
= mono_lookup_dynamic_token_class (image
, token
, TRUE
, &tmp_handle_class
, context
, error
);
4304 mono_error_assert_ok (error
);
4305 g_assert (tmp_handle_class
);
4307 *handle_class
= tmp_handle_class
;
4309 if (tmp_handle_class
== mono_defaults
.typehandle_class
)
4310 return m_class_get_byval_arg ((MonoClass
*)obj
);
4315 switch (token
& 0xff000000) {
4316 case MONO_TOKEN_TYPE_DEF
:
4317 case MONO_TOKEN_TYPE_REF
:
4318 case MONO_TOKEN_TYPE_SPEC
: {
4321 *handle_class
= mono_defaults
.typehandle_class
;
4322 type
= mono_type_get_checked (image
, token
, context
, error
);
4326 mono_class_init_internal (mono_class_from_mono_type_internal (type
));
4327 /* We return a MonoType* as handle */
4330 case MONO_TOKEN_FIELD_DEF
: {
4332 guint32 type
= mono_metadata_typedef_from_field (image
, mono_metadata_token_index (token
));
4334 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4338 *handle_class
= mono_defaults
.fieldhandle_class
;
4339 klass
= mono_class_get_and_inflate_typespec_checked (image
, MONO_TOKEN_TYPE_DEF
| type
, context
, error
);
4343 mono_class_init_internal (klass
);
4344 return mono_class_get_field (klass
, token
);
4346 case MONO_TOKEN_METHOD_DEF
:
4347 case MONO_TOKEN_METHOD_SPEC
: {
4349 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4351 *handle_class
= mono_defaults
.methodhandle_class
;
4357 case MONO_TOKEN_MEMBER_REF
: {
4358 guint32 cols
[MONO_MEMBERREF_SIZE
];
4360 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
4361 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
4362 mono_metadata_decode_blob_size (sig
, &sig
);
4363 if (*sig
== 0x6) { /* it's a field */
4365 MonoClassField
*field
;
4366 field
= mono_field_from_token_checked (image
, token
, &klass
, context
, error
);
4368 *handle_class
= mono_defaults
.fieldhandle_class
;
4372 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4374 *handle_class
= mono_defaults
.methodhandle_class
;
4379 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4385 mono_lookup_dynamic_token (MonoImage
*image
, guint32 token
, MonoGenericContext
*context
, MonoError
*error
)
4387 MonoClass
*handle_class
;
4389 return mono_reflection_lookup_dynamic_token (image
, token
, TRUE
, &handle_class
, context
, error
);
4393 mono_lookup_dynamic_token_class (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
, MonoError
*error
)
4395 return mono_reflection_lookup_dynamic_token (image
, token
, valid_token
, handle_class
, context
, error
);
4398 static MonoGetCachedClassInfo get_cached_class_info
= NULL
;
4401 mono_install_get_cached_class_info (MonoGetCachedClassInfo func
)
4403 get_cached_class_info
= func
;
4407 mono_class_get_cached_class_info (MonoClass
*klass
, MonoCachedClassInfo
*res
)
4409 if (!get_cached_class_info
)
4412 return get_cached_class_info (klass
, res
);
4416 mono_install_get_class_from_name (MonoGetClassFromName func
)
4418 get_class_from_name
= func
;
4422 * mono_class_get_image:
4424 * Use this method to get the \c MonoImage* where this class came from.
4426 * \returns The image where this class is defined.
4429 mono_class_get_image (MonoClass
*klass
)
4431 return m_class_get_image (klass
);
4435 * mono_class_get_element_class:
4436 * \param klass the \c MonoClass to act on
4438 * Use this function to get the element class of an array.
4440 * \returns The element class of an array.
4443 mono_class_get_element_class (MonoClass
*klass
)
4446 MONO_ENTER_GC_UNSAFE
;
4447 result
= m_class_get_element_class (klass
);
4448 MONO_EXIT_GC_UNSAFE
;
4453 * mono_class_is_valuetype:
4454 * \param klass the \c MonoClass to act on
4456 * Use this method to determine if the provided \c MonoClass* represents a value type,
4457 * or a reference type.
4459 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
4462 mono_class_is_valuetype (MonoClass
*klass
)
4465 MONO_ENTER_GC_UNSAFE
;
4466 result
= m_class_is_valuetype (klass
);
4467 MONO_EXIT_GC_UNSAFE
;
4472 * mono_class_is_enum:
4473 * \param klass the \c MonoClass to act on
4475 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
4477 * \returns TRUE if the \c MonoClass represents an enumeration.
4480 mono_class_is_enum (MonoClass
*klass
)
4483 MONO_ENTER_GC_UNSAFE
;
4484 result
= m_class_is_enumtype (klass
);
4485 MONO_EXIT_GC_UNSAFE
;
4490 * mono_class_enum_basetype_internal:
4491 * \param klass the \c MonoClass to act on
4493 * Use this function to get the underlying type for an enumeration value.
4495 * \returns The underlying type representation for an enumeration.
4498 mono_class_enum_basetype_internal (MonoClass
*klass
)
4500 if (m_class_get_element_class (klass
) == klass
)
4501 /* SRE or broken types */
4503 return m_class_get_byval_arg (m_class_get_element_class (klass
));
4507 * mono_class_enum_basetype:
4508 * \param klass the \c MonoClass to act on
4510 * Use this function to get the underlying type for an enumeration value.
4512 * \returns The underlying type representation for an enumeration.
4515 mono_class_enum_basetype (MonoClass
*klass
)
4518 MONO_ENTER_GC_UNSAFE
;
4519 res
= mono_class_enum_basetype_internal (klass
);
4520 MONO_EXIT_GC_UNSAFE
;
4525 * mono_class_get_parent
4526 * \param klass the \c MonoClass to act on
4528 * \returns The parent class for this class.
4531 mono_class_get_parent (MonoClass
*klass
)
4534 MONO_ENTER_GC_UNSAFE
;
4535 result
= m_class_get_parent (klass
);
4536 MONO_EXIT_GC_UNSAFE
;
4541 * mono_class_get_nesting_type:
4542 * \param klass the \c MonoClass to act on
4544 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
4546 * If the return is NULL, this indicates that this class is not nested.
4548 * \returns The container type where this type is nested or NULL if this type is not a nested type.
4551 mono_class_get_nesting_type (MonoClass
*klass
)
4553 return m_class_get_nested_in (klass
);
4557 * mono_class_get_rank:
4558 * \param klass the MonoClass to act on
4560 * \returns The rank for the array (the number of dimensions).
4563 mono_class_get_rank (MonoClass
*klass
)
4565 return m_class_get_rank (klass
);
4569 * mono_class_get_name
4570 * \param klass the \c MonoClass to act on
4572 * \returns The name of the class.
4575 mono_class_get_name (MonoClass
*klass
)
4578 MONO_ENTER_GC_UNSAFE
;
4579 result
= m_class_get_name (klass
);
4580 MONO_EXIT_GC_UNSAFE
;
4585 * mono_class_get_namespace:
4586 * \param klass the \c MonoClass to act on
4588 * \returns The namespace of the class.
4591 mono_class_get_namespace (MonoClass
*klass
)
4594 MONO_ENTER_GC_UNSAFE
;
4595 result
= m_class_get_name_space (klass
);
4596 MONO_EXIT_GC_UNSAFE
;
4601 * mono_class_get_type:
4602 * \param klass the \c MonoClass to act on
4604 * This method returns the internal \c MonoType representation for the class.
4606 * \returns The \c MonoType from the class.
4609 mono_class_get_type (MonoClass
*klass
)
4611 return m_class_get_byval_arg (klass
);
4615 * mono_class_get_type_token:
4616 * \param klass the \c MonoClass to act on
4618 * This method returns type token for the class.
4620 * \returns The type token for the class.
4623 mono_class_get_type_token (MonoClass
*klass
)
4625 return m_class_get_type_token (klass
);
4629 * mono_class_get_byref_type:
4630 * \param klass the \c MonoClass to act on
4635 mono_class_get_byref_type (MonoClass
*klass
)
4637 return m_class_get_this_arg (klass
);
4641 * mono_class_num_fields:
4642 * \param klass the \c MonoClass to act on
4644 * \returns The number of static and instance fields in the class.
4647 mono_class_num_fields (MonoClass
*klass
)
4649 return mono_class_get_field_count (klass
);
4653 * mono_class_num_methods:
4654 * \param klass the \c MonoClass to act on
4656 * \returns The number of methods in the class.
4659 mono_class_num_methods (MonoClass
*klass
)
4661 return mono_class_get_method_count (klass
);
4665 * mono_class_num_properties
4666 * \param klass the \c MonoClass to act on
4668 * \returns The number of properties in the class.
4671 mono_class_num_properties (MonoClass
*klass
)
4673 mono_class_setup_properties (klass
);
4675 return mono_class_get_property_info (klass
)->count
;
4679 * mono_class_num_events:
4680 * \param klass the \c MonoClass to act on
4682 * \returns The number of events in the class.
4685 mono_class_num_events (MonoClass
*klass
)
4687 mono_class_setup_events (klass
);
4689 return mono_class_get_event_info (klass
)->count
;
4693 * mono_class_get_fields:
4694 * \param klass the \c MonoClass to act on
4696 * This routine is an iterator routine for retrieving the fields in a class.
4698 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4699 * iterate over all of the elements. When no more values are
4700 * available, the return value is NULL.
4702 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
4705 mono_class_get_fields (MonoClass
* klass
, gpointer
*iter
)
4707 MonoClassField
*result
;
4708 MONO_ENTER_GC_UNSAFE
;
4709 result
= mono_class_get_fields_internal (klass
, iter
);
4710 MONO_EXIT_GC_UNSAFE
;
4715 mono_class_get_fields_internal (MonoClass
*klass
, gpointer
*iter
)
4717 MonoClassField
* field
;
4721 mono_class_setup_fields (klass
);
4722 if (mono_class_has_failure (klass
))
4724 /* start from the first */
4725 if (mono_class_get_field_count (klass
)) {
4726 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
4727 *iter
= &klass_fields
[0];
4728 return &klass_fields
[0];
4734 field
= (MonoClassField
*)*iter
;
4736 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
4744 * mono_class_get_methods:
4745 * \param klass the \c MonoClass to act on
4747 * This routine is an iterator routine for retrieving the fields in a class.
4749 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4750 * iterate over all of the elements. When no more values are
4751 * available, the return value is NULL.
4753 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
4756 mono_class_get_methods (MonoClass
* klass
, gpointer
*iter
)
4758 MonoMethod
** method
;
4762 mono_class_setup_methods (klass
);
4764 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
4766 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
4767 * FIXME we should better report this error to the caller
4771 /* start from the first */
4772 if (mono_class_get_method_count (klass
)) {
4773 *iter
= &klass_methods
[0];
4774 return klass_methods
[0];
4780 method
= (MonoMethod
**)*iter
;
4782 if (method
< &m_class_get_methods (klass
) [mono_class_get_method_count (klass
)]) {
4790 * mono_class_get_properties:
4791 * \param klass the \c MonoClass to act on
4793 * This routine is an iterator routine for retrieving the properties in a class.
4795 * You must pass a gpointer that points to zero and is treated as an opaque handle to
4796 * iterate over all of the elements. When no more values are
4797 * available, the return value is NULL.
4799 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
4802 mono_class_get_properties (MonoClass
* klass
, gpointer
*iter
)
4804 MonoProperty
* property
;
4808 mono_class_setup_properties (klass
);
4809 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4810 /* start from the first */
4812 *iter
= &info
->properties
[0];
4813 return (MonoProperty
*)*iter
;
4819 property
= (MonoProperty
*)*iter
;
4821 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4822 if (property
< &info
->properties
[info
->count
]) {
4824 return (MonoProperty
*)*iter
;
4830 * mono_class_get_events:
4831 * \param klass the \c MonoClass to act on
4833 * This routine is an iterator routine for retrieving the properties in a class.
4835 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4836 * iterate over all of the elements. When no more values are
4837 * available, the return value is NULL.
4839 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
4842 mono_class_get_events (MonoClass
* klass
, gpointer
*iter
)
4848 mono_class_setup_events (klass
);
4849 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4850 /* start from the first */
4852 *iter
= &info
->events
[0];
4853 return (MonoEvent
*)*iter
;
4859 event
= (MonoEvent
*)*iter
;
4861 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4862 if (event
< &info
->events
[info
->count
]) {
4864 return (MonoEvent
*)*iter
;
4870 * mono_class_get_interfaces
4871 * \param klass the \c MonoClass to act on
4873 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
4875 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4876 * iterate over all of the elements. When no more values are
4877 * available, the return value is NULL.
4879 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
4882 mono_class_get_interfaces (MonoClass
* klass
, gpointer
*iter
)
4889 if (!m_class_is_inited (klass
))
4890 mono_class_init_internal (klass
);
4891 if (!m_class_is_interfaces_inited (klass
)) {
4892 mono_class_setup_interfaces (klass
, error
);
4893 if (!is_ok (error
)) {
4894 mono_error_cleanup (error
);
4898 /* start from the first */
4899 if (m_class_get_interface_count (klass
)) {
4900 *iter
= &m_class_get_interfaces (klass
) [0];
4901 return m_class_get_interfaces (klass
) [0];
4907 iface
= (MonoClass
**)*iter
;
4909 if (iface
< &m_class_get_interfaces (klass
) [m_class_get_interface_count (klass
)]) {
4917 * mono_class_get_nested_types
4918 * \param klass the \c MonoClass to act on
4920 * This routine is an iterator routine for retrieving the nested types of a class.
4921 * This works only if \p klass is non-generic, or a generic type definition.
4923 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4924 * iterate over all of the elements. When no more values are
4925 * available, the return value is NULL.
4927 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
4930 mono_class_get_nested_types (MonoClass
* klass
, gpointer
*iter
)
4936 if (!m_class_is_nested_classes_inited (klass
))
4937 mono_class_setup_nested_types (klass
);
4940 GList
*nested_classes
= mono_class_get_nested_classes_property (klass
);
4941 /* start from the first */
4942 if (nested_classes
) {
4943 *iter
= nested_classes
;
4944 return (MonoClass
*)nested_classes
->data
;
4946 /* no nested types */
4950 item
= (GList
*)*iter
;
4954 return (MonoClass
*)item
->data
;
4961 * mono_class_is_delegate
4962 * \param klass the \c MonoClass to act on
4964 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
4967 mono_class_is_delegate (MonoClass
*klass
)
4970 MONO_ENTER_GC_UNSAFE
;
4971 result
= m_class_is_delegate (klass
);
4972 MONO_EXIT_GC_UNSAFE
;
4977 * mono_class_implements_interface
4978 * \param klass The MonoClass to act on
4979 * \param interface The interface to check if \p klass implements.
4981 * \returns TRUE if \p klass implements \p interface.
4984 mono_class_implements_interface (MonoClass
* klass
, MonoClass
* iface
)
4986 return mono_class_is_assignable_from_internal (iface
, klass
);
4990 class_implements_interface_ignore_generics (MonoClass
* klass
, MonoClass
* iface
)
4994 if (mono_class_is_ginst (iface
))
4995 iface
= mono_class_get_generic_type_definition (iface
);
4996 while (klass
!= NULL
) {
4997 if (mono_class_is_assignable_from_internal (iface
, klass
))
4999 mono_class_setup_interfaces (klass
, error
);
5000 if (!is_ok (error
)) {
5001 mono_error_cleanup (error
);
5004 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
5005 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
5006 MonoClass
*ic
= klass_interfaces
[i
];
5007 if (mono_class_is_ginst (ic
))
5008 ic
= mono_class_get_generic_type_definition (ic
);
5013 klass
= m_class_get_parent (klass
);
5020 * mono_field_get_name:
5021 * \param field the \c MonoClassField to act on
5023 * \returns The name of the field.
5026 mono_field_get_name (MonoClassField
*field
)
5032 * mono_field_get_type_internal:
5033 * \param field the \c MonoClassField to act on
5034 * \returns \c MonoType of the field.
5037 mono_field_get_type_internal (MonoClassField
*field
)
5039 MonoType
*type
= field
->type
;
5044 type
= mono_field_get_type_checked (field
, error
);
5045 if (!is_ok (error
)) {
5046 mono_trace_warning (MONO_TRACE_TYPE
, "Could not load field's type due to %s", mono_error_get_message (error
));
5047 mono_error_cleanup (error
);
5053 * mono_field_get_type:
5054 * \param field the \c MonoClassField to act on
5055 * \returns \c MonoType of the field.
5058 mono_field_get_type (MonoClassField
*field
)
5060 MonoType
*type
= field
->type
;
5064 MONO_ENTER_GC_UNSAFE
;
5065 type
= mono_field_get_type_internal (field
);
5066 MONO_EXIT_GC_UNSAFE
;
5071 * mono_field_get_type_checked:
5072 * \param field the \c MonoClassField to act on
5073 * \param error used to return any error found while retrieving \p field type
5075 * \returns \c MonoType of the field.
5078 mono_field_get_type_checked (MonoClassField
*field
, MonoError
*error
)
5081 MonoType
*type
= field
->type
;
5084 mono_field_resolve_type (field
, error
);
5089 * mono_field_get_parent:
5090 * \param field the \c MonoClassField to act on
5092 * \returns \c MonoClass where the field was defined.
5095 mono_field_get_parent (MonoClassField
*field
)
5097 return field
->parent
;
5101 * mono_field_get_flags;
5102 * \param field the \c MonoClassField to act on
5104 * The metadata flags for a field are encoded using the
5105 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5107 * \returns The flags for the field.
5110 mono_field_get_flags (MonoClassField
*field
)
5113 return mono_field_resolve_flags (field
);
5114 return field
->type
->attrs
;
5118 * mono_field_get_offset:
5119 * \param field the \c MonoClassField to act on
5121 * \returns The field offset.
5124 mono_field_get_offset (MonoClassField
*field
)
5126 mono_class_setup_fields(field
->parent
);
5127 return field
->offset
;
5131 mono_field_get_rva (MonoClassField
*field
)
5135 MonoClass
*klass
= field
->parent
;
5136 MonoFieldDefaultValue
*def_values
;
5138 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
);
5140 def_values
= mono_class_get_field_def_values (klass
);
5142 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
5144 mono_class_set_field_def_values (klass
, def_values
);
5147 field_index
= mono_field_get_index (field
);
5149 if (!def_values
[field_index
].data
&& !image_is_dynamic (m_class_get_image (klass
))) {
5150 int first_field_idx
= mono_class_get_first_field_idx (klass
);
5151 mono_metadata_field_info (m_class_get_image (field
->parent
), first_field_idx
+ field_index
, NULL
, &rva
, NULL
);
5153 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field
), m_class_get_name (field
->parent
));
5154 def_values
[field_index
].data
= mono_image_rva_map (m_class_get_image (field
->parent
), rva
);
5157 return def_values
[field_index
].data
;
5161 * mono_field_get_data:
5162 * \param field the \c MonoClassField to act on
5164 * \returns A pointer to the metadata constant value or to the field
5165 * data if it has an RVA flag.
5168 mono_field_get_data (MonoClassField
*field
)
5170 if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
) {
5171 MonoTypeEnum def_type
;
5173 return mono_class_get_field_default_value (field
, &def_type
);
5174 } else if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
5175 return mono_field_get_rva (field
);
5182 * mono_property_get_name:
5183 * \param prop the \c MonoProperty to act on
5184 * \returns The name of the property
5187 mono_property_get_name (MonoProperty
*prop
)
5193 * mono_property_get_set_method
5194 * \param prop the \c MonoProperty to act on.
5195 * \returns The setter method of the property, a \c MonoMethod.
5198 mono_property_get_set_method (MonoProperty
*prop
)
5204 * mono_property_get_get_method
5205 * \param prop the MonoProperty to act on.
5206 * \returns The getter method of the property (A \c MonoMethod)
5209 mono_property_get_get_method (MonoProperty
*prop
)
5215 * mono_property_get_parent:
5216 * \param prop the \c MonoProperty to act on.
5217 * \returns The \c MonoClass where the property was defined.
5220 mono_property_get_parent (MonoProperty
*prop
)
5222 return prop
->parent
;
5226 * mono_property_get_flags:
5227 * \param prop the \c MonoProperty to act on.
5229 * The metadata flags for a property are encoded using the
5230 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5232 * \returns The flags for the property.
5235 mono_property_get_flags (MonoProperty
*prop
)
5241 * mono_event_get_name:
5242 * \param event the MonoEvent to act on
5243 * \returns The name of the event.
5246 mono_event_get_name (MonoEvent
*event
)
5252 * mono_event_get_add_method:
5253 * \param event The \c MonoEvent to act on.
5254 * \returns The \c add method for the event, a \c MonoMethod.
5257 mono_event_get_add_method (MonoEvent
*event
)
5263 * mono_event_get_remove_method:
5264 * \param event The \c MonoEvent to act on.
5265 * \returns The \c remove method for the event, a \c MonoMethod.
5268 mono_event_get_remove_method (MonoEvent
*event
)
5270 return event
->remove
;
5274 * mono_event_get_raise_method:
5275 * \param event The \c MonoEvent to act on.
5276 * \returns The \c raise method for the event, a \c MonoMethod.
5279 mono_event_get_raise_method (MonoEvent
*event
)
5281 return event
->raise
;
5285 * mono_event_get_parent:
5286 * \param event the MonoEvent to act on.
5287 * \returns The \c MonoClass where the event is defined.
5290 mono_event_get_parent (MonoEvent
*event
)
5292 return event
->parent
;
5296 * mono_event_get_flags
5297 * \param event the \c MonoEvent to act on.
5299 * The metadata flags for an event are encoded using the
5300 * \c EVENT_* constants. See the \c tabledefs.h file for details.
5302 * \returns The flags for the event.
5305 mono_event_get_flags (MonoEvent
*event
)
5307 return event
->attrs
;
5311 * mono_class_get_method_from_name:
5312 * \param klass where to look for the method
5313 * \param name name of the method
5314 * \param param_count number of parameters. -1 for any number.
5316 * Obtains a \c MonoMethod with a given name and number of parameters.
5317 * It only works if there are no multiple signatures for any given method name.
5320 mono_class_get_method_from_name (MonoClass
*klass
, const char *name
, int param_count
)
5323 MONO_ENTER_GC_UNSAFE
;
5325 result
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, 0, error
);
5326 mono_error_cleanup (error
);
5327 MONO_EXIT_GC_UNSAFE
;
5332 mono_find_method_in_metadata (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5334 MonoImage
*klass_image
= m_class_get_image (klass
);
5335 MonoMethod
*res
= NULL
;
5338 /* Search directly in the metadata to avoid calling setup_methods () */
5339 int first_idx
= mono_class_get_first_method_idx (klass
);
5340 int mcount
= mono_class_get_method_count (klass
);
5341 for (i
= 0; i
< mcount
; ++i
) {
5343 guint32 cols
[MONO_METHOD_SIZE
];
5345 MonoMethodSignature
*sig
;
5347 /* first_idx points into the methodptr table */
5348 mono_metadata_decode_table_row (klass_image
, MONO_TABLE_METHOD
, first_idx
+ i
, cols
, MONO_METHOD_SIZE
);
5350 if (!strcmp (mono_metadata_string_heap (klass_image
, cols
[MONO_METHOD_NAME
]), name
)) {
5351 method
= mono_get_method_checked (klass_image
, MONO_TOKEN_METHOD_DEF
| (first_idx
+ i
+ 1), klass
, NULL
, error
);
5353 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5356 if (param_count
== -1) {
5360 sig
= mono_method_signature_checked (method
, error
);
5362 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5365 if (sig
->param_count
== param_count
) {
5376 * mono_class_get_method_from_name_flags:
5377 * \param klass where to look for the method
5378 * \param name_space name of the method
5379 * \param param_count number of parameters. -1 for any number.
5380 * \param flags flags which must be set in the method
5382 * Obtains a \c MonoMethod with a given name and number of parameters.
5383 * It only works if there are no multiple signatures for any given method name.
5386 mono_class_get_method_from_name_flags (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5389 MONO_ENTER_GC_UNSAFE
;
5391 method
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, flags
, error
);
5392 mono_error_cleanup (error
);
5393 MONO_EXIT_GC_UNSAFE
;
5398 * mono_class_get_method_from_name_checked:
5399 * \param klass where to look for the method
5400 * \param name_space name of the method
5401 * \param param_count number of parameters. -1 for any number.
5402 * \param flags flags which must be set in the method
5405 * Obtains a \c MonoMethod with a given name and number of parameters.
5406 * It only works if there are no multiple signatures for any given method name.
5409 mono_class_get_method_from_name_checked (MonoClass
*klass
, const char *name
,
5410 int param_count
, int flags
, MonoError
*error
)
5412 MonoMethod
*res
= NULL
;
5415 mono_class_init_internal (klass
);
5417 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
5418 res
= mono_class_get_method_from_name_checked (mono_class_get_generic_class (klass
)->container_class
, name
, param_count
, flags
, error
);
5421 res
= mono_class_inflate_generic_method_full_checked (res
, klass
, mono_class_get_context (klass
), error
);
5426 if (m_class_get_methods (klass
) || !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
5427 mono_class_setup_methods (klass
);
5429 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
5430 See mono/tests/array_load_exception.il
5431 FIXME we should better report this error to the caller
5433 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
5436 int mcount
= mono_class_get_method_count (klass
);
5437 for (i
= 0; i
< mcount
; ++i
) {
5438 MonoMethod
*method
= klass_methods
[i
];
5440 if (method
->name
[0] == name
[0] &&
5441 !strcmp (name
, method
->name
) &&
5442 (param_count
== -1 || mono_method_signature_internal (method
)->param_count
== param_count
) &&
5443 ((method
->flags
& flags
) == flags
)) {
5450 res
= mono_find_method_in_metadata (klass
, name
, param_count
, flags
);
5457 mono_class_has_failure (const MonoClass
*klass
)
5459 g_assert (klass
!= NULL
);
5460 return m_class_has_failure ((MonoClass
*)klass
) != 0;
5465 * mono_class_set_type_load_failure:
5466 * \param klass class in which the failure was detected
5467 * \param fmt \c printf -style error message string.
5469 * Collect detected failure informaion in the class for later processing.
5470 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
5471 * Note that only the first failure is kept.
5473 * LOCKING: Acquires the loader lock.
5475 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
5478 mono_class_set_type_load_failure (MonoClass
*klass
, const char * fmt
, ...)
5480 ERROR_DECL (prepare_error
);
5483 if (mono_class_has_failure (klass
))
5486 va_start (args
, fmt
);
5487 mono_error_vset_type_load_class (prepare_error
, klass
, fmt
, args
);
5490 MonoErrorBoxed
*box
= mono_error_box (prepare_error
, m_class_get_image (klass
));
5491 mono_error_cleanup (prepare_error
);
5492 return mono_class_set_failure (klass
, box
);
5496 * mono_class_get_exception_for_failure:
5497 * \param klass class in which the failure was detected
5499 * \returns a constructed MonoException than the caller can then throw
5500 * using mono_raise_exception - or NULL if no failure is present (or
5501 * doesn't result in an exception).
5504 mono_class_get_exception_for_failure (MonoClass
*klass
)
5506 if (!mono_class_has_failure (klass
))
5508 ERROR_DECL (unboxed_error
);
5509 mono_error_set_for_class_failure (unboxed_error
, klass
);
5510 return mono_error_convert_to_exception (unboxed_error
);
5514 is_nesting_type (MonoClass
*outer_klass
, MonoClass
*inner_klass
)
5516 outer_klass
= mono_class_get_generic_type_definition (outer_klass
);
5517 inner_klass
= mono_class_get_generic_type_definition (inner_klass
);
5519 if (outer_klass
== inner_klass
)
5521 inner_klass
= m_class_get_nested_in (inner_klass
);
5522 } while (inner_klass
);
5527 mono_class_get_generic_type_definition (MonoClass
*klass
)
5529 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5530 return gklass
? gklass
->container_class
: klass
;
5534 * Check if @klass is a subtype of @parent ignoring generic instantiations.
5536 * Generic instantiations are ignored for all super types of @klass.
5538 * Visibility checks ignoring generic instantiations.
5540 * Class implementing interface visibility checks ignore generic instantiations
5543 mono_class_has_parent_and_ignore_generics (MonoClass
*klass
, MonoClass
*parent
)
5546 klass
= mono_class_get_generic_type_definition (klass
);
5547 parent
= mono_class_get_generic_type_definition (parent
);
5548 mono_class_setup_supertypes (klass
);
5550 for (i
= 0; i
< m_class_get_idepth (klass
); ++i
) {
5551 if (parent
== mono_class_get_generic_type_definition (m_class_get_supertypes (klass
) [i
]))
5555 if (MONO_CLASS_IS_INTERFACE_INTERNAL (parent
) && class_implements_interface_ignore_generics (klass
, parent
))
5561 * Subtype can only access parent members with family protection if the site object
5562 * is subclass of Subtype. For example:
5563 * class A { protected int x; }
5565 * void valid_access () {
5569 * void invalid_access () {
5576 is_valid_family_access (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
*context_klass
)
5578 if (MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5579 /* Can happen with default interface methods */
5580 if (!class_implements_interface_ignore_generics (access_klass
, member_klass
))
5582 } else if (member_klass
!= access_klass
&& MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5583 /* Can happen with default interface methods */
5584 if (!mono_interface_implements_interface (access_klass
, member_klass
))
5587 if (!mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
))
5591 if (context_klass
== NULL
)
5593 /*if access_klass is not member_klass context_klass must be type compat*/
5594 if (access_klass
!= member_klass
&& !mono_class_has_parent_and_ignore_generics (context_klass
, access_klass
))
5600 can_access_internals (MonoAssembly
*accessing
, MonoAssembly
* accessed
)
5603 if (accessing
== accessed
)
5605 if (!accessed
|| !accessing
)
5608 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
5609 * anywhere so untrusted friends are not safe to access platform's code internals */
5610 if (mono_security_core_clr_enabled ()) {
5611 if (!mono_security_core_clr_can_access_internals (accessing
->image
, accessed
->image
))
5615 mono_assembly_load_friends (accessed
);
5616 for (tmp
= accessed
->friend_assembly_names
; tmp
; tmp
= tmp
->next
) {
5617 MonoAssemblyName
*friend_
= (MonoAssemblyName
*)tmp
->data
;
5618 /* Be conservative with checks */
5621 if (g_ascii_strcasecmp (accessing
->aname
.name
, friend_
->name
))
5623 if (friend_
->public_key_token
[0]) {
5624 if (!accessing
->aname
.public_key_token
[0])
5626 if (!mono_public_tokens_are_equal (friend_
->public_key_token
, accessing
->aname
.public_key_token
))
5635 * If klass is a generic type or if it is derived from a generic type, return the
5636 * MonoClass of the generic definition
5637 * Returns NULL if not found
5640 get_generic_definition_class (MonoClass
*klass
)
5643 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5644 if (gklass
&& gklass
->container_class
)
5645 return gklass
->container_class
;
5646 klass
= m_class_get_parent (klass
);
5652 can_access_instantiation (MonoClass
*access_klass
, MonoGenericInst
*ginst
)
5655 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
5656 MonoType
*type
= ginst
->type_argv
[i
];
5657 switch (type
->type
) {
5658 case MONO_TYPE_SZARRAY
:
5659 if (!can_access_type (access_klass
, type
->data
.klass
))
5662 case MONO_TYPE_ARRAY
:
5663 if (!can_access_type (access_klass
, type
->data
.array
->eklass
))
5667 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
->data
.type
)))
5670 case MONO_TYPE_CLASS
:
5671 case MONO_TYPE_VALUETYPE
:
5672 case MONO_TYPE_GENERICINST
:
5673 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
)))
5683 can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
)
5687 if (access_klass
== member_klass
)
5690 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5691 MonoAssembly
*member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5693 if (access_klass_assembly
&& m_class_get_image (access_klass
)->assembly
->corlib_internal
)
5696 if (m_class_get_element_class (access_klass
) && !m_class_is_enumtype (access_klass
)) {
5697 access_klass
= m_class_get_element_class (access_klass
);
5698 access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5701 if (m_class_get_element_class (member_klass
) && !m_class_is_enumtype (member_klass
)) {
5702 member_klass
= m_class_get_element_class (member_klass
);
5703 member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5706 access_level
= mono_class_get_flags (member_klass
) & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5708 if (mono_type_is_generic_argument (m_class_get_byval_arg (member_klass
)))
5711 if (mono_class_is_ginst (member_klass
) && !can_access_instantiation (access_klass
, mono_class_get_generic_class (member_klass
)->context
.class_inst
))
5714 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
)))
5717 /*Non nested type with nested visibility. We just fail it.*/
5718 if (access_level
>= TYPE_ATTRIBUTE_NESTED_PRIVATE
&& access_level
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
&& m_class_get_nested_in (member_klass
) == NULL
)
5721 MonoClass
*member_klass_nested_in
= m_class_get_nested_in (member_klass
);
5722 switch (access_level
) {
5723 case TYPE_ATTRIBUTE_NOT_PUBLIC
:
5724 return can_access_internals (access_klass_assembly
, member_klass_assembly
);
5726 case TYPE_ATTRIBUTE_PUBLIC
:
5729 case TYPE_ATTRIBUTE_NESTED_PUBLIC
:
5730 return member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5732 case TYPE_ATTRIBUTE_NESTED_PRIVATE
:
5733 return is_nesting_type (member_klass
, access_klass
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5735 case TYPE_ATTRIBUTE_NESTED_FAMILY
:
5736 return mono_class_has_parent_and_ignore_generics (access_klass
, m_class_get_nested_in (member_klass
));
5738 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY
:
5739 return can_access_internals (access_klass_assembly
, member_klass_assembly
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5741 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM
:
5742 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) &&
5743 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5745 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
:
5746 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) ||
5747 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5752 /* FIXME: check visibility of type, too */
5754 can_access_member (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
* context_klass
, int access_level
)
5756 MonoClass
*member_generic_def
;
5757 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5758 if (access_klass_assembly
&& access_klass_assembly
->corlib_internal
)
5761 MonoGenericClass
*access_gklass
= mono_class_try_get_generic_class (access_klass
);
5762 if (((access_gklass
&& access_gklass
->container_class
) ||
5763 mono_class_is_gtd (access_klass
)) &&
5764 (member_generic_def
= get_generic_definition_class (member_klass
))) {
5765 MonoClass
*access_container
;
5767 if (mono_class_is_gtd (access_klass
))
5768 access_container
= access_klass
;
5770 access_container
= access_gklass
->container_class
;
5772 if (can_access_member (access_container
, member_generic_def
, context_klass
, access_level
))
5776 MonoImage
*member_klass_image
= m_class_get_image (member_klass
);
5777 /* Partition I 8.5.3.2 */
5778 /* the access level values are the same for fields and methods */
5779 switch (access_level
) {
5780 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED
:
5781 /* same compilation unit */
5782 return m_class_get_image (access_klass
) == member_klass_image
;
5783 case FIELD_ATTRIBUTE_PRIVATE
:
5784 return access_klass
== member_klass
;
5785 case FIELD_ATTRIBUTE_FAM_AND_ASSEM
:
5786 if (is_valid_family_access (access_klass
, member_klass
, context_klass
) &&
5787 can_access_internals (access_klass_assembly
, member_klass_image
->assembly
))
5790 case FIELD_ATTRIBUTE_ASSEMBLY
:
5791 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5792 case FIELD_ATTRIBUTE_FAMILY
:
5793 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5796 case FIELD_ATTRIBUTE_FAM_OR_ASSEM
:
5797 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5799 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5800 case FIELD_ATTRIBUTE_PUBLIC
:
5807 * mono_method_can_access_field:
5808 * \param method Method that will attempt to access the field
5809 * \param field the field to access
5811 * Used to determine if a method is allowed to access the specified field.
5813 * \returns TRUE if the given \p method is allowed to access the \p field while following
5814 * the accessibility rules of the CLI.
5817 mono_method_can_access_field (MonoMethod
*method
, MonoClassField
*field
)
5819 /* FIXME: check all overlapping fields */
5820 int can
= can_access_member (method
->klass
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5822 MonoClass
*nested
= m_class_get_nested_in (method
->klass
);
5824 can
= can_access_member (nested
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5827 nested
= m_class_get_nested_in (nested
);
5834 mono_method_get_method_definition (MonoMethod
*method
)
5836 while (method
->is_inflated
)
5837 method
= ((MonoMethodInflated
*)method
)->declaring
;
5842 * mono_method_can_access_method:
5843 * \param method Method that will attempt to access the other method
5844 * \param called the method that we want to probe for accessibility.
5846 * Used to determine if the \p method is allowed to access the specified \p called method.
5848 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
5849 * the accessibility rules of the CLI.
5852 mono_method_can_access_method (MonoMethod
*method
, MonoMethod
*called
)
5854 method
= mono_method_get_method_definition (method
);
5855 called
= mono_method_get_method_definition (called
);
5856 return mono_method_can_access_method_full (method
, called
, NULL
);
5860 * mono_method_can_access_method_full:
5861 * @method: The caller method
5862 * @called: The called method
5863 * @context_klass: The static type on stack of the owner @called object used
5865 * This function must be used with instance calls, as they have more strict family accessibility.
5866 * It can be used with static methods, but context_klass should be NULL.
5868 * Returns: TRUE if caller have proper visibility and acessibility to @called
5871 mono_method_can_access_method_full (MonoMethod
*method
, MonoMethod
*called
, MonoClass
*context_klass
)
5873 /* Wrappers are except from access checks */
5874 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| called
->wrapper_type
!= MONO_WRAPPER_NONE
)
5877 MonoClass
*access_class
= method
->klass
;
5878 MonoClass
*member_class
= called
->klass
;
5879 int can
= can_access_member (access_class
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5881 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5883 can
= can_access_member (nested
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5886 nested
= m_class_get_nested_in (nested
);
5893 can
= can_access_type (access_class
, member_class
);
5895 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5897 can
= can_access_type (nested
, member_class
);
5900 nested
= m_class_get_nested_in (nested
);
5907 if (called
->is_inflated
) {
5908 MonoMethodInflated
* infl
= (MonoMethodInflated
*)called
;
5909 if (infl
->context
.method_inst
&& !can_access_instantiation (access_class
, infl
->context
.method_inst
))
5918 * mono_method_can_access_field_full:
5919 * @method: The caller method
5920 * @field: The accessed field
5921 * @context_klass: The static type on stack of the owner @field object used
5923 * This function must be used with instance fields, as they have more strict family accessibility.
5924 * It can be used with static fields, but context_klass should be NULL.
5926 * Returns: TRUE if caller have proper visibility and acessibility to @field
5929 mono_method_can_access_field_full (MonoMethod
*method
, MonoClassField
*field
, MonoClass
*context_klass
)
5931 MonoClass
*access_class
= method
->klass
;
5932 MonoClass
*member_class
= field
->parent
;
5933 /* FIXME: check all overlapping fields */
5934 int can
= can_access_member (access_class
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5936 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5938 can
= can_access_member (nested
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5941 nested
= m_class_get_nested_in (nested
);
5948 can
= can_access_type (access_class
, member_class
);
5950 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5952 can
= can_access_type (nested
, member_class
);
5955 nested
= m_class_get_nested_in (nested
);
5965 * mono_class_can_access_class:
5966 * @source_class: The source class
5967 * @target_class: The accessed class
5969 * This function returns is @target_class is visible to @source_class
5971 * Returns: TRUE if source have proper visibility and acessibility to target
5974 mono_class_can_access_class (MonoClass
*source_class
, MonoClass
*target_class
)
5976 return can_access_type (source_class
, target_class
);
5980 * mono_type_is_valid_enum_basetype:
5981 * \param type The MonoType to check
5982 * \returns TRUE if the type can be used as the basetype of an enum
5984 gboolean
mono_type_is_valid_enum_basetype (MonoType
* type
) {
5985 switch (type
->type
) {
5988 case MONO_TYPE_BOOLEAN
:
5991 case MONO_TYPE_CHAR
:
6009 * mono_class_is_valid_enum:
6010 * \param klass An enum class to be validated
6012 * This method verify the required properties an enum should have.
6014 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
6015 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
6016 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
6018 * \returns TRUE if the informed enum class is valid
6021 mono_class_is_valid_enum (MonoClass
*klass
)
6023 MonoClassField
* field
;
6024 gpointer iter
= NULL
;
6025 gboolean found_base_field
= FALSE
;
6027 g_assert (m_class_is_enumtype (klass
));
6028 MonoClass
*klass_parent
= m_class_get_parent (klass
);
6029 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
6030 if (!klass_parent
|| strcmp (m_class_get_name (klass_parent
), "Enum") || strcmp (m_class_get_name_space (klass_parent
), "System") ) {
6034 if (!mono_class_is_auto_layout (klass
))
6037 while ((field
= mono_class_get_fields_internal (klass
, &iter
))) {
6038 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
6039 if (found_base_field
)
6041 found_base_field
= TRUE
;
6042 if (!mono_type_is_valid_enum_basetype (field
->type
))
6047 if (!found_base_field
)
6050 if (mono_class_get_method_count (klass
) > 0)
6057 mono_generic_class_is_generic_type_definition (MonoGenericClass
*gklass
)
6059 return gklass
->context
.class_inst
== mono_class_get_generic_container (gklass
->container_class
)->context
.class_inst
;
6063 mono_field_resolve_type (MonoClassField
*field
, MonoError
*error
)
6065 MonoClass
*klass
= field
->parent
;
6066 MonoImage
*image
= m_class_get_image (klass
);
6067 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
6069 int field_idx
= field
- m_class_get_fields (klass
);
6074 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
6075 MonoType
*gtype
= mono_field_get_type_checked (gfield
, error
);
6076 if (!is_ok (error
)) {
6077 char *full_name
= mono_type_get_full_name (gtd
);
6078 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
));
6082 ftype
= mono_class_inflate_generic_type_no_copy (image
, gtype
, mono_class_get_context (klass
), error
);
6083 if (!is_ok (error
)) {
6084 char *full_name
= mono_type_get_full_name (klass
);
6085 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
));
6090 guint32 cols
[MONO_FIELD_SIZE
];
6091 MonoGenericContainer
*container
= NULL
;
6092 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
6094 /*FIXME, in theory we do not lazy load SRE fields*/
6095 g_assert (!image_is_dynamic (image
));
6097 if (mono_class_is_gtd (klass
)) {
6098 container
= mono_class_get_generic_container (klass
);
6100 container
= mono_class_get_generic_container (gtd
);
6101 g_assert (container
);
6104 /* first_field_idx and idx points into the fieldptr table */
6105 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
6107 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
)) {
6108 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
6112 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
6114 mono_metadata_decode_value (sig
, &sig
);
6115 /* FIELD signature == 0x06 */
6116 g_assert (*sig
== 0x06);
6118 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
6120 char *full_name
= mono_type_get_full_name (klass
);
6121 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
));
6125 mono_memory_barrier ();
6126 field
->type
= ftype
;
6130 mono_field_resolve_flags (MonoClassField
*field
)
6132 MonoClass
*klass
= field
->parent
;
6133 MonoImage
*image
= m_class_get_image (klass
);
6134 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
6135 int field_idx
= field
- m_class_get_fields (klass
);
6138 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
6139 return mono_field_get_flags (gfield
);
6141 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
6143 /*FIXME, in theory we do not lazy load SRE fields*/
6144 g_assert (!image_is_dynamic (image
));
6146 return mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_FLAGS
);
6151 * mono_class_get_fields_lazy:
6152 * \param klass the MonoClass to act on
6154 * This routine is an iterator routine for retrieving the fields in a class.
6155 * Only minimal information about fields are loaded. Accessors must be used
6156 * for all MonoClassField returned.
6158 * You must pass a gpointer that points to zero and is treated as an opaque handle to
6159 * iterate over all of the elements. When no more values are
6160 * available, the return value is NULL.
6162 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
6165 mono_class_get_fields_lazy (MonoClass
* klass
, gpointer
*iter
)
6167 MonoClassField
* field
;
6171 mono_class_setup_basic_field_info (klass
);
6172 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
6175 /* start from the first */
6176 if (mono_class_get_field_count (klass
)) {
6177 *iter
= &klass_fields
[0];
6178 return (MonoClassField
*)*iter
;
6184 field
= (MonoClassField
*)*iter
;
6186 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
6188 return (MonoClassField
*)*iter
;
6194 mono_class_full_name (MonoClass
*klass
)
6196 return mono_type_full_name (m_class_get_byval_arg (klass
));
6199 /* Declare all shared lazy type lookup functions */
6200 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle
, "System.Runtime.InteropServices", "SafeHandle")
6203 * mono_method_get_base_method:
6204 * \param method a method
6205 * \param definition if true, get the definition
6206 * \param error set on failure
6208 * Given a virtual method associated with a subclass, return the corresponding
6209 * method from an ancestor. If \p definition is FALSE, returns the method in the
6210 * superclass of the given method. If \p definition is TRUE, return the method
6211 * in the ancestor class where it was first declared. The type arguments will
6212 * be inflated in the ancestor classes. If the method is not associated with a
6213 * class, or isn't virtual, returns the method itself. On failure returns NULL
6214 * and sets \p error.
6217 mono_method_get_base_method (MonoMethod
*method
, gboolean definition
, MonoError
*error
)
6219 MonoClass
*klass
, *parent
;
6220 MonoGenericContext
*generic_inst
= NULL
;
6221 MonoMethod
*result
= NULL
;
6224 if (method
->klass
== NULL
)
6227 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
6228 MONO_CLASS_IS_INTERFACE_INTERNAL (method
->klass
) ||
6229 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
6232 slot
= mono_method_get_vtable_slot (method
);
6236 klass
= method
->klass
;
6237 if (mono_class_is_ginst (klass
)) {
6238 generic_inst
= mono_class_get_context (klass
);
6239 klass
= mono_class_get_generic_class (klass
)->container_class
;
6244 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6245 for (parent
= m_class_get_parent (klass
); parent
!= NULL
; parent
= m_class_get_parent (parent
)) {
6246 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6247 or klass is the generic container class and generic_inst is the instantiation.
6249 when we go to the parent, if the parent is an open constructed type, we need to
6250 replace the type parameters by the definitions from the generic_inst, and then take it
6251 apart again into the klass and the generic_inst.
6253 For cases like this:
6254 class C<T> : B<T, int> {
6255 public override void Foo () { ... }
6257 class B<U,V> : A<HashMap<U,V>> {
6258 public override void Foo () { ... }
6261 public virtual void Foo () { ... }
6264 if at each iteration the parent isn't open, we can skip inflating it. if at some
6265 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6268 MonoGenericContext
*parent_inst
= NULL
;
6269 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (parent
))) {
6270 parent
= mono_class_inflate_generic_class_checked (parent
, generic_inst
, error
);
6271 return_val_if_nok (error
, NULL
);
6273 if (mono_class_is_ginst (parent
)) {
6274 parent_inst
= mono_class_get_context (parent
);
6275 parent
= mono_class_get_generic_class (parent
)->container_class
;
6278 mono_class_setup_vtable (parent
);
6279 if (m_class_get_vtable_size (parent
) <= slot
)
6282 generic_inst
= parent_inst
;
6285 klass
= m_class_get_parent (klass
);
6288 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (klass
))) {
6289 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6290 return_val_if_nok (error
, NULL
);
6292 generic_inst
= NULL
;
6294 if (mono_class_is_ginst (klass
)) {
6295 generic_inst
= mono_class_get_context (klass
);
6296 klass
= mono_class_get_generic_class (klass
)->container_class
;
6302 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6303 return_val_if_nok (error
, NULL
);
6306 if (klass
== method
->klass
)
6309 /*This is possible if definition == FALSE.
6310 * Do it here to be really sure we don't read invalid memory.
6312 if (slot
>= m_class_get_vtable_size (klass
))
6315 mono_class_setup_vtable (klass
);
6317 result
= m_class_get_vtable (klass
) [slot
];
6318 if (result
== NULL
) {
6319 /* It is an abstract method */
6320 gboolean found
= FALSE
;
6321 gpointer iter
= NULL
;
6322 while ((result
= mono_class_get_methods (klass
, &iter
))) {
6323 if (result
->slot
== slot
) {
6328 /* found might be FALSE if we looked in an abstract class
6329 * that doesn't override an abstract method of its
6331 * abstract class Base {
6332 * public abstract void Foo ();
6334 * abstract class Derived : Base { }
6335 * class Child : Derived {
6336 * public override void Foo () { }
6339 * if m was Child.Foo and we ask for the base method,
6340 * then we get here with klass == Derived and found == FALSE
6342 /* but it shouldn't be the case that if we're looking
6343 * for the definition and didn't find a result; the
6344 * loop above should've taken us as far as we could
6346 g_assert (!(definition
&& !found
));
6351 g_assert (result
!= NULL
);