3 * Class management for the Mono runtime
6 * Miguel de Icaza (miguel@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/image-internals.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/exception-internals.h>
26 #include <mono/metadata/metadata.h>
27 #include <mono/metadata/metadata-internals.h>
28 #include <mono/metadata/profiler-private.h>
29 #include <mono/metadata/tabledefs.h>
30 #include <mono/metadata/tokentype.h>
31 #include <mono/metadata/class-init.h>
32 #include <mono/metadata/class-internals.h>
33 #include <mono/metadata/object.h>
34 #include <mono/metadata/appdomain.h>
35 #include <mono/metadata/mono-endian.h>
36 #include <mono/metadata/debug-helpers.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/exception.h>
39 #include <mono/metadata/security-manager.h>
40 #include <mono/metadata/security-core-clr.h>
41 #include <mono/metadata/attrdefs.h>
42 #include <mono/metadata/gc-internals.h>
43 #include <mono/metadata/verify-internals.h>
44 #include <mono/metadata/mono-debug.h>
45 #include <mono/utils/mono-counters.h>
46 #include <mono/utils/mono-string.h>
47 #include <mono/utils/mono-error-internals.h>
48 #include <mono/utils/mono-logger-internals.h>
49 #include <mono/utils/mono-memory-model.h>
50 #include <mono/utils/atomic.h>
51 #include <mono/utils/unlocked.h>
52 #include <mono/utils/bsearch.h>
53 #include <mono/utils/checked-build.h>
58 extern gint32 mono_inflated_methods_size
;
60 /* Function supplied by the runtime to find classes by name using information from the AOT file */
61 static MonoGetClassFromName get_class_from_name
= NULL
;
63 static gboolean
can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
);
65 static char* mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
);
66 static guint32
mono_field_resolve_flags (MonoClassField
*field
);
68 GENERATE_GET_CLASS_WITH_CACHE (valuetype
, "System", "ValueType")
69 GENERATE_TRY_GET_CLASS_WITH_CACHE (handleref
, "System.Runtime.InteropServices", "HandleRef")
71 // define to print types whenever custom modifiers are appended during inflation
72 #undef DEBUG_INFLATE_CMODS
76 mono_method_get_image (MonoMethod
*method
)
78 return m_class_get_image (method
->klass
);
82 * mono_class_from_typeref:
83 * \param image a MonoImage
84 * \param type_token a TypeRef token
86 * Creates the \c MonoClass* structure representing the type defined by
87 * the typeref token valid inside \p image.
88 * \returns The \c MonoClass* representing the typeref token, or NULL if it could
92 mono_class_from_typeref (MonoImage
*image
, guint32 type_token
)
95 MonoClass
*klass
= mono_class_from_typeref_checked (image
, type_token
, error
);
96 g_assert (mono_error_ok (error
)); /*FIXME proper error handling*/
101 * mono_class_from_typeref_checked:
102 * \param image a MonoImage
103 * \param type_token a TypeRef token
104 * \param error error return code, if any.
106 * Creates the \c MonoClass* structure representing the type defined by
107 * the typeref token valid inside \p image.
109 * \returns The \c MonoClass* representing the typeref token, NULL if it could
110 * not be loaded with the \p error value filled with the information about the
114 mono_class_from_typeref_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
116 guint32 cols
[MONO_TYPEREF_SIZE
];
117 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
119 const char *name
, *nspace
;
120 MonoClass
*res
= NULL
;
125 if (!mono_verifier_verify_typeref_row (image
, (type_token
& 0xffffff) - 1, error
))
128 mono_metadata_decode_row (t
, (type_token
&0xffffff)-1, cols
, MONO_TYPEREF_SIZE
);
130 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
131 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
133 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
134 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
135 case MONO_RESOLUTION_SCOPE_MODULE
:
137 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
138 This is not the observed behavior of existing implementations.
139 The defacto behavior is that it's just a typedef in disguise.
141 /* a typedef in disguise */
142 res
= mono_class_from_name_checked (image
, nspace
, name
, error
);
145 case MONO_RESOLUTION_SCOPE_MODULEREF
:
146 module
= mono_image_load_module_checked (image
, idx
, error
);
148 res
= mono_class_from_name_checked (module
, nspace
, name
, error
);
151 case MONO_RESOLUTION_SCOPE_TYPEREF
: {
152 MonoClass
*enclosing
;
155 if (idx
== mono_metadata_token_index (type_token
)) {
156 mono_error_set_bad_image (error
, image
, "Image with self-referencing typeref token %08x.", type_token
);
160 enclosing
= mono_class_from_typeref_checked (image
, MONO_TOKEN_TYPE_REF
| idx
, error
);
161 return_val_if_nok (error
, NULL
);
163 GList
*nested_classes
= mono_class_get_nested_classes_property (enclosing
);
164 if (m_class_is_nested_classes_inited (enclosing
) && nested_classes
) {
165 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
166 for (tmp
= nested_classes
; tmp
; tmp
= tmp
->next
) {
167 res
= (MonoClass
*)tmp
->data
;
168 if (strcmp (m_class_get_name (res
), name
) == 0)
172 MonoImage
*enclosing_image
= m_class_get_image (enclosing
);
173 guint32 enclosing_type_token
= m_class_get_type_token (enclosing
);
174 /* Don't call mono_class_init_internal as we might've been called by it recursively */
175 int i
= mono_metadata_nesting_typedef (enclosing_image
, enclosing_type_token
, 1);
177 guint32 class_nested
= mono_metadata_decode_row_col (&enclosing_image
->tables
[MONO_TABLE_NESTEDCLASS
], i
- 1, MONO_NESTED_CLASS_NESTED
);
178 guint32 string_offset
= mono_metadata_decode_row_col (&enclosing_image
->tables
[MONO_TABLE_TYPEDEF
], class_nested
- 1, MONO_TYPEDEF_NAME
);
179 const char *nname
= mono_metadata_string_heap (enclosing_image
, string_offset
);
181 if (strcmp (nname
, name
) == 0)
182 return mono_class_create_from_typedef (enclosing_image
, MONO_TOKEN_TYPE_DEF
| class_nested
, error
);
184 i
= mono_metadata_nesting_typedef (enclosing_image
, enclosing_type_token
, i
+ 1);
187 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx
, nspace
, name
, image
->name
);
190 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
194 if (idx
> image
->tables
[MONO_TABLE_ASSEMBLYREF
].rows
) {
195 mono_error_set_bad_image (error
, image
, "Image with invalid assemblyref token %08x.", idx
);
199 if (!image
->references
|| !image
->references
[idx
- 1])
200 mono_assembly_load_reference (image
, idx
- 1);
201 g_assert (image
->references
[idx
- 1]);
203 /* If the assembly did not load, register this as a type load exception */
204 if (image
->references
[idx
- 1] == REFERENCE_MISSING
){
205 MonoAssemblyName aname
;
208 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
209 human_name
= mono_stringify_assembly_name (&aname
);
210 gboolean refonly
= FALSE
;
212 refonly
= mono_asmctx_get_kind (&image
->assembly
->context
) == MONO_ASMCTX_REFONLY
;
213 mono_error_set_simple_file_not_found (error
, human_name
, refonly
);
218 res
= mono_class_from_name_checked (image
->references
[idx
- 1]->image
, nspace
, name
, error
);
221 /* Generic case, should be avoided for when a better error is possible. */
222 if (!res
&& mono_error_ok (error
)) {
223 char *name
= mono_class_name_from_token (image
, type_token
);
224 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
225 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
);
232 mono_image_memdup (MonoImage
*image
, void *data
, guint size
)
234 void *res
= mono_image_alloc (image
, size
);
235 memcpy (res
, data
, size
);
239 /* Copy everything mono_metadata_free_array free. */
241 mono_dup_array_type (MonoImage
*image
, MonoArrayType
*a
)
244 a
= (MonoArrayType
*)mono_image_memdup (image
, a
, sizeof (MonoArrayType
));
246 a
->sizes
= (int *)mono_image_memdup (image
, a
->sizes
, a
->numsizes
* sizeof (int));
248 a
->lobounds
= (int *)mono_image_memdup (image
, a
->lobounds
, a
->numlobounds
* sizeof (int));
250 a
= (MonoArrayType
*)g_memdup (a
, sizeof (MonoArrayType
));
252 a
->sizes
= (int *)g_memdup (a
->sizes
, a
->numsizes
* sizeof (int));
254 a
->lobounds
= (int *)g_memdup (a
->lobounds
, a
->numlobounds
* sizeof (int));
259 /* Copy everything mono_metadata_free_method_signature free. */
261 mono_metadata_signature_deep_dup (MonoImage
*image
, MonoMethodSignature
*sig
)
265 sig
= mono_metadata_signature_dup_full (image
, sig
);
267 sig
->ret
= mono_metadata_type_dup (image
, sig
->ret
);
268 for (i
= 0; i
< sig
->param_count
; ++i
)
269 sig
->params
[i
] = mono_metadata_type_dup (image
, sig
->params
[i
]);
275 _mono_type_get_assembly_name (MonoClass
*klass
, GString
*str
)
277 MonoAssembly
*ta
= m_class_get_image (klass
)->assembly
;
280 name
= mono_stringify_assembly_name (&ta
->aname
);
281 g_string_append_printf (str
, ", %s", name
);
286 mono_type_name_check_byref (MonoType
*type
, GString
*str
)
289 g_string_append_c (str
, '&');
293 * mono_identifier_escape_type_name_chars:
294 * \param str a destination string
295 * \param identifier an IDENTIFIER in internal form
299 * The displayed form of the identifier is appended to str.
301 * The displayed form of an identifier has the characters ,+&*[]\
302 * that have special meaning in type names escaped with a preceeding
303 * backslash (\) character.
306 mono_identifier_escape_type_name_chars (GString
* str
, const char* identifier
)
312 // reserve space for common case: there will be no escaped characters.
313 g_string_set_size(str
, n
+ strlen(identifier
));
314 g_string_set_size(str
, n
);
316 for (const char* s
= identifier
; *s
!= 0 ; s
++) {
325 g_string_append_c (str
, '\\');
326 g_string_append_c (str
, *s
);
329 g_string_append_c (str
, *s
);
337 mono_type_get_name_recurse (MonoType
*type
, GString
*str
, gboolean is_recursed
,
338 MonoTypeNameFormat format
)
342 switch (type
->type
) {
343 case MONO_TYPE_ARRAY
: {
344 int i
, rank
= type
->data
.array
->rank
;
345 MonoTypeNameFormat nested_format
;
347 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
348 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
350 mono_type_get_name_recurse (
351 m_class_get_byval_arg (type
->data
.array
->eklass
), str
, FALSE
, nested_format
);
352 g_string_append_c (str
, '[');
354 g_string_append_c (str
, '*');
355 for (i
= 1; i
< rank
; i
++)
356 g_string_append_c (str
, ',');
357 g_string_append_c (str
, ']');
359 mono_type_name_check_byref (type
, str
);
361 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
362 _mono_type_get_assembly_name (type
->data
.array
->eklass
, str
);
365 case MONO_TYPE_SZARRAY
: {
366 MonoTypeNameFormat nested_format
;
368 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
369 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
371 mono_type_get_name_recurse (
372 m_class_get_byval_arg (type
->data
.klass
), str
, FALSE
, nested_format
);
373 g_string_append (str
, "[]");
375 mono_type_name_check_byref (type
, str
);
377 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
378 _mono_type_get_assembly_name (type
->data
.klass
, str
);
381 case MONO_TYPE_PTR
: {
382 MonoTypeNameFormat nested_format
;
384 nested_format
= format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
?
385 MONO_TYPE_NAME_FORMAT_FULL_NAME
: format
;
387 mono_type_get_name_recurse (
388 type
->data
.type
, str
, FALSE
, nested_format
);
389 g_string_append_c (str
, '*');
391 mono_type_name_check_byref (type
, str
);
393 if (format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)
394 _mono_type_get_assembly_name (mono_class_from_mono_type_internal (type
->data
.type
), str
);
399 if (!mono_generic_param_name (type
->data
.generic_param
))
400 g_string_append_printf (str
, "%s%d", type
->type
== MONO_TYPE_VAR
? "!" : "!!", type
->data
.generic_param
->num
);
402 g_string_append (str
, mono_generic_param_name (type
->data
.generic_param
));
404 mono_type_name_check_byref (type
, str
);
408 klass
= mono_class_from_mono_type_internal (type
);
409 if (m_class_get_nested_in (klass
)) {
410 mono_type_get_name_recurse (
411 m_class_get_byval_arg (m_class_get_nested_in (klass
)), str
, TRUE
, format
);
412 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
413 g_string_append_c (str
, '.');
415 g_string_append_c (str
, '+');
416 } else if (*m_class_get_name_space (klass
)) {
417 const char *klass_name_space
= m_class_get_name_space (klass
);
418 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
419 g_string_append (str
, klass_name_space
);
421 mono_identifier_escape_type_name_chars (str
, klass_name_space
);
422 g_string_append_c (str
, '.');
424 const char *klass_name
= m_class_get_name (klass
);
425 if (format
== MONO_TYPE_NAME_FORMAT_IL
) {
426 const char *s
= strchr (klass_name
, '`');
427 gssize len
= s
? (s
- klass_name
) : (gssize
)strlen (klass_name
);
428 g_string_append_len (str
, klass_name
, len
);
430 mono_identifier_escape_type_name_chars (str
, klass_name
);
434 if (mono_class_is_ginst (klass
)) {
435 MonoGenericClass
*gclass
= mono_class_get_generic_class (klass
);
436 MonoGenericInst
*inst
= gclass
->context
.class_inst
;
437 MonoTypeNameFormat nested_format
;
440 nested_format
= format
== MONO_TYPE_NAME_FORMAT_FULL_NAME
?
441 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
: format
;
443 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
444 g_string_append_c (str
, '<');
446 g_string_append_c (str
, '[');
447 for (i
= 0; i
< inst
->type_argc
; i
++) {
448 MonoType
*t
= inst
->type_argv
[i
];
451 g_string_append_c (str
, ',');
452 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
453 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
454 g_string_append_c (str
, '[');
455 mono_type_get_name_recurse (inst
->type_argv
[i
], str
, FALSE
, nested_format
);
456 if ((nested_format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
457 (t
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
458 g_string_append_c (str
, ']');
460 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
461 g_string_append_c (str
, '>');
463 g_string_append_c (str
, ']');
464 } else if (mono_class_is_gtd (klass
) &&
465 (format
!= MONO_TYPE_NAME_FORMAT_FULL_NAME
) &&
466 (format
!= MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
)) {
469 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
470 g_string_append_c (str
, '<');
472 g_string_append_c (str
, '[');
473 for (i
= 0; i
< mono_class_get_generic_container (klass
)->type_argc
; i
++) {
475 g_string_append_c (str
, ',');
476 g_string_append (str
, mono_generic_container_get_param_info (mono_class_get_generic_container (klass
), i
)->name
);
478 if (format
== MONO_TYPE_NAME_FORMAT_IL
)
479 g_string_append_c (str
, '>');
481 g_string_append_c (str
, ']');
484 mono_type_name_check_byref (type
, str
);
486 if ((format
== MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
) &&
487 (type
->type
!= MONO_TYPE_VAR
) && (type
->type
!= MONO_TYPE_MVAR
))
488 _mono_type_get_assembly_name (klass
, str
);
494 * mono_type_get_name_full:
496 * \param format the format for the return string.
499 * \returns The string representation in a number of formats:
501 * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
502 * returned in the format required by \c System.Reflection, this is the
503 * inverse of mono_reflection_parse_type().
505 * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
506 * be used by the IL assembler.
508 * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
510 * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
513 mono_type_get_name_full (MonoType
*type
, MonoTypeNameFormat format
)
517 result
= g_string_new ("");
519 mono_type_get_name_recurse (type
, result
, FALSE
, format
);
521 return g_string_free (result
, FALSE
);
525 * mono_type_get_full_name:
526 * \param class a class
528 * \returns The string representation for type as required by System.Reflection.
529 * The inverse of mono_reflection_parse_type().
532 mono_type_get_full_name (MonoClass
*klass
)
534 return mono_type_get_name_full (m_class_get_byval_arg (klass
), MONO_TYPE_NAME_FORMAT_REFLECTION
);
538 * mono_type_get_name:
540 * \returns The string representation for type as it would be represented in IL code.
543 mono_type_get_name (MonoType
*type
)
545 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_IL
);
549 * mono_type_get_underlying_type:
551 * \returns The \c MonoType for the underlying integer type if \p type
552 * is an enum and byref is false, otherwise the type itself.
555 mono_type_get_underlying_type (MonoType
*type
)
557 if (type
->type
== MONO_TYPE_VALUETYPE
&& m_class_is_enumtype (type
->data
.klass
) && !type
->byref
)
558 return mono_class_enum_basetype_internal (type
->data
.klass
);
559 if (type
->type
== MONO_TYPE_GENERICINST
&& m_class_is_enumtype (type
->data
.generic_class
->container_class
) && !type
->byref
)
560 return mono_class_enum_basetype_internal (type
->data
.generic_class
->container_class
);
565 * mono_class_is_open_constructed_type:
568 * \returns TRUE if type represents a generics open constructed type.
569 * IOW, not all type parameters required for the instantiation have
570 * been provided or it's a generic type definition.
572 * An open constructed type means it's a non realizable type. Not to
573 * be mixed up with an abstract type - we can't cast or dispatch to
574 * an open type, for example.
577 mono_class_is_open_constructed_type (MonoType
*t
)
583 case MONO_TYPE_SZARRAY
:
584 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t
->data
.klass
));
585 case MONO_TYPE_ARRAY
:
586 return mono_class_is_open_constructed_type (m_class_get_byval_arg (t
->data
.array
->eklass
));
588 return mono_class_is_open_constructed_type (t
->data
.type
);
589 case MONO_TYPE_GENERICINST
:
590 return t
->data
.generic_class
->context
.class_inst
->is_open
;
591 case MONO_TYPE_CLASS
:
592 case MONO_TYPE_VALUETYPE
:
593 return mono_class_is_gtd (t
->data
.klass
);
600 This is a simple function to catch the most common bad instances of generic types.
601 Specially those that might lead to further failures in the runtime.
604 mono_type_is_valid_generic_argument (MonoType
*type
)
606 switch (type
->type
) {
608 case MONO_TYPE_TYPEDBYREF
:
610 case MONO_TYPE_VALUETYPE
:
611 return !m_class_is_byreflike (type
->data
.klass
);
618 can_inflate_gparam_with (MonoGenericParam
*gparam
, MonoType
*type
)
620 if (!mono_type_is_valid_generic_argument (type
))
623 /* Avoid inflating gparams with valuetype constraints with ref types during gsharing */
624 MonoGenericParamInfo
*info
= mono_generic_param_info (gparam
);
625 if (info
&& (info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
)) {
626 if (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
) {
627 MonoGenericParam
*inst_gparam
= type
->data
.generic_param
;
628 if (inst_gparam
->gshared_constraint
&& inst_gparam
->gshared_constraint
->type
== MONO_TYPE_OBJECT
)
637 inflate_generic_custom_modifiers (MonoImage
*image
, const MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
);
640 inflate_generic_type (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
642 gboolean changed
= FALSE
;
645 /* C++/CLI (and some Roslyn tests) constructs method signatures like:
646 * void .CL1`1.Test(!0 modopt(System.Nullable`1<!0>))
647 * where !0 has a custom modifier which itself mentions the type variable.
648 * So we need to potentially inflate the modifiers.
650 if (type
->has_cmods
) {
651 MonoType
*new_type
= inflate_generic_custom_modifiers (image
, type
, context
, error
);
652 return_val_if_nok (error
, NULL
);
653 if (new_type
!= NULL
) {
659 switch (type
->type
) {
660 case MONO_TYPE_MVAR
: {
662 int num
= mono_type_get_generic_param_num (type
);
663 MonoGenericInst
*inst
= context
->method_inst
;
670 MonoGenericParam
*gparam
= type
->data
.generic_param
;
671 if (num
>= inst
->type_argc
) {
672 const char *pname
= mono_generic_param_name (gparam
);
673 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
674 num
, pname
? pname
: "", inst
->type_argc
);
678 if (!can_inflate_gparam_with (gparam
, inst
->type_argv
[num
])) {
679 const char *pname
= mono_generic_param_name (gparam
);
680 mono_error_set_bad_image (error
, image
, "MVAR %d (%s) cannot be expanded with type 0x%x",
681 num
, pname
? pname
: "", inst
->type_argv
[num
]->type
);
685 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
686 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
687 * ->byref and ->attrs from @type are propagated to the returned type.
689 nt
= mono_metadata_type_dup_with_cmods (image
, inst
->type_argv
[num
], type
);
690 nt
->byref
= type
->byref
;
691 nt
->attrs
= type
->attrs
;
694 case MONO_TYPE_VAR
: {
696 int num
= mono_type_get_generic_param_num (type
);
697 MonoGenericInst
*inst
= context
->class_inst
;
704 MonoGenericParam
*gparam
= type
->data
.generic_param
;
705 if (num
>= inst
->type_argc
) {
706 const char *pname
= mono_generic_param_name (gparam
);
707 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
708 num
, pname
? pname
: "", inst
->type_argc
);
711 if (!can_inflate_gparam_with (gparam
, inst
->type_argv
[num
])) {
712 const char *pname
= mono_generic_param_name (gparam
);
713 mono_error_set_bad_image (error
, image
, "VAR %d (%s) cannot be expanded with type 0x%x",
714 num
, pname
? pname
: "", inst
->type_argv
[num
]->type
);
718 #ifdef DEBUG_INFLATE_CMODS
719 gboolean append_cmods
;
720 append_cmods
= FALSE
;
721 if (type
->has_cmods
&& inst
->type_argv
[num
]->has_cmods
) {
722 char *tname
= mono_type_full_name (type
);
723 char *vname
= mono_type_full_name (inst
->type_argv
[num
]);
724 printf ("\n\n\tsubstitution for '%s' with '%s' yields...\n", tname
, vname
);
731 nt
= mono_metadata_type_dup_with_cmods (image
, inst
->type_argv
[num
], type
);
732 nt
->byref
= type
->byref
|| inst
->type_argv
[num
]->byref
;
733 nt
->attrs
= type
->attrs
;
734 #ifdef DEBUG_INFLATE_CMODS
736 char *ntname
= mono_type_full_name (nt
);
737 printf ("\tyields '%s'\n\n\n", ntname
);
743 case MONO_TYPE_SZARRAY
: {
744 MonoClass
*eclass
= type
->data
.klass
;
745 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (eclass
), context
, error
);
746 if ((!inflated
&& !changed
) || !mono_error_ok (error
))
750 nt
= mono_metadata_type_dup (image
, type
);
751 nt
->data
.klass
= mono_class_from_mono_type_internal (inflated
);
752 mono_metadata_free_type (inflated
);
755 case MONO_TYPE_ARRAY
: {
756 MonoClass
*eclass
= type
->data
.array
->eklass
;
757 MonoType
*nt
, *inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (eclass
), context
, error
);
758 if ((!inflated
&& !changed
) || !mono_error_ok (error
))
762 nt
= mono_metadata_type_dup (image
, type
);
763 nt
->data
.array
->eklass
= mono_class_from_mono_type_internal (inflated
);
764 mono_metadata_free_type (inflated
);
767 case MONO_TYPE_GENERICINST
: {
768 MonoGenericClass
*gclass
= type
->data
.generic_class
;
769 MonoGenericInst
*inst
;
771 if (!gclass
->context
.class_inst
->is_open
) {
778 inst
= mono_metadata_inflate_generic_inst (gclass
->context
.class_inst
, context
, error
);
779 return_val_if_nok (error
, NULL
);
781 if (inst
!= gclass
->context
.class_inst
)
782 gclass
= mono_metadata_lookup_generic_class (gclass
->container_class
, inst
, gclass
->is_dynamic
);
784 if (gclass
== type
->data
.generic_class
) {
791 nt
= mono_metadata_type_dup (image
, type
);
792 nt
->data
.generic_class
= gclass
;
795 case MONO_TYPE_CLASS
:
796 case MONO_TYPE_VALUETYPE
: {
797 MonoClass
*klass
= type
->data
.klass
;
798 MonoGenericContainer
*container
= mono_class_try_get_generic_container (klass
);
799 MonoGenericInst
*inst
;
800 MonoGenericClass
*gclass
= NULL
;
810 /* We can't use context->class_inst directly, since it can have more elements */
811 inst
= mono_metadata_inflate_generic_inst (container
->context
.class_inst
, context
, error
);
812 return_val_if_nok (error
, NULL
);
814 if (inst
== container
->context
.class_inst
) {
821 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, image_is_dynamic (m_class_get_image (klass
)));
823 nt
= mono_metadata_type_dup (image
, type
);
824 nt
->type
= MONO_TYPE_GENERICINST
;
825 nt
->data
.generic_class
= gclass
;
828 case MONO_TYPE_PTR
: {
829 MonoType
*nt
, *inflated
= inflate_generic_type (image
, type
->data
.type
, context
, error
);
830 if ((!inflated
&& !changed
) || !mono_error_ok (error
))
832 if (!inflated
&& changed
)
834 nt
= mono_metadata_type_dup (image
, type
);
835 nt
->data
.type
= inflated
;
848 inflate_generic_custom_modifiers (MonoImage
*image
, const MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
850 MonoType
*result
= NULL
;
851 g_assert (type
->has_cmods
);
852 int count
= mono_type_custom_modifier_count (type
);
853 gboolean changed
= FALSE
;
855 /* Try not to blow up the stack. See comment on MONO_MAX_EXPECTED_CMODS. */
856 g_assert (count
< MONO_MAX_EXPECTED_CMODS
);
857 size_t aggregate_size
= mono_sizeof_aggregate_modifiers (count
);
858 MonoAggregateModContainer
*candidate_mods
= g_alloca (aggregate_size
);
859 memset (candidate_mods
, 0, aggregate_size
);
860 candidate_mods
->count
= count
;
862 for (int i
= 0; i
< count
; ++i
) {
864 MonoType
*cmod_old
= mono_type_get_custom_modifier (type
, i
, &required
, error
);
865 goto_if_nok (error
, leave
);
866 MonoType
*cmod_new
= inflate_generic_type (NULL
, cmod_old
, context
, error
);
867 goto_if_nok (error
, leave
);
870 candidate_mods
->modifiers
[i
].required
= required
;
871 candidate_mods
->modifiers
[i
].type
= cmod_new
;
875 /* 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. */
876 for (int i
= 0; i
< count
; ++i
) {
877 if (candidate_mods
->modifiers
[i
].type
== NULL
) {
878 candidate_mods
->modifiers
[i
].type
= mono_metadata_type_dup (NULL
, mono_type_get_custom_modifier (type
, i
, NULL
, error
));
880 /* it didn't error in the first loop, so should be ok now, too */
881 mono_error_assert_ok (error
);
885 #ifdef DEBUG_INFLATE_CMODS
887 char *full_name
= mono_type_full_name ((MonoType
*)type
);
888 printf ("\n\n\tcustom modifier on '%s' affected by subsititution\n\n\n", full_name
);
893 MonoType
*new_type
= g_alloca (mono_sizeof_type_with_mods (count
, TRUE
));
894 /* first init just the non-modifier portion of new_type before populating the
896 memcpy (new_type
, type
, MONO_SIZEOF_TYPE
);
897 mono_type_with_mods_init (new_type
, count
, TRUE
);
898 mono_type_set_amods (new_type
, mono_metadata_get_canonical_aggregate_modifiers (candidate_mods
));
899 result
= mono_metadata_type_dup (image
, new_type
);
903 for (int i
= 0; i
< count
; ++i
) {
904 if (candidate_mods
->modifiers
[i
].type
)
905 mono_metadata_free_type (candidate_mods
->modifiers
[i
].type
);
912 mono_generic_class_get_context (MonoGenericClass
*gclass
)
914 return &gclass
->context
;
918 mono_class_get_context (MonoClass
*klass
)
920 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
921 return gklass
? mono_generic_class_get_context (gklass
) : NULL
;
925 * mono_class_inflate_generic_type_with_mempool:
926 * @mempool: a mempool
928 * @context: a generics context
929 * @error: error context
931 * The same as mono_class_inflate_generic_type, but allocates the MonoType
932 * from mempool if it is non-NULL. If it is NULL, the MonoType is
933 * allocated on the heap and is owned by the caller.
934 * The returned type can potentially be the same as TYPE, so it should not be
935 * modified by the caller, and it should be freed using mono_metadata_free_type ().
938 mono_class_inflate_generic_type_with_mempool (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
940 MonoType
*inflated
= NULL
;
944 inflated
= inflate_generic_type (image
, type
, context
, error
);
945 return_val_if_nok (error
, NULL
);
948 MonoType
*shared
= mono_metadata_get_shared_type (type
);
950 if (shared
&& !type
->has_cmods
) {
953 return mono_metadata_type_dup (image
, type
);
957 UnlockedIncrement (&mono_stats
.inflated_type_count
);
962 * mono_class_inflate_generic_type:
964 * \param context a generics context
965 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
967 * If \p type is a generic type and \p context is not NULL, instantiate it using the
968 * generics context \p context.
970 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
971 * on the heap and is owned by the caller. Returns NULL on error.
974 mono_class_inflate_generic_type (MonoType
*type
, MonoGenericContext
*context
)
978 result
= mono_class_inflate_generic_type_checked (type
, context
, error
);
979 mono_error_cleanup (error
);
984 * mono_class_inflate_generic_type:
986 * @context: a generics context
987 * @error: error context to use
989 * If @type is a generic type and @context is not NULL, instantiate it using the
990 * generics context @context.
992 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
993 * on the heap and is owned by the caller.
996 mono_class_inflate_generic_type_checked (MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
998 return mono_class_inflate_generic_type_with_mempool (NULL
, type
, context
, error
);
1002 * mono_class_inflate_generic_type_no_copy:
1004 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
1008 mono_class_inflate_generic_type_no_copy (MonoImage
*image
, MonoType
*type
, MonoGenericContext
*context
, MonoError
*error
)
1010 MonoType
*inflated
= NULL
;
1014 inflated
= inflate_generic_type (image
, type
, context
, error
);
1015 return_val_if_nok (error
, NULL
);
1021 UnlockedIncrement (&mono_stats
.inflated_type_count
);
1026 * mono_class_inflate_generic_class:
1028 * Inflate the class @gklass with @context. Set @error on failure.
1031 mono_class_inflate_generic_class_checked (MonoClass
*gklass
, MonoGenericContext
*context
, MonoError
*error
)
1036 inflated
= mono_class_inflate_generic_type_checked (m_class_get_byval_arg (gklass
), context
, error
);
1037 return_val_if_nok (error
, NULL
);
1039 res
= mono_class_from_mono_type_internal (inflated
);
1040 mono_metadata_free_type (inflated
);
1045 static MonoGenericContext
1046 inflate_generic_context (MonoGenericContext
*context
, MonoGenericContext
*inflate_with
, MonoError
*error
)
1048 MonoGenericInst
*class_inst
= NULL
;
1049 MonoGenericInst
*method_inst
= NULL
;
1050 MonoGenericContext res
= { NULL
, NULL
};
1054 if (context
->class_inst
) {
1055 class_inst
= mono_metadata_inflate_generic_inst (context
->class_inst
, inflate_with
, error
);
1056 if (!mono_error_ok (error
))
1060 if (context
->method_inst
) {
1061 method_inst
= mono_metadata_inflate_generic_inst (context
->method_inst
, inflate_with
, error
);
1062 if (!mono_error_ok (error
))
1066 res
.class_inst
= class_inst
;
1067 res
.method_inst
= method_inst
;
1073 * mono_class_inflate_generic_method:
1074 * \param method a generic method
1075 * \param context a generics context
1077 * Instantiate the generic method \p method using the generics context \p context.
1079 * \returns The new instantiated method
1082 mono_class_inflate_generic_method (MonoMethod
*method
, MonoGenericContext
*context
)
1086 MonoMethod
*res
= mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
1087 mono_error_assert_msg_ok (error
, "Could not inflate generic method");
1092 mono_class_inflate_generic_method_checked (MonoMethod
*method
, MonoGenericContext
*context
, MonoError
*error
)
1094 return mono_class_inflate_generic_method_full_checked (method
, NULL
, context
, error
);
1098 * mono_class_inflate_generic_method_full_checked:
1099 * Instantiate method \p method with the generic context \p context.
1100 * On failure returns NULL and sets \p error.
1102 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1103 * Use mono_method_signature_internal () and mono_method_get_header () to get the correct values.
1106 mono_class_inflate_generic_method_full_checked (MonoMethod
*method
, MonoClass
*klass_hint
, MonoGenericContext
*context
, MonoError
*error
)
1109 MonoMethodInflated
*iresult
, *cached
;
1110 MonoMethodSignature
*sig
;
1111 MonoGenericContext tmp_context
;
1115 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1116 while (method
->is_inflated
) {
1117 MonoGenericContext
*method_context
= mono_method_get_context (method
);
1118 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1120 tmp_context
= inflate_generic_context (method_context
, context
, error
);
1121 return_val_if_nok (error
, NULL
);
1123 context
= &tmp_context
;
1125 if (mono_metadata_generic_context_equal (method_context
, context
))
1128 method
= imethod
->declaring
;
1132 * A method only needs to be inflated if the context has argument for which it is
1135 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1136 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1139 if (!((method
->is_generic
&& context
->method_inst
) ||
1140 (mono_class_is_gtd (method
->klass
) && context
->class_inst
)))
1143 iresult
= g_new0 (MonoMethodInflated
, 1);
1144 iresult
->context
= *context
;
1145 iresult
->declaring
= method
;
1147 if (!context
->method_inst
&& method
->is_generic
)
1148 iresult
->context
.method_inst
= mono_method_get_generic_container (method
)->context
.method_inst
;
1150 if (!context
->class_inst
) {
1151 g_assert (!mono_class_is_ginst (iresult
->declaring
->klass
));
1152 if (mono_class_is_gtd (iresult
->declaring
->klass
))
1153 iresult
->context
.class_inst
= mono_class_get_generic_container (iresult
->declaring
->klass
)->context
.class_inst
;
1155 /* This can happen with some callers like mono_object_get_virtual_method_internal () */
1156 if (!mono_class_is_gtd (iresult
->declaring
->klass
) && !mono_class_is_ginst (iresult
->declaring
->klass
))
1157 iresult
->context
.class_inst
= NULL
;
1159 MonoImageSet
*set
= mono_metadata_get_image_set_for_method (iresult
);
1162 mono_image_set_lock (set
);
1163 cached
= (MonoMethodInflated
*)g_hash_table_lookup (set
->gmethod_cache
, iresult
);
1164 mono_image_set_unlock (set
);
1168 return (MonoMethod
*)cached
;
1171 UnlockedIncrement (&mono_stats
.inflated_method_count
);
1173 UnlockedAdd (&mono_inflated_methods_size
, sizeof (MonoMethodInflated
));
1175 sig
= mono_method_signature_internal (method
);
1177 char *name
= mono_type_get_full_name (method
->klass
);
1178 mono_error_set_bad_image (error
, mono_method_get_image (method
), "Could not resolve signature of method %s:%s", name
, method
->name
);
1184 memcpy (&iresult
->method
.pinvoke
, method
, sizeof (MonoMethodPInvoke
));
1186 memcpy (&iresult
->method
.method
, method
, sizeof (MonoMethod
));
1189 result
= (MonoMethod
*) iresult
;
1190 result
->is_inflated
= TRUE
;
1191 result
->is_generic
= FALSE
;
1192 result
->sre_method
= FALSE
;
1193 result
->signature
= NULL
;
1195 if (method
->wrapper_type
) {
1196 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)method
;
1197 MonoMethodWrapper
*resw
= (MonoMethodWrapper
*)result
;
1198 int len
= GPOINTER_TO_INT (((void**)mw
->method_data
) [0]);
1200 resw
->method_data
= (void **)g_malloc (sizeof (gpointer
) * (len
+ 1));
1201 memcpy (resw
->method_data
, mw
->method_data
, sizeof (gpointer
) * (len
+ 1));
1204 if (iresult
->context
.method_inst
) {
1205 MonoGenericInst
*method_inst
= iresult
->context
.method_inst
;
1206 /* Set the generic_container of the result to the generic_container of method */
1207 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
1209 if (generic_container
&& method_inst
== generic_container
->context
.method_inst
) {
1210 result
->is_generic
= 1;
1211 mono_method_set_generic_container (result
, generic_container
);
1214 /* Check that the method is not instantiated with any invalid types */
1215 for (int i
= 0; i
< method_inst
->type_argc
; i
++) {
1216 if (!mono_type_is_valid_generic_argument (method_inst
->type_argv
[i
])) {
1217 mono_error_set_bad_image (error
, mono_method_get_image (method
), "MVAR %d cannot be expanded with type 0x%x",
1218 i
, method_inst
->type_argv
[i
]->type
);
1225 MonoGenericClass
*gklass_hint
= mono_class_try_get_generic_class (klass_hint
);
1226 if (gklass_hint
&& (gklass_hint
->container_class
!= method
->klass
|| gklass_hint
->context
.class_inst
!= context
->class_inst
))
1230 if (mono_class_is_gtd (method
->klass
))
1231 result
->klass
= klass_hint
;
1233 if (!result
->klass
) {
1234 MonoType
*inflated
= inflate_generic_type (NULL
, m_class_get_byval_arg (method
->klass
), context
, error
);
1235 if (!mono_error_ok (error
))
1238 result
->klass
= inflated
? mono_class_from_mono_type_internal (inflated
) : method
->klass
;
1240 mono_metadata_free_type (inflated
);
1244 * FIXME: This should hold, but it doesn't:
1246 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1247 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1248 * g_assert (result->is_generic);
1251 * Fixing this here causes other things to break, hence a very
1252 * ugly hack in mini-trampolines.c - see
1253 * is_generic_method_definition().
1257 mono_image_set_lock (set
);
1258 cached
= (MonoMethodInflated
*)g_hash_table_lookup (set
->gmethod_cache
, iresult
);
1260 g_hash_table_insert (set
->gmethod_cache
, iresult
, iresult
);
1261 iresult
->owner
= set
;
1264 mono_image_set_unlock (set
);
1266 return (MonoMethod
*)cached
;
1274 * mono_get_inflated_method:
1276 * Obsolete. We keep it around since it's mentioned in the public API.
1279 mono_get_inflated_method (MonoMethod
*method
)
1285 * mono_method_get_context_general:
1287 * @uninflated: handle uninflated methods?
1289 * Returns the generic context of a method or NULL if it doesn't have
1290 * one. For an inflated method that's the context stored in the
1291 * method. Otherwise it's in the method's generic container or in the
1292 * generic container of the method's class.
1295 mono_method_get_context_general (MonoMethod
*method
, gboolean uninflated
)
1297 if (method
->is_inflated
) {
1298 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) method
;
1299 return &imethod
->context
;
1303 if (method
->is_generic
)
1304 return &(mono_method_get_generic_container (method
)->context
);
1305 if (mono_class_is_gtd (method
->klass
))
1306 return &mono_class_get_generic_container (method
->klass
)->context
;
1311 * mono_method_get_context:
1314 * Returns the generic context for method if it's inflated, otherwise
1318 mono_method_get_context (MonoMethod
*method
)
1320 return mono_method_get_context_general (method
, FALSE
);
1324 * mono_method_get_generic_container:
1326 * Returns the generic container of METHOD, which should be a generic method definition.
1327 * Returns NULL if METHOD is not a generic method definition.
1328 * LOCKING: Acquires the loader lock.
1330 MonoGenericContainer
*
1331 mono_method_get_generic_container (MonoMethod
*method
)
1333 MonoGenericContainer
*container
;
1335 if (!method
->is_generic
)
1338 container
= (MonoGenericContainer
*)mono_image_property_lookup (mono_method_get_image (method
), method
, MONO_METHOD_PROP_GENERIC_CONTAINER
);
1339 g_assert (container
);
1345 * mono_method_set_generic_container:
1347 * Sets the generic container of METHOD to CONTAINER.
1348 * LOCKING: Acquires the image lock.
1351 mono_method_set_generic_container (MonoMethod
*method
, MonoGenericContainer
* container
)
1353 g_assert (method
->is_generic
);
1355 mono_image_property_insert (mono_method_get_image (method
), method
, MONO_METHOD_PROP_GENERIC_CONTAINER
, container
);
1359 * mono_class_find_enum_basetype:
1360 * \param class The enum class
1362 * Determine the basetype of an enum by iterating through its fields. We do this
1363 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1366 mono_class_find_enum_basetype (MonoClass
*klass
, MonoError
*error
)
1368 MonoGenericContainer
*container
= NULL
;
1369 MonoImage
*image
= m_class_get_image (klass
);
1370 const int top
= mono_class_get_field_count (klass
);
1371 int i
, first_field_idx
;
1373 g_assert (m_class_is_enumtype (klass
));
1377 container
= mono_class_try_get_generic_container (klass
);
1378 if (mono_class_is_ginst (klass
)) {
1379 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1381 container
= mono_class_get_generic_container (gklass
);
1382 g_assert (container
);
1386 * Fetch all the field information.
1388 first_field_idx
= mono_class_get_first_field_idx (klass
);
1389 for (i
= 0; i
< top
; i
++){
1391 guint32 cols
[MONO_FIELD_SIZE
];
1392 int idx
= first_field_idx
+ i
;
1395 /* first_field_idx and idx points into the fieldptr table */
1396 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
1398 if (cols
[MONO_FIELD_FLAGS
] & FIELD_ATTRIBUTE_STATIC
) //no need to decode static fields
1401 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
))
1404 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
1405 mono_metadata_decode_value (sig
, &sig
);
1406 /* FIELD signature == 0x06 */
1408 mono_error_set_bad_image (error
, image
, "Invalid field signature %x, expected 0x6 but got %x", cols
[MONO_FIELD_SIGNATURE
], *sig
);
1412 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
1416 if (mono_class_is_ginst (klass
)) {
1417 //FIXME do we leak here?
1418 ftype
= mono_class_inflate_generic_type_checked (ftype
, mono_class_get_context (klass
), error
);
1419 if (!mono_error_ok (error
))
1421 ftype
->attrs
= cols
[MONO_FIELD_FLAGS
];
1426 mono_error_set_type_load_class (error
, klass
, "Could not find base type");
1433 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1436 mono_type_has_exceptions (MonoType
*type
)
1438 switch (type
->type
) {
1439 case MONO_TYPE_CLASS
:
1440 case MONO_TYPE_VALUETYPE
:
1441 case MONO_TYPE_SZARRAY
:
1442 return mono_class_has_failure (type
->data
.klass
);
1443 case MONO_TYPE_ARRAY
:
1444 return mono_class_has_failure (type
->data
.array
->eklass
);
1445 case MONO_TYPE_GENERICINST
:
1446 return mono_class_has_failure (mono_class_create_generic_inst (type
->data
.generic_class
));
1453 mono_error_set_for_class_failure (MonoError
*oerror
, const MonoClass
*klass
)
1455 g_assert (mono_class_has_failure (klass
));
1456 MonoErrorBoxed
*box
= mono_class_get_exception_data ((MonoClass
*)klass
);
1457 mono_error_set_from_boxed (oerror
, box
);
1463 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1467 mono_class_alloc (MonoClass
*klass
, int size
)
1469 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1471 return mono_image_set_alloc (gklass
->owner
, size
);
1473 return mono_image_alloc (m_class_get_image (klass
), size
);
1477 (mono_class_alloc0
) (MonoClass
*klass
, int size
)
1481 res
= mono_class_alloc (klass
, size
);
1482 memset (res
, 0, size
);
1486 #define mono_class_new0(klass,struct_type, n_structs) \
1487 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1490 * mono_class_set_failure_causedby_class:
1491 * \param klass the class that is failing
1492 * \param caused_by the class that caused the failure
1493 * \param msg Why \p klass is failing.
1495 * If \p caused_by has a failure, sets a TypeLoadException failure on
1496 * \p klass with message "\p msg, due to: {\p caused_by message}".
1498 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1501 mono_class_set_type_load_failure_causedby_class (MonoClass
*klass
, const MonoClass
*caused_by
, const gchar
* msg
)
1503 if (mono_class_has_failure (caused_by
)) {
1504 ERROR_DECL (cause_error
);
1505 mono_error_set_for_class_failure (cause_error
, caused_by
);
1506 mono_class_set_type_load_failure (klass
, "%s, due to: %s", msg
, mono_error_get_message (cause_error
));
1507 mono_error_cleanup (cause_error
);
1516 * mono_type_get_basic_type_from_generic:
1519 * Returns a closed type corresponding to the possibly open type
1523 mono_type_get_basic_type_from_generic (MonoType
*type
)
1525 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1526 if (!type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
) &&
1527 (!type
->data
.generic_param
->gshared_constraint
|| type
->data
.generic_param
->gshared_constraint
->type
== MONO_TYPE_OBJECT
))
1528 return mono_get_object_type ();
1533 * mono_class_get_method_by_index:
1535 * Returns klass->methods [index], initializing klass->methods if neccesary.
1537 * LOCKING: Acquires the loader lock.
1540 mono_class_get_method_by_index (MonoClass
*klass
, int index
)
1544 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1545 /* Avoid calling setup_methods () if possible */
1546 if (gklass
&& !m_class_get_methods (klass
)) {
1549 m
= mono_class_inflate_generic_method_full_checked (
1550 m_class_get_methods (gklass
->container_class
) [index
], klass
, mono_class_get_context (klass
), error
);
1551 g_assert (mono_error_ok (error
)); /* FIXME don't swallow the error */
1553 * If setup_methods () is called later for this class, no duplicates are created,
1554 * since inflate_generic_method guarantees that only one instance of a method
1555 * is created for each context.
1558 mono_class_setup_methods (klass);
1559 g_assert (m == klass->methods [index]);
1563 mono_class_setup_methods (klass
);
1564 if (mono_class_has_failure (klass
)) /*FIXME do proper error handling*/
1566 g_assert (index
>= 0 && index
< mono_class_get_method_count (klass
));
1567 return m_class_get_methods (klass
) [index
];
1572 * mono_class_get_inflated_method:
1573 * \param klass an inflated class
1574 * \param method a method of \p klass's generic definition
1575 * \param error set on error
1577 * Given an inflated class \p klass and a method \p method which should be a
1578 * method of \p klass's generic definition, return the inflated method
1579 * corresponding to \p method.
1581 * On failure sets \p error and returns NULL.
1584 mono_class_get_inflated_method (MonoClass
*klass
, MonoMethod
*method
, MonoError
*error
)
1586 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1589 g_assert (method
->klass
== gklass
);
1591 mono_class_setup_methods (gklass
);
1592 if (mono_class_has_failure (gklass
)) {
1593 mono_error_set_for_class_failure (error
, gklass
);
1597 MonoMethod
**gklass_methods
= m_class_get_methods (gklass
);
1598 mcount
= mono_class_get_method_count (gklass
);
1599 for (i
= 0; i
< mcount
; ++i
) {
1600 if (gklass_methods
[i
] == method
) {
1601 MonoMethod
*inflated_method
= NULL
;
1602 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
1603 if (klass_methods
) {
1604 inflated_method
= klass_methods
[i
];
1606 inflated_method
= mono_class_inflate_generic_method_full_checked (gklass_methods
[i
], klass
, mono_class_get_context (klass
), error
);
1607 return_val_if_nok (error
, NULL
);
1609 g_assert (inflated_method
);
1610 return inflated_method
;
1614 g_assert_not_reached ();
1618 * mono_class_get_vtable_entry:
1620 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
1621 * LOCKING: Acquires the loader lock.
1624 mono_class_get_vtable_entry (MonoClass
*klass
, int offset
)
1628 if (m_class_get_rank (klass
) == 1) {
1629 MonoClass
*klass_parent
= m_class_get_parent (klass
);
1631 * szarrays do not overwrite any methods of Array, so we can avoid
1632 * initializing their vtables in some cases.
1634 mono_class_setup_vtable (klass_parent
);
1635 if (offset
< m_class_get_vtable_size (klass_parent
))
1636 return m_class_get_vtable (klass_parent
) [offset
];
1639 if (mono_class_is_ginst (klass
)) {
1641 MonoClass
*gklass
= mono_class_get_generic_class (klass
)->container_class
;
1642 mono_class_setup_vtable (gklass
);
1643 m
= m_class_get_vtable (gklass
) [offset
];
1645 m
= mono_class_inflate_generic_method_full_checked (m
, klass
, mono_class_get_context (klass
), error
);
1646 g_assert (mono_error_ok (error
)); /* FIXME don't swallow this error */
1648 mono_class_setup_vtable (klass
);
1649 if (mono_class_has_failure (klass
))
1651 m
= m_class_get_vtable (klass
) [offset
];
1658 * mono_class_get_vtable_size:
1660 * Return the vtable size for KLASS.
1663 mono_class_get_vtable_size (MonoClass
*klass
)
1665 mono_class_setup_vtable (klass
);
1667 return m_class_get_vtable_size (klass
);
1671 collect_implemented_interfaces_aux (MonoClass
*klass
, GPtrArray
**res
, GHashTable
**ifaces
, MonoError
*error
)
1676 mono_class_setup_interfaces (klass
, error
);
1677 return_if_nok (error
);
1679 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
1680 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
1681 ic
= klass_interfaces
[i
];
1684 *res
= g_ptr_array_new ();
1685 if (*ifaces
== NULL
)
1686 *ifaces
= g_hash_table_new (NULL
, NULL
);
1687 if (g_hash_table_lookup (*ifaces
, ic
))
1689 /* A gparam is not an implemented interface for the purposes of
1690 * mono_class_get_implemented_interfaces */
1691 if (mono_class_is_gparam (ic
))
1693 g_ptr_array_add (*res
, ic
);
1694 g_hash_table_insert (*ifaces
, ic
, ic
);
1695 mono_class_init_internal (ic
);
1696 if (mono_class_has_failure (ic
)) {
1697 mono_error_set_type_load_class (error
, ic
, "Error Loading class");
1701 collect_implemented_interfaces_aux (ic
, res
, ifaces
, error
);
1702 return_if_nok (error
);
1707 mono_class_get_implemented_interfaces (MonoClass
*klass
, MonoError
*error
)
1709 GPtrArray
*res
= NULL
;
1710 GHashTable
*ifaces
= NULL
;
1712 collect_implemented_interfaces_aux (klass
, &res
, &ifaces
, error
);
1714 g_hash_table_destroy (ifaces
);
1715 if (!mono_error_ok (error
)) {
1717 g_ptr_array_free (res
, TRUE
);
1724 compare_interface_ids (const void *p_key
, const void *p_element
)
1726 MonoClass
*key
= (MonoClass
*)p_key
;
1727 MonoClass
*element
= *(MonoClass
**)p_element
;
1729 return (m_class_get_interface_id (key
) - m_class_get_interface_id (element
));
1732 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
1734 mono_class_interface_offset (MonoClass
*klass
, MonoClass
*itf
)
1737 MonoClass
**klass_interfaces_packed
= m_class_get_interfaces_packed (klass
);
1738 for (i
= m_class_get_interface_offsets_count (klass
) -1 ; i
>= 0 ; i
-- ){
1739 MonoClass
*result
= klass_interfaces_packed
[i
];
1740 if (m_class_get_interface_id(result
) == m_class_get_interface_id(itf
)) {
1741 return m_class_get_interface_offsets_packed (klass
) [i
];
1748 * mono_class_interface_offset_with_variance:
1750 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
1751 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
1753 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
1755 * FIXME figure out MS disambiguation rules and fix this function.
1758 mono_class_interface_offset_with_variance (MonoClass
*klass
, MonoClass
*itf
, gboolean
*non_exact_match
)
1760 int i
= mono_class_interface_offset (klass
, itf
);
1761 *non_exact_match
= FALSE
;
1765 int klass_interface_offsets_count
= m_class_get_interface_offsets_count (klass
);
1767 if (m_class_is_array_special_interface (itf
) && m_class_get_rank (klass
) < 2) {
1768 MonoClass
*gtd
= mono_class_get_generic_type_definition (itf
);
1771 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1772 if (mono_class_is_variant_compatible (itf
, m_class_get_interfaces_packed (klass
) [i
], FALSE
)) {
1774 *non_exact_match
= TRUE
;
1780 return m_class_get_interface_offsets_packed (klass
) [found
];
1782 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1783 if (mono_class_get_generic_type_definition (m_class_get_interfaces_packed (klass
) [i
]) == gtd
) {
1785 *non_exact_match
= TRUE
;
1793 return m_class_get_interface_offsets_packed (klass
) [found
];
1796 if (!mono_class_has_variant_generic_params (itf
))
1799 for (i
= 0; i
< klass_interface_offsets_count
; i
++) {
1800 if (mono_class_is_variant_compatible (itf
, m_class_get_interfaces_packed (klass
) [i
], FALSE
)) {
1801 *non_exact_match
= TRUE
;
1802 return m_class_get_interface_offsets_packed (klass
) [i
];
1811 * mono_method_get_vtable_slot:
1813 * Returns method->slot, computing it if neccesary. Return -1 on failure.
1814 * LOCKING: Acquires the loader lock.
1816 * FIXME Use proper MonoError machinery here.
1819 mono_method_get_vtable_slot (MonoMethod
*method
)
1821 if (method
->slot
== -1) {
1822 mono_class_setup_vtable (method
->klass
);
1823 if (mono_class_has_failure (method
->klass
))
1825 if (method
->slot
== -1) {
1829 if (!mono_class_is_ginst (method
->klass
)) {
1830 g_assert (method
->is_inflated
);
1831 return mono_method_get_vtable_slot (((MonoMethodInflated
*)method
)->declaring
);
1834 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
1835 g_assert (mono_class_is_ginst (method
->klass
));
1836 gklass
= mono_class_get_generic_class (method
->klass
)->container_class
;
1837 mono_class_setup_methods (method
->klass
);
1838 MonoMethod
**klass_methods
= m_class_get_methods (method
->klass
);
1839 g_assert (klass_methods
);
1840 mcount
= mono_class_get_method_count (method
->klass
);
1841 for (i
= 0; i
< mcount
; ++i
) {
1842 if (klass_methods
[i
] == method
)
1845 g_assert (i
< mcount
);
1846 g_assert (m_class_get_methods (gklass
));
1847 method
->slot
= m_class_get_methods (gklass
) [i
]->slot
;
1849 g_assert (method
->slot
!= -1);
1851 return method
->slot
;
1855 * mono_method_get_vtable_index:
1856 * \param method a method
1858 * Returns the index into the runtime vtable to access the method or,
1859 * in the case of a virtual generic method, the virtual generic method
1860 * thunk. Returns -1 on failure.
1862 * FIXME Use proper MonoError machinery here.
1865 mono_method_get_vtable_index (MonoMethod
*method
)
1867 if (method
->is_inflated
&& (method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
1868 MonoMethodInflated
*imethod
= (MonoMethodInflated
*)method
;
1869 if (imethod
->declaring
->is_generic
)
1870 return mono_method_get_vtable_slot (imethod
->declaring
);
1872 return mono_method_get_vtable_slot (method
);
1876 * mono_class_has_finalizer:
1878 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
1881 * LOCKING: Acquires the loader lock;
1884 mono_class_has_finalizer (MonoClass
*klass
)
1886 if (!m_class_is_has_finalize_inited (klass
))
1887 mono_class_setup_has_finalizer (klass
);
1889 return m_class_has_finalize (klass
);
1893 mono_is_corlib_image (MonoImage
*image
)
1895 return image
== mono_defaults
.corlib
;
1899 /** Is klass a Nullable<T> ginst? */
1901 mono_class_is_nullable (MonoClass
*klass
)
1903 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
1904 return gklass
&& gklass
->container_class
== mono_defaults
.generic_nullable_class
;
1907 /** if klass is T? return T */
1909 mono_class_get_nullable_param_internal (MonoClass
*klass
)
1911 g_assert (mono_class_is_nullable (klass
));
1912 return mono_class_from_mono_type_internal (mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0]);
1916 mono_class_get_nullable_param (MonoClass
*klass
)
1918 MonoClass
*result
= NULL
;
1919 MONO_ENTER_GC_UNSAFE
;
1920 result
= mono_class_get_nullable_param_internal (klass
);
1921 MONO_EXIT_GC_UNSAFE
;
1926 mono_type_is_primitive (MonoType
*type
)
1928 return (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_R8
) ||
1929 type
-> type
== MONO_TYPE_I
|| type
->type
== MONO_TYPE_U
;
1933 get_image_for_container (MonoGenericContainer
*container
)
1936 if (container
->is_anonymous
) {
1937 result
= container
->owner
.image
;
1940 if (container
->is_method
) {
1941 MonoMethod
*method
= container
->owner
.method
;
1942 g_assert_checked (method
);
1943 klass
= method
->klass
;
1945 klass
= container
->owner
.klass
;
1947 g_assert_checked (klass
);
1948 result
= m_class_get_image (klass
);
1955 mono_get_image_for_generic_param (MonoGenericParam
*param
)
1957 MonoGenericContainer
*container
= mono_generic_param_owner (param
);
1958 g_assert_checked (container
);
1959 return get_image_for_container (container
);
1962 // Make a string in the designated image consisting of a single integer.
1963 #define INT_STRING_SIZE 16
1965 mono_make_generic_name_string (MonoImage
*image
, int num
)
1967 char *name
= (char *)mono_image_alloc0 (image
, INT_STRING_SIZE
);
1968 g_snprintf (name
, INT_STRING_SIZE
, "%d", num
);
1973 * mono_class_from_generic_parameter:
1974 * \param param Parameter to find/construct a class for.
1975 * \param arg2 Is ignored.
1976 * \param arg3 Is ignored.
1979 mono_class_from_generic_parameter (MonoGenericParam
*param
, MonoImage
*arg2 G_GNUC_UNUSED
, gboolean arg3 G_GNUC_UNUSED
)
1981 return mono_class_create_generic_parameter (param
);
1985 * mono_ptr_class_get:
1988 mono_ptr_class_get (MonoType
*type
)
1990 return mono_class_create_ptr (type
);
1994 * mono_class_from_mono_type:
1995 * \param type describes the type to return
1996 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
1999 mono_class_from_mono_type (MonoType
*type
)
2002 MONO_ENTER_GC_UNSAFE
;
2003 result
= mono_class_from_mono_type_internal (type
);
2004 MONO_EXIT_GC_UNSAFE
;
2009 mono_class_from_mono_type_internal (MonoType
*type
)
2011 switch (type
->type
) {
2012 case MONO_TYPE_OBJECT
:
2013 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.object_class
;
2014 case MONO_TYPE_VOID
:
2015 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.void_class
;
2016 case MONO_TYPE_BOOLEAN
:
2017 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.boolean_class
;
2018 case MONO_TYPE_CHAR
:
2019 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.char_class
;
2021 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.sbyte_class
;
2023 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.byte_class
;
2025 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int16_class
;
2027 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint16_class
;
2029 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int32_class
;
2031 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint32_class
;
2033 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int_class
;
2035 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint_class
;
2037 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.int64_class
;
2039 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.uint64_class
;
2041 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.single_class
;
2043 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.double_class
;
2044 case MONO_TYPE_STRING
:
2045 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.string_class
;
2046 case MONO_TYPE_TYPEDBYREF
:
2047 return type
->data
.klass
? type
->data
.klass
: mono_defaults
.typed_reference_class
;
2048 case MONO_TYPE_ARRAY
:
2049 return mono_class_create_bounded_array (type
->data
.array
->eklass
, type
->data
.array
->rank
, TRUE
);
2051 return mono_class_create_ptr (type
->data
.type
);
2052 case MONO_TYPE_FNPTR
:
2053 return mono_class_create_fnptr (type
->data
.method
);
2054 case MONO_TYPE_SZARRAY
:
2055 return mono_class_create_array (type
->data
.klass
, 1);
2056 case MONO_TYPE_CLASS
:
2057 case MONO_TYPE_VALUETYPE
:
2058 return type
->data
.klass
;
2059 case MONO_TYPE_GENERICINST
:
2060 return mono_class_create_generic_inst (type
->data
.generic_class
);
2061 case MONO_TYPE_MVAR
:
2063 return mono_class_create_generic_parameter (type
->data
.generic_param
);
2065 g_warning ("mono_class_from_mono_type_internal: implement me 0x%02x\n", type
->type
);
2066 g_assert_not_reached ();
2069 // Yes, this returns NULL, even if it is documented as not doing so, but there
2070 // is no way for the code to make it this far, due to the assert above.
2075 * mono_type_retrieve_from_typespec
2076 * \param image context where the image is created
2077 * \param type_spec typespec token
2078 * \param context the generic context used to evaluate generic instantiations in
2081 mono_type_retrieve_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, gboolean
*did_inflate
, MonoError
*error
)
2083 MonoType
*t
= mono_type_create_from_typespec_checked (image
, type_spec
, error
);
2085 *did_inflate
= FALSE
;
2090 if (context
&& (context
->class_inst
|| context
->method_inst
)) {
2091 MonoType
*inflated
= inflate_generic_type (NULL
, t
, context
, error
);
2093 if (!mono_error_ok (error
)) {
2099 *did_inflate
= TRUE
;
2106 * mono_class_create_from_typespec
2107 * \param image context where the image is created
2108 * \param type_spec typespec token
2109 * \param context the generic context used to evaluate generic instantiations in
2112 mono_class_create_from_typespec (MonoImage
*image
, guint32 type_spec
, MonoGenericContext
*context
, MonoError
*error
)
2115 gboolean inflated
= FALSE
;
2116 MonoType
*t
= mono_type_retrieve_from_typespec (image
, type_spec
, context
, &inflated
, error
);
2117 return_val_if_nok (error
, NULL
);
2118 ret
= mono_class_from_mono_type_internal (t
);
2120 mono_metadata_free_type (t
);
2125 * mono_bounded_array_class_get:
2126 * \param element_class element class
2127 * \param rank the dimension of the array class
2128 * \param bounded whenever the array has non-zero bounds
2129 * \returns A class object describing the array with element type \p element_type and
2130 * dimension \p rank.
2133 mono_bounded_array_class_get (MonoClass
*eclass
, guint32 rank
, gboolean bounded
)
2135 return mono_class_create_bounded_array (eclass
, rank
, bounded
);
2139 * mono_array_class_get:
2140 * \param element_class element class
2141 * \param rank the dimension of the array class
2142 * \returns A class object describing the array with element type \p element_type and
2143 * dimension \p rank.
2146 mono_array_class_get (MonoClass
*eclass
, guint32 rank
)
2148 return mono_class_create_array (eclass
, rank
);
2152 * mono_class_instance_size:
2153 * \param klass a class
2155 * Use to get the size of a class in bytes.
2157 * \returns The size of an object instance
2160 mono_class_instance_size (MonoClass
*klass
)
2162 if (!m_class_is_size_inited (klass
))
2163 mono_class_init_internal (klass
);
2165 return m_class_get_instance_size (klass
);
2169 * mono_class_min_align:
2170 * \param klass a class
2172 * Use to get the computed minimum alignment requirements for the specified class.
2174 * Returns: minimum alignment requirements
2177 mono_class_min_align (MonoClass
*klass
)
2179 if (!m_class_is_size_inited (klass
))
2180 mono_class_init_internal (klass
);
2182 return m_class_get_min_align (klass
);
2186 * mono_class_data_size:
2187 * \param klass a class
2189 * \returns The size of the static class data
2192 mono_class_data_size (MonoClass
*klass
)
2194 if (!m_class_is_inited (klass
))
2195 mono_class_init_internal (klass
);
2196 /* This can happen with dynamically created types */
2197 if (!m_class_is_fields_inited (klass
))
2198 mono_class_setup_fields (klass
);
2200 /* in arrays, sizes.class_size is unioned with element_size
2201 * and arrays have no static fields
2203 if (m_class_get_rank (klass
))
2205 return m_class_get_sizes (klass
).class_size
;
2209 * Auxiliary routine to mono_class_get_field
2211 * Takes a field index instead of a field token.
2213 static MonoClassField
*
2214 mono_class_get_field_idx (MonoClass
*klass
, int idx
)
2216 mono_class_setup_fields (klass
);
2217 if (mono_class_has_failure (klass
))
2221 int first_field_idx
= mono_class_get_first_field_idx (klass
);
2222 int fcount
= mono_class_get_field_count (klass
);
2223 MonoImage
*klass_image
= m_class_get_image (klass
);
2224 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
2225 if (klass_image
->uncompressed_metadata
) {
2227 * first_field_idx points to the FieldPtr table, while idx points into the
2228 * Field table, so we have to do a search.
2230 /*FIXME this is broken for types with multiple fields with the same name.*/
2231 const char *name
= mono_metadata_string_heap (klass_image
, mono_metadata_decode_row_col (&klass_image
->tables
[MONO_TABLE_FIELD
], idx
, MONO_FIELD_NAME
));
2234 for (i
= 0; i
< fcount
; ++i
)
2235 if (mono_field_get_name (&klass_fields
[i
]) == name
)
2236 return &klass_fields
[i
];
2237 g_assert_not_reached ();
2240 if ((idx
>= first_field_idx
) && (idx
< first_field_idx
+ fcount
)){
2241 return &klass_fields
[idx
- first_field_idx
];
2245 klass
= m_class_get_parent (klass
);
2251 * mono_class_get_field:
2252 * \param class the class to lookup the field.
2253 * \param field_token the field token
2255 * \returns A \c MonoClassField representing the type and offset of
2256 * the field, or a NULL value if the field does not belong to this
2260 mono_class_get_field (MonoClass
*klass
, guint32 field_token
)
2262 int idx
= mono_metadata_token_index (field_token
);
2264 g_assert (mono_metadata_token_code (field_token
) == MONO_TOKEN_FIELD_DEF
);
2266 return mono_class_get_field_idx (klass
, idx
- 1);
2270 * mono_class_get_field_from_name:
2271 * \param klass the class to lookup the field.
2272 * \param name the field name
2274 * Search the class \p klass and its parents for a field with the name \p name.
2276 * \returns The \c MonoClassField pointer of the named field or NULL
2279 mono_class_get_field_from_name (MonoClass
*klass
, const char *name
)
2281 MonoClassField
*result
;
2282 MONO_ENTER_GC_UNSAFE
;
2283 result
= mono_class_get_field_from_name_full (klass
, name
, NULL
);
2284 MONO_EXIT_GC_UNSAFE
;
2289 * mono_class_get_field_from_name_full:
2290 * \param klass the class to lookup the field.
2291 * \param name the field name
2292 * \param type the type of the fields. This optional.
2294 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
2296 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
2297 * of its generic type definition.
2299 * \returns The MonoClassField pointer of the named field or NULL
2302 mono_class_get_field_from_name_full (MonoClass
*klass
, const char *name
, MonoType
*type
)
2304 MONO_REQ_GC_UNSAFE_MODE
;
2308 mono_class_setup_fields (klass
);
2309 if (mono_class_has_failure (klass
))
2313 int fcount
= mono_class_get_field_count (klass
);
2314 for (i
= 0; i
< fcount
; ++i
) {
2315 MonoClassField
*field
= &m_class_get_fields (klass
) [i
];
2317 if (strcmp (name
, mono_field_get_name (field
)) != 0)
2321 MonoType
*field_type
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
)->type
;
2322 if (!mono_metadata_type_equal_full (type
, field_type
, TRUE
))
2327 klass
= m_class_get_parent (klass
);
2333 * mono_class_get_field_token:
2334 * \param field the field we need the token of
2336 * Get the token of a field. Note that the tokesn is only valid for the image
2337 * the field was loaded from. Don't use this function for fields in dynamic types.
2339 * \returns The token representing the field in the image it was loaded from.
2342 mono_class_get_field_token (MonoClassField
*field
)
2344 MonoClass
*klass
= field
->parent
;
2347 mono_class_setup_fields (klass
);
2350 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
2353 int first_field_idx
= mono_class_get_first_field_idx (klass
);
2354 int fcount
= mono_class_get_field_count (klass
);
2355 for (i
= 0; i
< fcount
; ++i
) {
2356 if (&klass_fields
[i
] == field
) {
2357 int idx
= first_field_idx
+ i
+ 1;
2359 if (m_class_get_image (klass
)->uncompressed_metadata
)
2360 idx
= mono_metadata_translate_token_index (m_class_get_image (klass
), MONO_TABLE_FIELD
, idx
);
2361 return mono_metadata_make_token (MONO_TABLE_FIELD
, idx
);
2364 klass
= m_class_get_parent (klass
);
2367 g_assert_not_reached ();
2372 mono_field_get_index (MonoClassField
*field
)
2374 int index
= field
- m_class_get_fields (field
->parent
);
2375 g_assert (index
>= 0 && index
< mono_class_get_field_count (field
->parent
));
2381 * mono_class_get_field_default_value:
2383 * Return the default value of the field as a pointer into the metadata blob.
2386 mono_class_get_field_default_value (MonoClassField
*field
, MonoTypeEnum
*def_type
)
2389 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
2391 MonoClass
*klass
= field
->parent
;
2392 MonoFieldDefaultValue
*def_values
;
2394 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
);
2396 def_values
= mono_class_get_field_def_values (klass
);
2398 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
2400 mono_class_set_field_def_values (klass
, def_values
);
2403 field_index
= mono_field_get_index (field
);
2405 if (!def_values
[field_index
].data
) {
2406 MonoImage
*field_parent_image
= m_class_get_image (field
->parent
);
2407 cindex
= mono_metadata_get_constant_index (field_parent_image
, mono_class_get_field_token (field
), 0);
2411 g_assert (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
));
2413 mono_metadata_decode_row (&field_parent_image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
2414 def_values
[field_index
].def_type
= (MonoTypeEnum
)constant_cols
[MONO_CONSTANT_TYPE
];
2415 mono_memory_barrier ();
2416 def_values
[field_index
].data
= (const char *)mono_metadata_blob_heap (field_parent_image
, constant_cols
[MONO_CONSTANT_VALUE
]);
2419 *def_type
= def_values
[field_index
].def_type
;
2420 return def_values
[field_index
].data
;
2424 mono_property_get_index (MonoProperty
*prop
)
2426 MonoClassPropertyInfo
*info
= mono_class_get_property_info (prop
->parent
);
2427 int index
= prop
- info
->properties
;
2429 g_assert (index
>= 0 && index
< info
->count
);
2435 * mono_class_get_property_default_value:
2437 * Return the default value of the field as a pointer into the metadata blob.
2440 mono_class_get_property_default_value (MonoProperty
*property
, MonoTypeEnum
*def_type
)
2443 guint32 constant_cols
[MONO_CONSTANT_SIZE
];
2444 MonoClass
*klass
= property
->parent
;
2445 MonoImage
*klass_image
= m_class_get_image (klass
);
2447 g_assert (property
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
);
2449 * We don't cache here because it is not used by C# so it's quite rare, but
2450 * we still do the lookup in klass->ext because that is where the data
2451 * is stored for dynamic assemblies.
2454 if (image_is_dynamic (klass_image
)) {
2455 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
2456 int prop_index
= mono_property_get_index (property
);
2457 if (info
->def_values
&& info
->def_values
[prop_index
].data
) {
2458 *def_type
= info
->def_values
[prop_index
].def_type
;
2459 return info
->def_values
[prop_index
].data
;
2463 cindex
= mono_metadata_get_constant_index (klass_image
, mono_class_get_property_token (property
), 0);
2467 mono_metadata_decode_row (&klass_image
->tables
[MONO_TABLE_CONSTANT
], cindex
- 1, constant_cols
, MONO_CONSTANT_SIZE
);
2468 *def_type
= (MonoTypeEnum
)constant_cols
[MONO_CONSTANT_TYPE
];
2469 return (const char *)mono_metadata_blob_heap (klass_image
, constant_cols
[MONO_CONSTANT_VALUE
]);
2473 * mono_class_get_event_token:
2476 mono_class_get_event_token (MonoEvent
*event
)
2478 MonoClass
*klass
= event
->parent
;
2482 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
2484 for (i
= 0; i
< info
->count
; ++i
) {
2485 if (&info
->events
[i
] == event
)
2486 return mono_metadata_make_token (MONO_TABLE_EVENT
, info
->first
+ i
+ 1);
2489 klass
= m_class_get_parent (klass
);
2492 g_assert_not_reached ();
2497 mono_class_get_property_from_name_internal (MonoClass
*klass
, const char *name
)
2499 MONO_REQ_GC_UNSAFE_MODE
;
2502 gpointer iter
= NULL
;
2503 while ((p
= mono_class_get_properties (klass
, &iter
))) {
2504 if (! strcmp (name
, p
->name
))
2507 klass
= m_class_get_parent (klass
);
2513 * mono_class_get_property_token:
2514 * \param prop MonoProperty to query
2516 * \returns The ECMA token for the specified property.
2519 mono_class_get_property_token (MonoProperty
*prop
)
2521 MonoClass
*klass
= prop
->parent
;
2525 gpointer iter
= NULL
;
2526 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
2527 while ((p
= mono_class_get_properties (klass
, &iter
))) {
2528 if (&info
->properties
[i
] == prop
)
2529 return mono_metadata_make_token (MONO_TABLE_PROPERTY
, info
->first
+ i
+ 1);
2533 klass
= m_class_get_parent (klass
);
2536 g_assert_not_reached ();
2541 * mono_class_name_from_token:
2544 mono_class_name_from_token (MonoImage
*image
, guint32 type_token
)
2546 const char *name
, *nspace
;
2547 if (image_is_dynamic (image
))
2548 return g_strdup_printf ("DynamicType 0x%08x", type_token
);
2550 switch (type_token
& 0xff000000){
2551 case MONO_TOKEN_TYPE_DEF
: {
2552 guint32 cols
[MONO_TYPEDEF_SIZE
];
2553 MonoTableInfo
*tt
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2554 guint tidx
= mono_metadata_token_index (type_token
);
2556 if (tidx
> tt
->rows
)
2557 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2559 mono_metadata_decode_row (tt
, tidx
- 1, cols
, MONO_TYPEDEF_SIZE
);
2560 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2561 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2562 if (strlen (nspace
) == 0)
2563 return g_strdup_printf ("%s", name
);
2565 return g_strdup_printf ("%s.%s", nspace
, name
);
2568 case MONO_TOKEN_TYPE_REF
: {
2570 guint32 cols
[MONO_TYPEREF_SIZE
];
2571 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2572 guint tidx
= mono_metadata_token_index (type_token
);
2575 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2577 if (!mono_verifier_verify_typeref_row (image
, tidx
- 1, error
)) {
2578 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (error
));
2579 mono_error_cleanup (error
);
2583 mono_metadata_decode_row (t
, tidx
-1, cols
, MONO_TYPEREF_SIZE
);
2584 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAME
]);
2585 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEREF_NAMESPACE
]);
2586 if (strlen (nspace
) == 0)
2587 return g_strdup_printf ("%s", name
);
2589 return g_strdup_printf ("%s.%s", nspace
, name
);
2592 case MONO_TOKEN_TYPE_SPEC
:
2593 return g_strdup_printf ("Typespec 0x%08x", type_token
);
2595 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2600 mono_assembly_name_from_token (MonoImage
*image
, guint32 type_token
)
2602 if (image_is_dynamic (image
))
2603 return g_strdup_printf ("DynamicAssembly %s", image
->name
);
2605 switch (type_token
& 0xff000000){
2606 case MONO_TOKEN_TYPE_DEF
:
2607 if (image
->assembly
)
2608 return mono_stringify_assembly_name (&image
->assembly
->aname
);
2609 else if (image
->assembly_name
)
2610 return g_strdup (image
->assembly_name
);
2611 return g_strdup_printf ("%s", image
->name
? image
->name
: "[Could not resolve assembly name");
2612 case MONO_TOKEN_TYPE_REF
: {
2614 MonoAssemblyName aname
;
2615 guint32 cols
[MONO_TYPEREF_SIZE
];
2616 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEREF
];
2617 guint32 idx
= mono_metadata_token_index (type_token
);
2620 return g_strdup_printf ("Invalid type token 0x%08x", type_token
);
2622 if (!mono_verifier_verify_typeref_row (image
, idx
- 1, error
)) {
2623 char *msg
= g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token
, mono_error_get_message (error
));
2624 mono_error_cleanup (error
);
2627 mono_metadata_decode_row (t
, idx
-1, cols
, MONO_TYPEREF_SIZE
);
2629 idx
= cols
[MONO_TYPEREF_SCOPE
] >> MONO_RESOLUTION_SCOPE_BITS
;
2630 switch (cols
[MONO_TYPEREF_SCOPE
] & MONO_RESOLUTION_SCOPE_MASK
) {
2631 case MONO_RESOLUTION_SCOPE_MODULE
:
2633 return g_strdup ("");
2634 case MONO_RESOLUTION_SCOPE_MODULEREF
:
2636 return g_strdup ("");
2637 case MONO_RESOLUTION_SCOPE_TYPEREF
:
2639 return g_strdup ("");
2640 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF
:
2641 mono_assembly_get_assemblyref (image
, idx
- 1, &aname
);
2642 return mono_stringify_assembly_name (&aname
);
2644 g_assert_not_reached ();
2648 case MONO_TOKEN_TYPE_SPEC
:
2650 return g_strdup ("");
2652 g_assert_not_reached ();
2659 * mono_class_get_full:
2660 * \param image the image where the class resides
2661 * \param type_token the token for the class
2662 * \param context the generic context used to evaluate generic instantiations in
2663 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
2664 * \returns The \c MonoClass that represents \p type_token in \p image
2667 mono_class_get_full (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
)
2671 klass
= mono_class_get_checked (image
, type_token
, error
);
2673 if (klass
&& context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
2674 klass
= mono_class_inflate_generic_class_checked (klass
, context
, error
);
2676 mono_error_assert_ok (error
);
2682 mono_class_get_and_inflate_typespec_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
2687 klass
= mono_class_get_checked (image
, type_token
, error
);
2689 if (klass
&& context
&& mono_metadata_token_table (type_token
) == MONO_TABLE_TYPESPEC
)
2690 klass
= mono_class_inflate_generic_class_checked (klass
, context
, error
);
2695 * mono_class_get_checked:
2696 * \param image the image where the class resides
2697 * \param type_token the token for the class
2698 * \param error error object to return any error
2700 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
2703 mono_class_get_checked (MonoImage
*image
, guint32 type_token
, MonoError
*error
)
2705 MonoClass
*klass
= NULL
;
2709 if (image_is_dynamic (image
)) {
2710 int table
= mono_metadata_token_table (type_token
);
2712 if (table
!= MONO_TABLE_TYPEDEF
&& table
!= MONO_TABLE_TYPEREF
&& table
!= MONO_TABLE_TYPESPEC
) {
2713 mono_error_set_bad_image (error
, image
,"Bad token table for dynamic image: %x", table
);
2716 klass
= (MonoClass
*)mono_lookup_dynamic_token (image
, type_token
, NULL
, error
);
2720 switch (type_token
& 0xff000000){
2721 case MONO_TOKEN_TYPE_DEF
:
2722 klass
= mono_class_create_from_typedef (image
, type_token
, error
);
2724 case MONO_TOKEN_TYPE_REF
:
2725 klass
= mono_class_from_typeref_checked (image
, type_token
, error
);
2727 case MONO_TOKEN_TYPE_SPEC
:
2728 klass
= mono_class_create_from_typespec (image
, type_token
, NULL
, error
);
2731 mono_error_set_bad_image (error
, image
, "Unknown type token %x", type_token
& 0xff000000);
2735 /* Generic case, should be avoided for when a better error is possible. */
2736 if (!klass
&& mono_error_ok (error
)) {
2737 char *name
= mono_class_name_from_token (image
, type_token
);
2738 char *assembly
= mono_assembly_name_from_token (image
, type_token
);
2739 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
);
2747 * mono_type_get_checked:
2748 * \param image the image where the type resides
2749 * \param type_token the token for the type
2750 * \param context the generic context used to evaluate generic instantiations in
2751 * \param error Error handling context
2753 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
2755 * \returns The MonoType that represents \p type_token in \p image
2758 mono_type_get_checked (MonoImage
*image
, guint32 type_token
, MonoGenericContext
*context
, MonoError
*error
)
2760 MonoType
*type
= NULL
;
2761 gboolean inflated
= FALSE
;
2765 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
2766 if (image_is_dynamic (image
)) {
2767 MonoClass
*klass
= (MonoClass
*)mono_lookup_dynamic_token (image
, type_token
, context
, error
);
2768 return_val_if_nok (error
, NULL
);
2769 return m_class_get_byval_arg (klass
);
2772 if ((type_token
& 0xff000000) != MONO_TOKEN_TYPE_SPEC
) {
2773 MonoClass
*klass
= mono_class_get_checked (image
, type_token
, error
);
2777 if (m_class_has_failure (klass
)) {
2778 mono_error_set_for_class_failure (error
, klass
);
2781 return m_class_get_byval_arg (klass
);
2784 type
= mono_type_retrieve_from_typespec (image
, type_token
, context
, &inflated
, error
);
2791 MonoType
*tmp
= type
;
2792 type
= m_class_get_byval_arg (mono_class_from_mono_type_internal (type
));
2793 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
2794 * A MonoClass::_byval_arg of a generic type definion has type CLASS.
2795 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with _byval_arg.
2797 * The long term solution is to chaise this places and make then set MonoType::type correctly.
2799 if (type
->type
!= tmp
->type
)
2802 mono_metadata_free_type (tmp
);
2809 * \param image image where the class token will be looked up.
2810 * \param type_token a type token from the image
2811 * \returns the \c MonoClass with the given \p type_token on the \p image
2814 mono_class_get (MonoImage
*image
, guint32 type_token
)
2818 MonoClass
*result
= mono_class_get_checked (image
, type_token
, error
);
2819 mono_error_assert_ok (error
);
2824 * mono_image_init_name_cache:
2826 * Initializes the class name cache stored in image->name_cache.
2828 * LOCKING: Acquires the corresponding image lock.
2831 mono_image_init_name_cache (MonoImage
*image
)
2833 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
2834 guint32 cols
[MONO_TYPEDEF_SIZE
];
2837 guint32 i
, visib
, nspace_index
;
2838 GHashTable
*name_cache2
, *nspace_table
, *the_name_cache
;
2840 if (image
->name_cache
)
2843 the_name_cache
= g_hash_table_new (g_str_hash
, g_str_equal
);
2845 if (image_is_dynamic (image
)) {
2846 mono_image_lock (image
);
2847 if (image
->name_cache
) {
2848 /* Somebody initialized it before us */
2849 g_hash_table_destroy (the_name_cache
);
2851 mono_atomic_store_release (&image
->name_cache
, the_name_cache
);
2853 mono_image_unlock (image
);
2857 /* Temporary hash table to avoid lookups in the nspace_table */
2858 name_cache2
= g_hash_table_new (NULL
, NULL
);
2860 for (i
= 1; i
<= t
->rows
; ++i
) {
2861 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
2862 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
2864 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
2865 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
2867 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
2869 name
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
2870 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
2872 nspace_index
= cols
[MONO_TYPEDEF_NAMESPACE
];
2873 nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
2874 if (!nspace_table
) {
2875 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2876 g_hash_table_insert (the_name_cache
, (char*)nspace
, nspace_table
);
2877 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
2880 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (i
));
2883 /* Load type names from EXPORTEDTYPES table */
2885 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
2886 guint32 cols
[MONO_EXP_TYPE_SIZE
];
2889 for (i
= 0; i
< t
->rows
; ++i
) {
2890 mono_metadata_decode_row (t
, i
, cols
, MONO_EXP_TYPE_SIZE
);
2892 guint32 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
2893 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_EXP_TYPE
)
2897 name
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAME
]);
2898 nspace
= mono_metadata_string_heap (image
, cols
[MONO_EXP_TYPE_NAMESPACE
]);
2900 nspace_index
= cols
[MONO_EXP_TYPE_NAMESPACE
];
2901 nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache2
, GUINT_TO_POINTER (nspace_index
));
2902 if (!nspace_table
) {
2903 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2904 g_hash_table_insert (the_name_cache
, (char*)nspace
, nspace_table
);
2905 g_hash_table_insert (name_cache2
, GUINT_TO_POINTER (nspace_index
),
2908 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE
, i
+ 1)));
2912 g_hash_table_destroy (name_cache2
);
2914 mono_image_lock (image
);
2915 if (image
->name_cache
) {
2916 /* Somebody initialized it before us */
2917 g_hash_table_destroy (the_name_cache
);
2919 mono_atomic_store_release (&image
->name_cache
, the_name_cache
);
2921 mono_image_unlock (image
);
2924 /*FIXME Only dynamic assemblies should allow this operation.*/
2926 * mono_image_add_to_name_cache:
2929 mono_image_add_to_name_cache (MonoImage
*image
, const char *nspace
,
2930 const char *name
, guint32 index
)
2932 GHashTable
*nspace_table
;
2933 GHashTable
*name_cache
;
2936 mono_image_init_name_cache (image
);
2937 mono_image_lock (image
);
2939 name_cache
= image
->name_cache
;
2940 if (!(nspace_table
= (GHashTable
*)g_hash_table_lookup (name_cache
, nspace
))) {
2941 nspace_table
= g_hash_table_new (g_str_hash
, g_str_equal
);
2942 g_hash_table_insert (name_cache
, (char *)nspace
, (char *)nspace_table
);
2945 if ((old_index
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, (char*) name
))))
2946 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index
, image
->name
, nspace
, name
);
2948 g_hash_table_insert (nspace_table
, (char *) name
, GUINT_TO_POINTER (index
));
2950 mono_image_unlock (image
);
2959 find_nocase (gpointer key
, gpointer value
, gpointer user_data
)
2961 char *name
= (char*)key
;
2962 FindUserData
*data
= (FindUserData
*)user_data
;
2964 if (!data
->value
&& (mono_utf8_strcasecmp (name
, (char*)data
->key
) == 0))
2965 data
->value
= value
;
2969 * mono_class_from_name_case:
2970 * \param image The MonoImage where the type is looked up in
2971 * \param name_space the type namespace
2972 * \param name the type short name.
2973 * \deprecated use the mono_class_from_name_case_checked variant instead.
2975 * Obtains a \c MonoClass with a given namespace and a given name which
2976 * is located in the given \c MonoImage. The namespace and name
2977 * lookups are case insensitive.
2980 mono_class_from_name_case (MonoImage
*image
, const char* name_space
, const char *name
)
2983 MonoClass
*res
= mono_class_from_name_case_checked (image
, name_space
, name
, error
);
2984 mono_error_cleanup (error
);
2990 * mono_class_from_name_case_checked:
2991 * \param image The MonoImage where the type is looked up in
2992 * \param name_space the type namespace
2993 * \param name the type short name.
2996 * Obtains a MonoClass with a given namespace and a given name which
2997 * is located in the given MonoImage. The namespace and name
2998 * lookups are case insensitive.
3000 * \returns The MonoClass if the given namespace and name were found, or NULL if it
3001 * was not found. The \p error object will contain information about the problem
3005 mono_class_from_name_case_checked (MonoImage
*image
, const char *name_space
, const char *name
, MonoError
*error
)
3007 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
3008 guint32 cols
[MONO_TYPEDEF_SIZE
];
3015 if (image_is_dynamic (image
)) {
3017 FindUserData user_data
;
3019 mono_image_init_name_cache (image
);
3020 mono_image_lock (image
);
3022 user_data
.key
= name_space
;
3023 user_data
.value
= NULL
;
3024 g_hash_table_foreach (image
->name_cache
, find_nocase
, &user_data
);
3026 if (user_data
.value
) {
3027 GHashTable
*nspace_table
= (GHashTable
*)user_data
.value
;
3029 user_data
.key
= name
;
3030 user_data
.value
= NULL
;
3032 g_hash_table_foreach (nspace_table
, find_nocase
, &user_data
);
3034 if (user_data
.value
)
3035 token
= GPOINTER_TO_UINT (user_data
.value
);
3038 mono_image_unlock (image
);
3041 return mono_class_get_checked (image
, MONO_TOKEN_TYPE_DEF
| token
, error
);
3047 /* add a cache if needed */
3048 for (i
= 1; i
<= t
->rows
; ++i
) {
3049 mono_metadata_decode_row (t
, i
- 1, cols
, MONO_TYPEDEF_SIZE
);
3050 visib
= cols
[MONO_TYPEDEF_FLAGS
] & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
3052 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
3053 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
3055 if (visib
>= TYPE_ATTRIBUTE_NESTED_PUBLIC
&& visib
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
)
3057 n
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAME
]);
3058 nspace
= mono_metadata_string_heap (image
, cols
[MONO_TYPEDEF_NAMESPACE
]);
3059 if (mono_utf8_strcasecmp (n
, name
) == 0 && mono_utf8_strcasecmp (nspace
, name_space
) == 0)
3060 return mono_class_get_checked (image
, MONO_TOKEN_TYPE_DEF
| i
, error
);
3066 return_nested_in (MonoClass
*klass
, char *nested
)
3069 char *s
= strchr (nested
, '/');
3070 gpointer iter
= NULL
;
3077 while ((found
= mono_class_get_nested_types (klass
, &iter
))) {
3078 if (strcmp (m_class_get_name (found
), nested
) == 0) {
3080 return return_nested_in (found
, s
);
3088 search_modules (MonoImage
*image
, const char *name_space
, const char *name
, MonoError
*error
)
3090 MonoTableInfo
*file_table
= &image
->tables
[MONO_TABLE_FILE
];
3091 MonoImage
*file_image
;
3098 * The EXPORTEDTYPES table only contains public types, so have to search the
3100 * Note: image->modules contains the contents of the MODULEREF table, while
3101 * the real module list is in the FILE table.
3103 for (i
= 0; i
< file_table
->rows
; i
++) {
3104 guint32 cols
[MONO_FILE_SIZE
];
3105 mono_metadata_decode_row (file_table
, i
, cols
, MONO_FILE_SIZE
);
3106 if (cols
[MONO_FILE_FLAGS
] == FILE_CONTAINS_NO_METADATA
)
3109 file_image
= mono_image_load_file_for_image_checked (image
, i
+ 1, error
);
3111 klass
= mono_class_from_name_checked (file_image
, name_space
, name
, error
);
3112 if (klass
|| !is_ok (error
))
3121 mono_class_from_name_checked_aux (MonoImage
*image
, const char* name_space
, const char *name
, GHashTable
* visited_images
, MonoError
*error
)
3123 GHashTable
*nspace_table
;
3124 MonoImage
*loaded_image
;
3133 // Checking visited images avoids stack overflows when cyclic references exist.
3134 if (g_hash_table_lookup (visited_images
, image
))
3137 g_hash_table_insert (visited_images
, image
, GUINT_TO_POINTER(1));
3139 if ((nested
= (char*)strchr (name
, '/'))) {
3140 int pos
= nested
- name
;
3141 int len
= strlen (name
);
3144 memcpy (buf
, name
, len
+ 1);
3146 nested
= buf
+ pos
+ 1;
3150 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
3151 if (get_class_from_name
&& image
->tables
[MONO_TABLE_EXPORTEDTYPE
].rows
== 0) {
3152 gboolean res
= get_class_from_name (image
, name_space
, name
, &klass
);
3155 klass
= search_modules (image
, name_space
, name
, error
);
3160 return klass
? return_nested_in (klass
, nested
) : NULL
;
3166 mono_image_init_name_cache (image
);
3167 mono_image_lock (image
);
3169 nspace_table
= (GHashTable
*)g_hash_table_lookup (image
->name_cache
, name_space
);
3172 token
= GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table
, name
));
3174 mono_image_unlock (image
);
3176 if (!token
&& image_is_dynamic (image
) && image
->modules
) {
3177 /* Search modules as well */
3178 for (i
= 0; i
< image
->module_count
; ++i
) {
3179 MonoImage
*module
= image
->modules
[i
];
3181 klass
= mono_class_from_name_checked (module
, name_space
, name
, error
);
3182 if (klass
|| !is_ok (error
))
3188 klass
= search_modules (image
, name_space
, name
, error
);
3189 if (klass
|| !is_ok (error
))
3194 if (mono_metadata_token_table (token
) == MONO_TABLE_EXPORTEDTYPE
) {
3195 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3196 guint32 cols
[MONO_EXP_TYPE_SIZE
];
3199 idx
= mono_metadata_token_index (token
);
3201 mono_metadata_decode_row (t
, idx
- 1, cols
, MONO_EXP_TYPE_SIZE
);
3203 impl
= cols
[MONO_EXP_TYPE_IMPLEMENTATION
];
3204 if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
) {
3205 loaded_image
= mono_assembly_load_module_checked (image
->assembly
, impl
>> MONO_IMPLEMENTATION_BITS
, error
);
3208 klass
= mono_class_from_name_checked_aux (loaded_image
, name_space
, name
, visited_images
, error
);
3210 return klass
? return_nested_in (klass
, nested
) : NULL
;
3212 } else if ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_ASSEMBLYREF
) {
3213 guint32 assembly_idx
;
3215 assembly_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
3217 mono_assembly_load_reference (image
, assembly_idx
- 1);
3218 g_assert (image
->references
[assembly_idx
- 1]);
3219 if (image
->references
[assembly_idx
- 1] == (gpointer
)-1)
3221 klass
= mono_class_from_name_checked_aux (image
->references
[assembly_idx
- 1]->image
, name_space
, name
, visited_images
, error
);
3223 return klass
? return_nested_in (klass
, nested
) : NULL
;
3226 g_assert_not_reached ();
3230 token
= MONO_TOKEN_TYPE_DEF
| token
;
3232 klass
= mono_class_get_checked (image
, token
, error
);
3234 return return_nested_in (klass
, nested
);
3239 * mono_class_from_name_checked:
3240 * \param image The MonoImage where the type is looked up in
3241 * \param name_space the type namespace
3242 * \param name the type short name.
3244 * Obtains a MonoClass with a given namespace and a given name which
3245 * is located in the given MonoImage.
3247 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
3248 * set if the class was not found or it will return NULL and set the error if there was a loading error.
3251 mono_class_from_name_checked (MonoImage
*image
, const char* name_space
, const char *name
, MonoError
*error
)
3254 GHashTable
*visited_images
;
3256 visited_images
= g_hash_table_new (g_direct_hash
, g_direct_equal
);
3258 klass
= mono_class_from_name_checked_aux (image
, name_space
, name
, visited_images
, error
);
3260 g_hash_table_destroy (visited_images
);
3266 * mono_class_from_name:
3267 * \param image The \c MonoImage where the type is looked up in
3268 * \param name_space the type namespace
3269 * \param name the type short name.
3271 * Obtains a \c MonoClass with a given namespace and a given name which
3272 * is located in the given \c MonoImage.
3274 * To reference nested classes, use the "/" character as a separator.
3275 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
3276 * inside \c Foo, like this: "class Foo { class Bar {} }".
3279 mono_class_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3282 MONO_ENTER_GC_UNSAFE
;
3285 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3286 mono_error_cleanup (error
); /* FIXME Don't swallow the error */
3287 MONO_EXIT_GC_UNSAFE
;
3292 * mono_class_load_from_name:
3293 * \param image The MonoImage where the type is looked up in
3294 * \param name_space the type namespace
3295 * \param name the type short name.
3297 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
3298 * This function should be used by the runtime for critical types to which there's no way to recover but crash
3299 * If they are missing. Thing of System.Object or System.String.
3302 mono_class_load_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3307 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3309 g_error ("Runtime critical type %s.%s not found", name_space
, name
);
3310 mono_error_assertf_ok (error
, "Could not load runtime critical type %s.%s", name_space
, name
);
3315 * mono_class_try_load_from_name:
3316 * \param image The MonoImage where the type is looked up in
3317 * \param name_space the type namespace
3318 * \param name the type short name.
3320 * This function tries to load a type, returning the class was found or NULL otherwise.
3321 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
3323 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
3324 * a type that we would otherwise assume to be available but was not due some error.
3328 mono_class_try_load_from_name (MonoImage
*image
, const char* name_space
, const char *name
)
3333 klass
= mono_class_from_name_checked (image
, name_space
, name
, error
);
3334 mono_error_assertf_ok (error
, "Could not load runtime critical type %s.%s", name_space
, name
);
3339 mono_interface_implements_interface (MonoClass
*interface_implementer
, MonoClass
*interface_implemented
)
3343 mono_class_setup_interfaces (interface_implementer
, error
);
3344 if (!is_ok (error
)) {
3345 mono_error_cleanup (error
);
3348 MonoClass
**klass_interfaces
= m_class_get_interfaces (interface_implementer
);
3349 for (i
= 0; i
< m_class_get_interface_count (interface_implementer
); i
++) {
3350 MonoClass
*ic
= klass_interfaces
[i
];
3351 if (mono_class_is_ginst (ic
))
3352 ic
= mono_class_get_generic_type_definition (ic
);
3353 if (ic
== interface_implemented
)
3360 mono_class_is_subclass_of_internal (MonoClass
*klass
, MonoClass
*klassc
,
3361 gboolean check_interfaces
)
3363 MONO_REQ_GC_UNSAFE_MODE
;
3364 /* FIXME test for interfaces with variant generic arguments */
3365 mono_class_init_internal (klass
);
3366 mono_class_init_internal (klassc
);
3368 if (check_interfaces
&& MONO_CLASS_IS_INTERFACE_INTERNAL (klassc
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3369 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass
, m_class_get_interface_id (klassc
)))
3371 } else if (check_interfaces
&& MONO_CLASS_IS_INTERFACE_INTERNAL (klassc
) && MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3374 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
3375 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
3376 MonoClass
*ic
= klass_interfaces
[i
];
3381 if (!MONO_CLASS_IS_INTERFACE_INTERNAL (klass
) && mono_class_has_parent (klass
, klassc
))
3386 * MS.NET thinks interfaces are a subclass of Object, so we think it as
3389 if (klassc
== mono_defaults
.object_class
)
3396 mono_type_is_generic_argument (MonoType
*type
)
3398 return type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
;
3402 mono_class_has_variant_generic_params (MonoClass
*klass
)
3405 MonoGenericContainer
*container
;
3407 if (!mono_class_is_ginst (klass
))
3410 container
= mono_class_get_generic_container (mono_class_get_generic_class (klass
)->container_class
);
3412 for (i
= 0; i
< container
->type_argc
; ++i
)
3413 if (mono_generic_container_get_param_info (container
, i
)->flags
& (MONO_GEN_PARAM_VARIANT
|MONO_GEN_PARAM_COVARIANT
))
3420 mono_gparam_is_reference_conversible (MonoClass
*target
, MonoClass
*candidate
, gboolean check_for_reference_conv
)
3422 if (target
== candidate
)
3425 if (check_for_reference_conv
&&
3426 mono_type_is_generic_argument (m_class_get_byval_arg (target
)) &&
3427 mono_type_is_generic_argument (m_class_get_byval_arg (candidate
))) {
3428 MonoGenericParam
*gparam
= m_class_get_byval_arg (candidate
)->data
.generic_param
;
3429 MonoGenericParamInfo
*pinfo
= mono_generic_param_info (gparam
);
3431 if (!pinfo
|| (pinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0)
3434 if (!mono_class_is_assignable_from_internal (target
, candidate
))
3440 * @container the generic container from the GTD
3441 * @klass: the class to be assigned to
3442 * @oklass: the source class
3444 * Both @klass and @oklass must be instances of the same generic interface.
3446 * Returns: TRUE if @klass can be assigned to a @klass variable
3449 mono_class_is_variant_compatible (MonoClass
*klass
, MonoClass
*oklass
, gboolean check_for_reference_conv
)
3452 MonoType
**klass_argv
, **oklass_argv
;
3453 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3454 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3456 if (klass
== oklass
)
3459 /*Viable candidates are instances of the same generic interface*/
3460 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3463 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3464 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3466 for (j
= 0; j
< container
->type_argc
; ++j
) {
3467 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3468 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3470 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
) || (m_class_is_valuetype (param1_class
) && param1_class
!= param2_class
))
3474 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3475 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3477 if (param1_class
!= param2_class
) {
3478 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3479 if (!mono_gparam_is_reference_conversible (param1_class
, param2_class
, check_for_reference_conv
))
3481 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3482 if (!mono_gparam_is_reference_conversible (param2_class
, param1_class
, check_for_reference_conv
))
3492 mono_gparam_is_assignable_from (MonoClass
*target
, MonoClass
*candidate
)
3494 MonoGenericParam
*gparam
, *ogparam
;
3495 MonoGenericParamInfo
*tinfo
, *cinfo
;
3496 MonoClass
**candidate_class
;
3497 gboolean class_constraint_satisfied
, valuetype_constraint_satisfied
;
3500 if (target
== candidate
)
3502 MonoType
*target_byval_arg
= m_class_get_byval_arg (target
);
3503 MonoType
*candidate_byval_arg
= m_class_get_byval_arg (candidate
);
3504 if (target_byval_arg
->type
!= candidate_byval_arg
->type
)
3507 gparam
= target_byval_arg
->data
.generic_param
;
3508 ogparam
= candidate_byval_arg
->data
.generic_param
;
3509 tinfo
= mono_generic_param_info (gparam
);
3510 cinfo
= mono_generic_param_info (ogparam
);
3512 class_constraint_satisfied
= FALSE
;
3513 valuetype_constraint_satisfied
= FALSE
;
3515 /*candidate must have a super set of target's special constraints*/
3516 tmask
= tinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3517 cmask
= cinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3519 if (cinfo
->constraints
) {
3520 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3521 MonoClass
*cc
= *candidate_class
;
3522 MonoType
*cc_byval_arg
= m_class_get_byval_arg (cc
);
3524 if (mono_type_is_reference (cc_byval_arg
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc
))
3525 class_constraint_satisfied
= TRUE
;
3526 else if (!mono_type_is_reference (cc_byval_arg
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (cc
))
3527 valuetype_constraint_satisfied
= TRUE
;
3530 class_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) != 0;
3531 valuetype_constraint_satisfied
|= (cmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0;
3533 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) && !class_constraint_satisfied
)
3535 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) && !valuetype_constraint_satisfied
)
3537 if ((tmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) && !((cmask
& GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT
) ||
3538 valuetype_constraint_satisfied
)) {
3543 /*candidate type constraints must be a superset of target's*/
3544 if (tinfo
->constraints
) {
3545 MonoClass
**target_class
;
3546 for (target_class
= tinfo
->constraints
; *target_class
; ++target_class
) {
3547 MonoClass
*tc
= *target_class
;
3548 MonoType
*tc_byval_arg
= m_class_get_byval_arg (tc
);
3551 * A constraint from @target might inflate into @candidate itself and in that case we don't need
3552 * check it's constraints since it satisfy the constraint by itself.
3554 if (mono_metadata_type_equal (tc_byval_arg
, candidate_byval_arg
))
3557 if (!cinfo
->constraints
)
3560 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3561 MonoClass
*cc
= *candidate_class
;
3563 if (mono_class_is_assignable_from_internal (tc
, cc
))
3567 * This happens when we have the following:
3569 * Bar<K> where K : IFace
3570 * Foo<T, U> where T : U where U : IFace
3572 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
3575 if (mono_type_is_generic_argument (m_class_get_byval_arg (cc
))) {
3576 if (mono_gparam_is_assignable_from (target
, cc
))
3580 if (!*candidate_class
)
3585 /*candidate itself must have a constraint that satisfy target*/
3586 if (cinfo
->constraints
) {
3587 for (candidate_class
= cinfo
->constraints
; *candidate_class
; ++candidate_class
) {
3588 MonoClass
*cc
= *candidate_class
;
3589 if (mono_class_is_assignable_from_internal (target
, cc
))
3597 * mono_class_is_assignable_from_internal:
3598 * \param klass the class to be assigned to
3599 * \param oklass the source class
3601 * \returns TRUE if an instance of class \p oklass can be assigned to an
3602 * instance of class \p klass
3605 mono_class_is_assignable_from_internal (MonoClass
*klass
, MonoClass
*oklass
)
3607 gboolean result
= FALSE
;
3609 mono_class_is_assignable_from_checked (klass
, oklass
, &result
, error
);
3610 mono_error_cleanup (error
);
3615 * mono_class_is_assignable_from:
3616 * \param klass the class to be assigned to
3617 * \param oklass the source class
3619 * \returns TRUE if an instance of class \p oklass can be assigned to an
3620 * instance of class \p klass
3623 mono_class_is_assignable_from (MonoClass
*klass
, MonoClass
*oklass
)
3626 MONO_ENTER_GC_UNSAFE
;
3627 result
= mono_class_is_assignable_from_internal (klass
, oklass
);
3628 MONO_EXIT_GC_UNSAFE
;
3633 * mono_class_is_assignable_from_checked:
3634 * \param klass the class to be assigned to
3635 * \param oklass the source class
3636 * \param result set if there was no error
3637 * \param error set if there was an error
3639 * Sets \p result to TRUE if an instance of class \p oklass can be assigned to
3640 * an instance of class \p klass or FALSE if it cannot. On error, no \p error
3641 * is set and \p result is not valid.
3644 mono_class_is_assignable_from_checked (MonoClass
*klass
, MonoClass
*oklass
, gboolean
*result
, MonoError
*error
)
3647 if (klass
== oklass
) {
3652 MONO_REQ_GC_UNSAFE_MODE
;
3653 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
3654 if (!m_class_is_inited (klass
))
3655 mono_class_init_internal (klass
);
3657 if (!m_class_is_inited (oklass
))
3658 mono_class_init_internal (oklass
);
3660 if (mono_class_has_failure (klass
)) {
3661 mono_error_set_for_class_failure (error
, klass
);
3666 if (mono_class_has_failure (oklass
)) {
3667 mono_error_set_for_class_failure (error
, oklass
);
3672 MonoType
*klass_byval_arg
= m_class_get_byval_arg (klass
);
3673 MonoType
*oklass_byval_arg
= m_class_get_byval_arg (oklass
);
3675 if (mono_type_is_generic_argument (klass_byval_arg
)) {
3676 if (!mono_type_is_generic_argument (oklass_byval_arg
)) {
3680 *result
= mono_gparam_is_assignable_from (klass
, oklass
);
3684 /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
3685 * has a constraint which is a class type:
3688 * class G<T1, T2> where T1 : T2 where T2 : Foo { }
3690 * In this case, Foo is assignable from T1.
3692 if (mono_type_is_generic_argument (oklass_byval_arg
)) {
3693 MonoGenericParam
*gparam
= oklass_byval_arg
->data
.generic_param
;
3694 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
3698 for (i
= 0; constraints
[i
]; ++i
) {
3699 if (mono_class_is_assignable_from_internal (klass
, constraints
[i
])) {
3706 *result
= mono_class_has_parent (oklass
, klass
);
3710 if (MONO_CLASS_IS_INTERFACE_INTERNAL (klass
)) {
3712 /* interface_offsets might not be set for dynamic classes */
3713 if (mono_class_get_ref_info_handle (oklass
) && !m_class_get_interface_bitmap (oklass
)) {
3715 * oklass might be a generic type parameter but they have
3716 * interface_offsets set.
3718 gboolean assign_result
= mono_reflection_call_is_assignable_to (oklass
, klass
, error
);
3719 return_if_nok (error
);
3720 *result
= assign_result
;
3723 if (!m_class_get_interface_bitmap (oklass
)) {
3724 /* Happens with generic instances of not-yet created dynamic types */
3728 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass
, m_class_get_interface_id (klass
))) {
3733 if (m_class_is_array_special_interface (klass
) && m_class_get_rank (oklass
) == 1) {
3734 if (mono_class_is_gtd (klass
)) {
3735 /* klass is an array special gtd like
3736 * IList`1<>, and oklass is X[] for some X.
3737 * Moreover we know that X isn't !0 (the gparam
3738 * of IList`1) because in that case we would
3739 * have returned TRUE for
3740 * MONO_CLASS_IMPLEMENTS_INTERFACE, above.
3745 // FIXME: IEnumerator`1 should not be an array special interface.
3746 // The correct fix is to make
3747 // ((IEnumerable<U>) (new T[] {...})).GetEnumerator()
3748 // return an IEnumerator<U> (like .NET does) instead of IEnumerator<T>
3749 // and to stop marking IEnumerable`1 as an array_special_interface.
3750 if (mono_class_get_generic_type_definition (klass
) == mono_defaults
.generic_ienumerator_class
) {
3755 //XXX we could offset this by having the cast target computed at JIT time
3756 //XXX we could go even further and emit a wrapper that would do the extra type check
3757 MonoClass
*iface_klass
= mono_class_from_mono_type_internal (mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0]);
3758 MonoClass
*obj_klass
= m_class_get_cast_class (oklass
); //This gets us the cast class of element type of the array
3760 // 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
3761 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
3762 if (!mono_class_is_nullable (iface_klass
)) {
3763 if (m_class_is_valuetype (iface_klass
))
3764 iface_klass
= m_class_get_cast_class (iface_klass
);
3766 //array covariant casts only operates on scalar to scalar
3767 //This is so int[] can't be casted to IComparable<int>[]
3768 if (!(m_class_is_valuetype (obj_klass
) && !m_class_is_valuetype (iface_klass
)) && mono_class_is_assignable_from_internal (iface_klass
, obj_klass
)) {
3775 if (mono_class_has_variant_generic_params (klass
)) {
3777 mono_class_setup_interfaces (oklass
, error
);
3778 return_if_nok (error
);
3780 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
3781 for (i
= 0; i
< m_class_get_interface_offsets_count (oklass
); ++i
) {
3782 MonoClass
*iface
= m_class_get_interfaces_packed (oklass
) [i
];
3784 if (mono_class_is_variant_compatible (klass
, iface
, FALSE
)) {
3793 } else if (m_class_is_delegate (klass
)) {
3794 if (mono_class_has_variant_generic_params (klass
) && mono_class_is_variant_compatible (klass
, oklass
, FALSE
)) {
3798 } else if (m_class_get_rank (klass
)) {
3799 MonoClass
*eclass
, *eoclass
;
3801 if (m_class_get_rank (oklass
) != m_class_get_rank (klass
)) {
3806 /* vectors vs. one dimensional arrays */
3807 if (oklass_byval_arg
->type
!= klass_byval_arg
->type
) {
3812 eclass
= m_class_get_cast_class (klass
);
3813 eoclass
= m_class_get_cast_class (oklass
);
3816 * a is b does not imply a[] is b[] when a is a valuetype, and
3817 * b is a reference type.
3820 if (m_class_is_valuetype (eoclass
)) {
3821 if ((eclass
== mono_defaults
.enum_class
) ||
3822 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
3823 (!m_class_is_valuetype (eclass
))) {
3830 * a is b does not imply a[] is b[] in the case where b is an interface and
3831 * a is a generic parameter, unless a has an additional class constraint.
3835 * class G<T> where T : I {}
3836 * class H<U> where U : class, I {}
3838 * public static void Main() {
3839 * var t = typeof(G<>).GetTypeInfo().GenericTypeParameters[0].MakeArrayType();
3840 * var i = typeof(I).MakeArrayType();
3841 * var u = typeof(H<>).GetTypeInfo().GenericTypeParameters[0].MakeArrayType();
3842 * Console.WriteLine("I[] assignable from T[] ? {0}", i.IsAssignableFrom(t));
3843 * Console.WriteLine("I[] assignable from U[] ? {0}", i.IsAssignableFrom(u));
3847 * This should print:
3848 * I[] assignable from T[] ? False
3849 * I[] assignable from U[] ? True
3852 if (MONO_CLASS_IS_INTERFACE_INTERNAL (eclass
)) {
3853 MonoType
*eoclass_byval_arg
= m_class_get_byval_arg (eoclass
);
3854 if (mono_type_is_generic_argument (eoclass_byval_arg
)) {
3855 MonoGenericParam
*eoparam
= eoclass_byval_arg
->data
.generic_param
;
3856 MonoGenericParamInfo
*eoinfo
= mono_generic_param_info (eoparam
);
3857 int eomask
= eoinfo
->flags
& GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK
;
3858 // check for class constraint
3859 if ((eomask
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0) {
3866 if (mono_class_is_nullable (eclass
) ^ mono_class_is_nullable (eoclass
)) {
3871 mono_class_is_assignable_from_checked (eclass
, eoclass
, result
, error
);
3873 } else if (mono_class_is_nullable (klass
)) {
3874 if (mono_class_is_nullable (oklass
))
3875 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), m_class_get_cast_class (oklass
), result
, error
);
3877 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), oklass
, result
, error
);
3879 } else if (klass
== mono_defaults
.object_class
) {
3880 if (m_class_get_class_kind (oklass
) == MONO_CLASS_POINTER
)
3887 *result
= mono_class_has_parent (oklass
, klass
);
3890 /*Check if @oklass is variant compatible with @klass.*/
3892 mono_class_is_variant_compatible_slow (MonoClass
*klass
, MonoClass
*oklass
)
3895 MonoType
**klass_argv
, **oklass_argv
;
3896 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3897 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3899 /*Viable candidates are instances of the same generic interface*/
3900 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3903 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3904 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3906 for (j
= 0; j
< container
->type_argc
; ++j
) {
3907 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3908 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3910 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
))
3914 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3915 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3917 if (param1_class
!= param2_class
) {
3918 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3919 if (!mono_class_is_assignable_from_slow (param1_class
, param2_class
))
3921 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3922 if (!mono_class_is_assignable_from_slow (param2_class
, param1_class
))
3930 /*Check if @candidate implements the interface @target*/
3932 mono_class_implement_interface_slow (MonoClass
*target
, MonoClass
*candidate
)
3936 gboolean is_variant
= mono_class_has_variant_generic_params (target
);
3938 if (is_variant
&& MONO_CLASS_IS_INTERFACE_INTERNAL (candidate
)) {
3939 if (mono_class_is_variant_compatible_slow (target
, candidate
))
3944 if (candidate
== target
)
3947 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
3948 if (image_is_dynamic (m_class_get_image (candidate
)) && !m_class_was_typebuilder (candidate
)) {
3949 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info_raw (candidate
); /* FIXME use handles */
3951 if (tb
&& tb
->interfaces
) {
3952 for (j
= mono_array_length_internal (tb
->interfaces
) - 1; j
>= 0; --j
) {
3953 MonoReflectionType
*iface
= mono_array_get_internal (tb
->interfaces
, MonoReflectionType
*, j
);
3954 MonoClass
*iface_class
;
3956 /* we can't realize the type here since it can do pretty much anything. */
3959 iface_class
= mono_class_from_mono_type_internal (iface
->type
);
3960 if (iface_class
== target
)
3962 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, iface_class
))
3964 if (mono_class_implement_interface_slow (target
, iface_class
))
3969 /*setup_interfaces don't mono_class_init_internal anything*/
3970 /*FIXME this doesn't handle primitive type arrays.
3971 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
3972 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
3974 mono_class_setup_interfaces (candidate
, error
);
3975 if (!mono_error_ok (error
)) {
3976 mono_error_cleanup (error
);
3980 int candidate_interface_count
= m_class_get_interface_count (candidate
);
3981 MonoClass
**candidate_interfaces
= m_class_get_interfaces (candidate
);
3982 for (i
= 0; i
< candidate_interface_count
; ++i
) {
3983 if (candidate_interfaces
[i
] == target
)
3986 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, candidate_interfaces
[i
]))
3989 if (mono_class_implement_interface_slow (target
, candidate_interfaces
[i
]))
3993 candidate
= m_class_get_parent (candidate
);
3994 } while (candidate
);
4000 * Check if @oklass can be assigned to @klass.
4001 * This function does the same as mono_class_is_assignable_from_internal but is safe to be used from mono_class_init_internal context.
4004 mono_class_is_assignable_from_slow (MonoClass
*target
, MonoClass
*candidate
)
4006 if (candidate
== target
)
4008 if (target
== mono_defaults
.object_class
)
4011 if (mono_class_has_parent (candidate
, target
))
4014 /*If target is not an interface there is no need to check them.*/
4015 if (MONO_CLASS_IS_INTERFACE_INTERNAL (target
))
4016 return mono_class_implement_interface_slow (target
, candidate
);
4018 if (m_class_is_delegate (target
) && mono_class_has_variant_generic_params (target
))
4019 return mono_class_is_variant_compatible (target
, candidate
, FALSE
);
4021 if (m_class_get_rank (target
)) {
4022 MonoClass
*eclass
, *eoclass
;
4024 if (m_class_get_rank (target
) != m_class_get_rank (candidate
))
4027 /* vectors vs. one dimensional arrays */
4028 if (m_class_get_byval_arg (target
)->type
!= m_class_get_byval_arg (candidate
)->type
)
4031 eclass
= m_class_get_cast_class (target
);
4032 eoclass
= m_class_get_cast_class (candidate
);
4035 * a is b does not imply a[] is b[] when a is a valuetype, and
4036 * b is a reference type.
4039 if (m_class_is_valuetype (eoclass
)) {
4040 if ((eclass
== mono_defaults
.enum_class
) ||
4041 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
4042 (eclass
== mono_defaults
.object_class
))
4046 return mono_class_is_assignable_from_slow (eclass
, eoclass
);
4048 /*FIXME properly handle nullables */
4049 /*FIXME properly handle (M)VAR */
4054 * mono_generic_param_get_base_type:
4056 * Return the base type of the given generic parameter from its constraints.
4058 * Could be another generic parameter, or it could be Object or ValueType.
4061 mono_generic_param_get_base_type (MonoClass
*klass
)
4063 MonoType
*type
= m_class_get_byval_arg (klass
);
4064 g_assert (mono_type_is_generic_argument (type
));
4066 MonoGenericParam
*gparam
= type
->data
.generic_param
;
4068 g_assert (gparam
->owner
&& !gparam
->owner
->is_anonymous
);
4070 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
4072 MonoClass
*base_class
= mono_defaults
.object_class
;
4076 for (i
= 0; constraints
[i
]; ++i
) {
4077 MonoClass
*constraint
= constraints
[i
];
4079 if (MONO_CLASS_IS_INTERFACE_INTERNAL (constraint
))
4082 MonoType
*constraint_type
= m_class_get_byval_arg (constraint
);
4083 if (mono_type_is_generic_argument (constraint_type
)) {
4084 MonoGenericParam
*constraint_param
= constraint_type
->data
.generic_param
;
4085 MonoGenericParamInfo
*constraint_info
= mono_generic_param_info (constraint_param
);
4086 if ((constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0 &&
4087 (constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) == 0)
4091 base_class
= constraint
;
4096 if (base_class
== mono_defaults
.object_class
)
4098 MonoGenericParamInfo
*gparam_info
= mono_generic_param_info (gparam
);
4099 if ((gparam_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0) {
4100 base_class
= mono_class_get_valuetype_class ();
4108 * mono_class_get_cctor:
4109 * \param klass A MonoClass pointer
4111 * \returns The static constructor of \p klass if it exists, NULL otherwise.
4114 mono_class_get_cctor (MonoClass
*klass
)
4116 MonoMethod
*result
= NULL
;
4118 MonoCachedClassInfo cached_info
;
4120 if (image_is_dynamic (m_class_get_image (klass
))) {
4122 * has_cctor is not set for these classes because mono_class_init_internal () is
4125 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
4126 mono_error_assert_msg_ok (error
, "Could not lookup class cctor in dynamic image");
4130 mono_class_init_internal (klass
);
4132 if (!m_class_has_cctor (klass
))
4135 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
4136 result
= mono_class_get_inflated_method (klass
, mono_class_get_cctor (mono_class_get_generic_class (klass
)->container_class
), error
);
4137 mono_error_assert_msg_ok (error
, "Could not lookup inflated class cctor"); /* FIXME do proper error handling */
4141 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
4142 result
= mono_get_method_checked (m_class_get_image (klass
), cached_info
.cctor_token
, klass
, NULL
, error
);
4143 mono_error_assert_msg_ok (error
, "Could not lookup class cctor from cached metadata");
4147 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
4148 mono_error_assert_msg_ok (error
, "Could not lookup class cctor");
4153 * mono_class_get_finalizer:
4154 * \param klass: The MonoClass pointer
4156 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
4159 mono_class_get_finalizer (MonoClass
*klass
)
4161 MonoCachedClassInfo cached_info
;
4163 if (!m_class_is_inited (klass
))
4164 mono_class_init_internal (klass
);
4165 if (!mono_class_has_finalizer (klass
))
4168 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
4170 MonoMethod
*result
= mono_get_method_checked (cached_info
.finalize_image
, cached_info
.finalize_token
, NULL
, NULL
, error
);
4171 mono_error_assert_msg_ok (error
, "Could not lookup finalizer from cached metadata");
4174 mono_class_setup_vtable (klass
);
4175 return m_class_get_vtable (klass
) [mono_class_get_object_finalize_slot ()];
4180 * mono_class_needs_cctor_run:
4181 * \param klass the MonoClass pointer
4182 * \param caller a MonoMethod describing the caller
4184 * Determines whenever the class has a static constructor and whenever it
4185 * needs to be called when executing CALLER.
4188 mono_class_needs_cctor_run (MonoClass
*klass
, MonoMethod
*caller
)
4192 method
= mono_class_get_cctor (klass
);
4194 return (method
== caller
) ? FALSE
: TRUE
;
4200 * mono_class_array_element_size:
4203 * \returns The number of bytes an element of type \p klass uses when stored into an array.
4206 mono_class_array_element_size (MonoClass
*klass
)
4208 MonoType
*type
= m_class_get_byval_arg (klass
);
4211 switch (type
->type
) {
4214 case MONO_TYPE_BOOLEAN
:
4218 case MONO_TYPE_CHAR
:
4227 case MONO_TYPE_CLASS
:
4228 case MONO_TYPE_STRING
:
4229 case MONO_TYPE_OBJECT
:
4230 case MONO_TYPE_SZARRAY
:
4231 case MONO_TYPE_ARRAY
:
4232 return TARGET_SIZEOF_VOID_P
;
4237 case MONO_TYPE_VALUETYPE
:
4238 if (m_class_is_enumtype (type
->data
.klass
)) {
4239 type
= mono_class_enum_basetype_internal (type
->data
.klass
);
4240 klass
= m_class_get_element_class (klass
);
4243 return mono_class_value_size (klass
, NULL
);
4244 case MONO_TYPE_GENERICINST
:
4245 type
= m_class_get_byval_arg (type
->data
.generic_class
->container_class
);
4248 case MONO_TYPE_MVAR
: {
4251 return mono_type_size (type
, &align
);
4253 case MONO_TYPE_VOID
:
4257 g_error ("unknown type 0x%02x in mono_class_array_element_size", type
->type
);
4263 * mono_array_element_size:
4264 * \param ac pointer to a \c MonoArrayClass
4266 * \returns The size of single array element.
4268 * LOCKING: Acquires the loader lock.
4271 mono_array_element_size (MonoClass
*ac
)
4273 g_assert (m_class_get_rank (ac
));
4274 if (G_UNLIKELY (!m_class_is_size_inited (ac
))) {
4275 mono_class_setup_fields (ac
);
4277 return m_class_get_sizes (ac
).element_size
;
4284 mono_ldtoken (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4285 MonoGenericContext
*context
)
4288 gpointer res
= mono_ldtoken_checked (image
, token
, handle_class
, context
, error
);
4289 mono_error_assert_ok (error
);
4294 mono_ldtoken_checked (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4295 MonoGenericContext
*context
, MonoError
*error
)
4299 if (image_is_dynamic (image
)) {
4300 MonoClass
*tmp_handle_class
;
4301 gpointer obj
= mono_lookup_dynamic_token_class (image
, token
, TRUE
, &tmp_handle_class
, context
, error
);
4303 mono_error_assert_ok (error
);
4304 g_assert (tmp_handle_class
);
4306 *handle_class
= tmp_handle_class
;
4308 if (tmp_handle_class
== mono_defaults
.typehandle_class
)
4309 return m_class_get_byval_arg ((MonoClass
*)obj
);
4314 switch (token
& 0xff000000) {
4315 case MONO_TOKEN_TYPE_DEF
:
4316 case MONO_TOKEN_TYPE_REF
:
4317 case MONO_TOKEN_TYPE_SPEC
: {
4320 *handle_class
= mono_defaults
.typehandle_class
;
4321 type
= mono_type_get_checked (image
, token
, context
, error
);
4325 mono_class_init_internal (mono_class_from_mono_type_internal (type
));
4326 /* We return a MonoType* as handle */
4329 case MONO_TOKEN_FIELD_DEF
: {
4331 guint32 type
= mono_metadata_typedef_from_field (image
, mono_metadata_token_index (token
));
4333 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4337 *handle_class
= mono_defaults
.fieldhandle_class
;
4338 klass
= mono_class_get_and_inflate_typespec_checked (image
, MONO_TOKEN_TYPE_DEF
| type
, context
, error
);
4342 mono_class_init_internal (klass
);
4343 return mono_class_get_field (klass
, token
);
4345 case MONO_TOKEN_METHOD_DEF
:
4346 case MONO_TOKEN_METHOD_SPEC
: {
4348 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4350 *handle_class
= mono_defaults
.methodhandle_class
;
4356 case MONO_TOKEN_MEMBER_REF
: {
4357 guint32 cols
[MONO_MEMBERREF_SIZE
];
4359 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
4360 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
4361 mono_metadata_decode_blob_size (sig
, &sig
);
4362 if (*sig
== 0x6) { /* it's a field */
4364 MonoClassField
*field
;
4365 field
= mono_field_from_token_checked (image
, token
, &klass
, context
, error
);
4367 *handle_class
= mono_defaults
.fieldhandle_class
;
4371 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4373 *handle_class
= mono_defaults
.methodhandle_class
;
4378 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4384 mono_lookup_dynamic_token (MonoImage
*image
, guint32 token
, MonoGenericContext
*context
, MonoError
*error
)
4386 MonoClass
*handle_class
;
4388 return mono_reflection_lookup_dynamic_token (image
, token
, TRUE
, &handle_class
, context
, error
);
4392 mono_lookup_dynamic_token_class (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
, MonoError
*error
)
4394 return mono_reflection_lookup_dynamic_token (image
, token
, valid_token
, handle_class
, context
, error
);
4397 static MonoGetCachedClassInfo get_cached_class_info
= NULL
;
4400 mono_install_get_cached_class_info (MonoGetCachedClassInfo func
)
4402 get_cached_class_info
= func
;
4406 mono_class_get_cached_class_info (MonoClass
*klass
, MonoCachedClassInfo
*res
)
4408 if (!get_cached_class_info
)
4411 return get_cached_class_info (klass
, res
);
4415 mono_install_get_class_from_name (MonoGetClassFromName func
)
4417 get_class_from_name
= func
;
4421 * mono_class_get_image:
4423 * Use this method to get the \c MonoImage* where this class came from.
4425 * \returns The image where this class is defined.
4428 mono_class_get_image (MonoClass
*klass
)
4430 return m_class_get_image (klass
);
4434 * mono_class_get_element_class:
4435 * \param klass the \c MonoClass to act on
4437 * Use this function to get the element class of an array.
4439 * \returns The element class of an array.
4442 mono_class_get_element_class (MonoClass
*klass
)
4445 MONO_ENTER_GC_UNSAFE
;
4446 result
= m_class_get_element_class (klass
);
4447 MONO_EXIT_GC_UNSAFE
;
4452 * mono_class_is_valuetype:
4453 * \param klass the \c MonoClass to act on
4455 * Use this method to determine if the provided \c MonoClass* represents a value type,
4456 * or a reference type.
4458 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
4461 mono_class_is_valuetype (MonoClass
*klass
)
4464 MONO_ENTER_GC_UNSAFE
;
4465 result
= m_class_is_valuetype (klass
);
4466 MONO_EXIT_GC_UNSAFE
;
4471 * mono_class_is_enum:
4472 * \param klass the \c MonoClass to act on
4474 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
4476 * \returns TRUE if the \c MonoClass represents an enumeration.
4479 mono_class_is_enum (MonoClass
*klass
)
4482 MONO_ENTER_GC_UNSAFE
;
4483 result
= m_class_is_enumtype (klass
);
4484 MONO_EXIT_GC_UNSAFE
;
4489 * mono_class_enum_basetype_internal:
4490 * \param klass the \c MonoClass to act on
4492 * Use this function to get the underlying type for an enumeration value.
4494 * \returns The underlying type representation for an enumeration.
4497 mono_class_enum_basetype_internal (MonoClass
*klass
)
4499 if (m_class_get_element_class (klass
) == klass
)
4500 /* SRE or broken types */
4502 return m_class_get_byval_arg (m_class_get_element_class (klass
));
4506 * mono_class_enum_basetype:
4507 * \param klass the \c MonoClass to act on
4509 * Use this function to get the underlying type for an enumeration value.
4511 * \returns The underlying type representation for an enumeration.
4514 mono_class_enum_basetype (MonoClass
*klass
)
4517 MONO_ENTER_GC_UNSAFE
;
4518 res
= mono_class_enum_basetype_internal (klass
);
4519 MONO_EXIT_GC_UNSAFE
;
4524 * mono_class_get_parent
4525 * \param klass the \c MonoClass to act on
4527 * \returns The parent class for this class.
4530 mono_class_get_parent (MonoClass
*klass
)
4533 MONO_ENTER_GC_UNSAFE
;
4534 result
= m_class_get_parent (klass
);
4535 MONO_EXIT_GC_UNSAFE
;
4540 * mono_class_get_nesting_type:
4541 * \param klass the \c MonoClass to act on
4543 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
4545 * If the return is NULL, this indicates that this class is not nested.
4547 * \returns The container type where this type is nested or NULL if this type is not a nested type.
4550 mono_class_get_nesting_type (MonoClass
*klass
)
4552 return m_class_get_nested_in (klass
);
4556 * mono_class_get_rank:
4557 * \param klass the MonoClass to act on
4559 * \returns The rank for the array (the number of dimensions).
4562 mono_class_get_rank (MonoClass
*klass
)
4564 return m_class_get_rank (klass
);
4568 * mono_class_get_name
4569 * \param klass the \c MonoClass to act on
4571 * \returns The name of the class.
4574 mono_class_get_name (MonoClass
*klass
)
4577 MONO_ENTER_GC_UNSAFE
;
4578 result
= m_class_get_name (klass
);
4579 MONO_EXIT_GC_UNSAFE
;
4584 * mono_class_get_namespace:
4585 * \param klass the \c MonoClass to act on
4587 * \returns The namespace of the class.
4590 mono_class_get_namespace (MonoClass
*klass
)
4593 MONO_ENTER_GC_UNSAFE
;
4594 result
= m_class_get_name_space (klass
);
4595 MONO_EXIT_GC_UNSAFE
;
4600 * mono_class_get_type:
4601 * \param klass the \c MonoClass to act on
4603 * This method returns the internal \c MonoType representation for the class.
4605 * \returns The \c MonoType from the class.
4608 mono_class_get_type (MonoClass
*klass
)
4610 return m_class_get_byval_arg (klass
);
4614 * mono_class_get_type_token:
4615 * \param klass the \c MonoClass to act on
4617 * This method returns type token for the class.
4619 * \returns The type token for the class.
4622 mono_class_get_type_token (MonoClass
*klass
)
4624 return m_class_get_type_token (klass
);
4628 * mono_class_get_byref_type:
4629 * \param klass the \c MonoClass to act on
4634 mono_class_get_byref_type (MonoClass
*klass
)
4636 return m_class_get_this_arg (klass
);
4640 * mono_class_num_fields:
4641 * \param klass the \c MonoClass to act on
4643 * \returns The number of static and instance fields in the class.
4646 mono_class_num_fields (MonoClass
*klass
)
4648 return mono_class_get_field_count (klass
);
4652 * mono_class_num_methods:
4653 * \param klass the \c MonoClass to act on
4655 * \returns The number of methods in the class.
4658 mono_class_num_methods (MonoClass
*klass
)
4660 return mono_class_get_method_count (klass
);
4664 * mono_class_num_properties
4665 * \param klass the \c MonoClass to act on
4667 * \returns The number of properties in the class.
4670 mono_class_num_properties (MonoClass
*klass
)
4672 mono_class_setup_properties (klass
);
4674 return mono_class_get_property_info (klass
)->count
;
4678 * mono_class_num_events:
4679 * \param klass the \c MonoClass to act on
4681 * \returns The number of events in the class.
4684 mono_class_num_events (MonoClass
*klass
)
4686 mono_class_setup_events (klass
);
4688 return mono_class_get_event_info (klass
)->count
;
4692 * mono_class_get_fields:
4693 * \param klass the \c MonoClass to act on
4695 * This routine is an iterator routine for retrieving the fields in a class.
4697 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4698 * iterate over all of the elements. When no more values are
4699 * available, the return value is NULL.
4701 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
4704 mono_class_get_fields (MonoClass
* klass
, gpointer
*iter
)
4706 MonoClassField
*result
;
4707 MONO_ENTER_GC_UNSAFE
;
4708 result
= mono_class_get_fields_internal (klass
, iter
);
4709 MONO_EXIT_GC_UNSAFE
;
4714 mono_class_get_fields_internal (MonoClass
*klass
, gpointer
*iter
)
4716 MonoClassField
* field
;
4720 mono_class_setup_fields (klass
);
4721 if (mono_class_has_failure (klass
))
4723 /* start from the first */
4724 if (mono_class_get_field_count (klass
)) {
4725 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
4726 *iter
= &klass_fields
[0];
4727 return &klass_fields
[0];
4733 field
= (MonoClassField
*)*iter
;
4735 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
4743 * mono_class_get_methods:
4744 * \param klass the \c MonoClass to act on
4746 * This routine is an iterator routine for retrieving the fields in a class.
4748 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4749 * iterate over all of the elements. When no more values are
4750 * available, the return value is NULL.
4752 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
4755 mono_class_get_methods (MonoClass
* klass
, gpointer
*iter
)
4757 MonoMethod
** method
;
4761 mono_class_setup_methods (klass
);
4763 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
4765 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
4766 * FIXME we should better report this error to the caller
4770 /* start from the first */
4771 if (mono_class_get_method_count (klass
)) {
4772 *iter
= &klass_methods
[0];
4773 return klass_methods
[0];
4779 method
= (MonoMethod
**)*iter
;
4781 if (method
< &m_class_get_methods (klass
) [mono_class_get_method_count (klass
)]) {
4789 * mono_class_get_properties:
4790 * \param klass the \c MonoClass to act on
4792 * This routine is an iterator routine for retrieving the properties in a class.
4794 * You must pass a gpointer that points to zero and is treated as an opaque handle to
4795 * iterate over all of the elements. When no more values are
4796 * available, the return value is NULL.
4798 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
4801 mono_class_get_properties (MonoClass
* klass
, gpointer
*iter
)
4803 MonoProperty
* property
;
4807 mono_class_setup_properties (klass
);
4808 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4809 /* start from the first */
4811 *iter
= &info
->properties
[0];
4812 return (MonoProperty
*)*iter
;
4818 property
= (MonoProperty
*)*iter
;
4820 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4821 if (property
< &info
->properties
[info
->count
]) {
4823 return (MonoProperty
*)*iter
;
4829 * mono_class_get_events:
4830 * \param klass the \c MonoClass to act on
4832 * This routine is an iterator routine for retrieving the properties in a class.
4834 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4835 * iterate over all of the elements. When no more values are
4836 * available, the return value is NULL.
4838 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
4841 mono_class_get_events (MonoClass
* klass
, gpointer
*iter
)
4847 mono_class_setup_events (klass
);
4848 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4849 /* start from the first */
4851 *iter
= &info
->events
[0];
4852 return (MonoEvent
*)*iter
;
4858 event
= (MonoEvent
*)*iter
;
4860 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4861 if (event
< &info
->events
[info
->count
]) {
4863 return (MonoEvent
*)*iter
;
4869 * mono_class_get_interfaces
4870 * \param klass the \c MonoClass to act on
4872 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
4874 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4875 * iterate over all of the elements. When no more values are
4876 * available, the return value is NULL.
4878 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
4881 mono_class_get_interfaces (MonoClass
* klass
, gpointer
*iter
)
4888 if (!m_class_is_inited (klass
))
4889 mono_class_init_internal (klass
);
4890 if (!m_class_is_interfaces_inited (klass
)) {
4891 mono_class_setup_interfaces (klass
, error
);
4892 if (!mono_error_ok (error
)) {
4893 mono_error_cleanup (error
);
4897 /* start from the first */
4898 if (m_class_get_interface_count (klass
)) {
4899 *iter
= &m_class_get_interfaces (klass
) [0];
4900 return m_class_get_interfaces (klass
) [0];
4906 iface
= (MonoClass
**)*iter
;
4908 if (iface
< &m_class_get_interfaces (klass
) [m_class_get_interface_count (klass
)]) {
4916 * mono_class_get_nested_types
4917 * \param klass the \c MonoClass to act on
4919 * This routine is an iterator routine for retrieving the nested types of a class.
4920 * This works only if \p klass is non-generic, or a generic type definition.
4922 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4923 * iterate over all of the elements. When no more values are
4924 * available, the return value is NULL.
4926 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
4929 mono_class_get_nested_types (MonoClass
* klass
, gpointer
*iter
)
4935 if (!m_class_is_nested_classes_inited (klass
))
4936 mono_class_setup_nested_types (klass
);
4939 GList
*nested_classes
= mono_class_get_nested_classes_property (klass
);
4940 /* start from the first */
4941 if (nested_classes
) {
4942 *iter
= nested_classes
;
4943 return (MonoClass
*)nested_classes
->data
;
4945 /* no nested types */
4949 item
= (GList
*)*iter
;
4953 return (MonoClass
*)item
->data
;
4960 * mono_class_is_delegate
4961 * \param klass the \c MonoClass to act on
4963 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
4966 mono_class_is_delegate (MonoClass
*klass
)
4969 MONO_ENTER_GC_UNSAFE
;
4970 result
= m_class_is_delegate (klass
);
4971 MONO_EXIT_GC_UNSAFE
;
4976 * mono_class_implements_interface
4977 * \param klass The MonoClass to act on
4978 * \param interface The interface to check if \p klass implements.
4980 * \returns TRUE if \p klass implements \p interface.
4983 mono_class_implements_interface (MonoClass
* klass
, MonoClass
* iface
)
4985 return mono_class_is_assignable_from_internal (iface
, klass
);
4989 class_implements_interface_ignore_generics (MonoClass
* klass
, MonoClass
* iface
)
4993 if (mono_class_is_ginst (iface
))
4994 iface
= mono_class_get_generic_type_definition (iface
);
4995 while (klass
!= NULL
) {
4996 if (mono_class_is_assignable_from_internal (iface
, klass
))
4998 mono_class_setup_interfaces (klass
, error
);
4999 if (!is_ok (error
)) {
5000 mono_error_cleanup (error
);
5003 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
5004 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
5005 MonoClass
*ic
= klass_interfaces
[i
];
5006 if (mono_class_is_ginst (ic
))
5007 ic
= mono_class_get_generic_type_definition (ic
);
5012 klass
= m_class_get_parent (klass
);
5019 * mono_field_get_name:
5020 * \param field the \c MonoClassField to act on
5022 * \returns The name of the field.
5025 mono_field_get_name (MonoClassField
*field
)
5031 * mono_field_get_type_internal:
5032 * \param field the \c MonoClassField to act on
5033 * \returns \c MonoType of the field.
5036 mono_field_get_type_internal (MonoClassField
*field
)
5038 MonoType
*type
= field
->type
;
5043 type
= mono_field_get_type_checked (field
, error
);
5044 if (!mono_error_ok (error
)) {
5045 mono_trace_warning (MONO_TRACE_TYPE
, "Could not load field's type due to %s", mono_error_get_message (error
));
5046 mono_error_cleanup (error
);
5052 * mono_field_get_type:
5053 * \param field the \c MonoClassField to act on
5054 * \returns \c MonoType of the field.
5057 mono_field_get_type (MonoClassField
*field
)
5059 MonoType
*type
= field
->type
;
5063 MONO_ENTER_GC_UNSAFE
;
5064 type
= mono_field_get_type_internal (field
);
5065 MONO_EXIT_GC_UNSAFE
;
5070 * mono_field_get_type_checked:
5071 * \param field the \c MonoClassField to act on
5072 * \param error used to return any error found while retrieving \p field type
5074 * \returns \c MonoType of the field.
5077 mono_field_get_type_checked (MonoClassField
*field
, MonoError
*error
)
5080 MonoType
*type
= field
->type
;
5083 mono_field_resolve_type (field
, error
);
5088 * mono_field_get_parent:
5089 * \param field the \c MonoClassField to act on
5091 * \returns \c MonoClass where the field was defined.
5094 mono_field_get_parent (MonoClassField
*field
)
5096 return field
->parent
;
5100 * mono_field_get_flags;
5101 * \param field the \c MonoClassField to act on
5103 * The metadata flags for a field are encoded using the
5104 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5106 * \returns The flags for the field.
5109 mono_field_get_flags (MonoClassField
*field
)
5112 return mono_field_resolve_flags (field
);
5113 return field
->type
->attrs
;
5117 * mono_field_get_offset:
5118 * \param field the \c MonoClassField to act on
5120 * \returns The field offset.
5123 mono_field_get_offset (MonoClassField
*field
)
5125 mono_class_setup_fields(field
->parent
);
5126 return field
->offset
;
5130 mono_field_get_rva (MonoClassField
*field
)
5134 MonoClass
*klass
= field
->parent
;
5135 MonoFieldDefaultValue
*def_values
;
5137 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
);
5139 def_values
= mono_class_get_field_def_values (klass
);
5141 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
5143 mono_class_set_field_def_values (klass
, def_values
);
5146 field_index
= mono_field_get_index (field
);
5148 if (!def_values
[field_index
].data
&& !image_is_dynamic (m_class_get_image (klass
))) {
5149 int first_field_idx
= mono_class_get_first_field_idx (klass
);
5150 mono_metadata_field_info (m_class_get_image (field
->parent
), first_field_idx
+ field_index
, NULL
, &rva
, NULL
);
5152 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field
), m_class_get_name (field
->parent
));
5153 def_values
[field_index
].data
= mono_image_rva_map (m_class_get_image (field
->parent
), rva
);
5156 return def_values
[field_index
].data
;
5160 * mono_field_get_data:
5161 * \param field the \c MonoClassField to act on
5163 * \returns A pointer to the metadata constant value or to the field
5164 * data if it has an RVA flag.
5167 mono_field_get_data (MonoClassField
*field
)
5169 if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
) {
5170 MonoTypeEnum def_type
;
5172 return mono_class_get_field_default_value (field
, &def_type
);
5173 } else if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
5174 return mono_field_get_rva (field
);
5181 * mono_property_get_name:
5182 * \param prop the \c MonoProperty to act on
5183 * \returns The name of the property
5186 mono_property_get_name (MonoProperty
*prop
)
5192 * mono_property_get_set_method
5193 * \param prop the \c MonoProperty to act on.
5194 * \returns The setter method of the property, a \c MonoMethod.
5197 mono_property_get_set_method (MonoProperty
*prop
)
5203 * mono_property_get_get_method
5204 * \param prop the MonoProperty to act on.
5205 * \returns The getter method of the property (A \c MonoMethod)
5208 mono_property_get_get_method (MonoProperty
*prop
)
5214 * mono_property_get_parent:
5215 * \param prop the \c MonoProperty to act on.
5216 * \returns The \c MonoClass where the property was defined.
5219 mono_property_get_parent (MonoProperty
*prop
)
5221 return prop
->parent
;
5225 * mono_property_get_flags:
5226 * \param prop the \c MonoProperty to act on.
5228 * The metadata flags for a property are encoded using the
5229 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5231 * \returns The flags for the property.
5234 mono_property_get_flags (MonoProperty
*prop
)
5240 * mono_event_get_name:
5241 * \param event the MonoEvent to act on
5242 * \returns The name of the event.
5245 mono_event_get_name (MonoEvent
*event
)
5251 * mono_event_get_add_method:
5252 * \param event The \c MonoEvent to act on.
5253 * \returns The \c add method for the event, a \c MonoMethod.
5256 mono_event_get_add_method (MonoEvent
*event
)
5262 * mono_event_get_remove_method:
5263 * \param event The \c MonoEvent to act on.
5264 * \returns The \c remove method for the event, a \c MonoMethod.
5267 mono_event_get_remove_method (MonoEvent
*event
)
5269 return event
->remove
;
5273 * mono_event_get_raise_method:
5274 * \param event The \c MonoEvent to act on.
5275 * \returns The \c raise method for the event, a \c MonoMethod.
5278 mono_event_get_raise_method (MonoEvent
*event
)
5280 return event
->raise
;
5284 * mono_event_get_parent:
5285 * \param event the MonoEvent to act on.
5286 * \returns The \c MonoClass where the event is defined.
5289 mono_event_get_parent (MonoEvent
*event
)
5291 return event
->parent
;
5295 * mono_event_get_flags
5296 * \param event the \c MonoEvent to act on.
5298 * The metadata flags for an event are encoded using the
5299 * \c EVENT_* constants. See the \c tabledefs.h file for details.
5301 * \returns The flags for the event.
5304 mono_event_get_flags (MonoEvent
*event
)
5306 return event
->attrs
;
5310 * mono_class_get_method_from_name:
5311 * \param klass where to look for the method
5312 * \param name name of the method
5313 * \param param_count number of parameters. -1 for any number.
5315 * Obtains a \c MonoMethod with a given name and number of parameters.
5316 * It only works if there are no multiple signatures for any given method name.
5319 mono_class_get_method_from_name (MonoClass
*klass
, const char *name
, int param_count
)
5322 MONO_ENTER_GC_UNSAFE
;
5324 result
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, 0, error
);
5325 mono_error_cleanup (error
);
5326 MONO_EXIT_GC_UNSAFE
;
5331 mono_find_method_in_metadata (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5333 MonoImage
*klass_image
= m_class_get_image (klass
);
5334 MonoMethod
*res
= NULL
;
5337 /* Search directly in the metadata to avoid calling setup_methods () */
5338 int first_idx
= mono_class_get_first_method_idx (klass
);
5339 int mcount
= mono_class_get_method_count (klass
);
5340 for (i
= 0; i
< mcount
; ++i
) {
5342 guint32 cols
[MONO_METHOD_SIZE
];
5344 MonoMethodSignature
*sig
;
5346 /* first_idx points into the methodptr table */
5347 mono_metadata_decode_table_row (klass_image
, MONO_TABLE_METHOD
, first_idx
+ i
, cols
, MONO_METHOD_SIZE
);
5349 if (!strcmp (mono_metadata_string_heap (klass_image
, cols
[MONO_METHOD_NAME
]), name
)) {
5350 method
= mono_get_method_checked (klass_image
, MONO_TOKEN_METHOD_DEF
| (first_idx
+ i
+ 1), klass
, NULL
, error
);
5352 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5355 if (param_count
== -1) {
5359 sig
= mono_method_signature_checked (method
, error
);
5361 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5364 if (sig
->param_count
== param_count
) {
5375 * mono_class_get_method_from_name_flags:
5376 * \param klass where to look for the method
5377 * \param name_space name of the method
5378 * \param param_count number of parameters. -1 for any number.
5379 * \param flags flags which must be set in the method
5381 * Obtains a \c MonoMethod with a given name and number of parameters.
5382 * It only works if there are no multiple signatures for any given method name.
5385 mono_class_get_method_from_name_flags (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5388 MONO_ENTER_GC_UNSAFE
;
5390 method
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, flags
, error
);
5391 mono_error_cleanup (error
);
5392 MONO_EXIT_GC_UNSAFE
;
5397 * mono_class_get_method_from_name_checked:
5398 * \param klass where to look for the method
5399 * \param name_space name of the method
5400 * \param param_count number of parameters. -1 for any number.
5401 * \param flags flags which must be set in the method
5404 * Obtains a \c MonoMethod with a given name and number of parameters.
5405 * It only works if there are no multiple signatures for any given method name.
5408 mono_class_get_method_from_name_checked (MonoClass
*klass
, const char *name
,
5409 int param_count
, int flags
, MonoError
*error
)
5411 MonoMethod
*res
= NULL
;
5414 mono_class_init_internal (klass
);
5416 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
5417 res
= mono_class_get_method_from_name_checked (mono_class_get_generic_class (klass
)->container_class
, name
, param_count
, flags
, error
);
5420 res
= mono_class_inflate_generic_method_full_checked (res
, klass
, mono_class_get_context (klass
), error
);
5425 if (m_class_get_methods (klass
) || !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
5426 mono_class_setup_methods (klass
);
5428 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
5429 See mono/tests/array_load_exception.il
5430 FIXME we should better report this error to the caller
5432 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
5435 int mcount
= mono_class_get_method_count (klass
);
5436 for (i
= 0; i
< mcount
; ++i
) {
5437 MonoMethod
*method
= klass_methods
[i
];
5439 if (method
->name
[0] == name
[0] &&
5440 !strcmp (name
, method
->name
) &&
5441 (param_count
== -1 || mono_method_signature_internal (method
)->param_count
== param_count
) &&
5442 ((method
->flags
& flags
) == flags
)) {
5449 res
= mono_find_method_in_metadata (klass
, name
, param_count
, flags
);
5456 mono_class_has_failure (const MonoClass
*klass
)
5458 g_assert (klass
!= NULL
);
5459 return m_class_has_failure ((MonoClass
*)klass
) != 0;
5464 * mono_class_set_type_load_failure:
5465 * \param klass class in which the failure was detected
5466 * \param fmt \c printf -style error message string.
5468 * Collect detected failure informaion in the class for later processing.
5469 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
5470 * Note that only the first failure is kept.
5472 * LOCKING: Acquires the loader lock.
5474 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
5477 mono_class_set_type_load_failure (MonoClass
*klass
, const char * fmt
, ...)
5479 ERROR_DECL (prepare_error
);
5482 if (mono_class_has_failure (klass
))
5485 va_start (args
, fmt
);
5486 mono_error_vset_type_load_class (prepare_error
, klass
, fmt
, args
);
5489 MonoErrorBoxed
*box
= mono_error_box (prepare_error
, m_class_get_image (klass
));
5490 mono_error_cleanup (prepare_error
);
5491 return mono_class_set_failure (klass
, box
);
5495 * mono_class_get_exception_for_failure:
5496 * \param klass class in which the failure was detected
5498 * \returns a constructed MonoException than the caller can then throw
5499 * using mono_raise_exception - or NULL if no failure is present (or
5500 * doesn't result in an exception).
5503 mono_class_get_exception_for_failure (MonoClass
*klass
)
5505 if (!mono_class_has_failure (klass
))
5507 ERROR_DECL (unboxed_error
);
5508 mono_error_set_for_class_failure (unboxed_error
, klass
);
5509 return mono_error_convert_to_exception (unboxed_error
);
5513 is_nesting_type (MonoClass
*outer_klass
, MonoClass
*inner_klass
)
5515 outer_klass
= mono_class_get_generic_type_definition (outer_klass
);
5516 inner_klass
= mono_class_get_generic_type_definition (inner_klass
);
5518 if (outer_klass
== inner_klass
)
5520 inner_klass
= m_class_get_nested_in (inner_klass
);
5521 } while (inner_klass
);
5526 mono_class_get_generic_type_definition (MonoClass
*klass
)
5528 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5529 return gklass
? gklass
->container_class
: klass
;
5533 * Check if @klass is a subtype of @parent ignoring generic instantiations.
5535 * Generic instantiations are ignored for all super types of @klass.
5537 * Visibility checks ignoring generic instantiations.
5539 * Class implementing interface visibility checks ignore generic instantiations
5542 mono_class_has_parent_and_ignore_generics (MonoClass
*klass
, MonoClass
*parent
)
5545 klass
= mono_class_get_generic_type_definition (klass
);
5546 parent
= mono_class_get_generic_type_definition (parent
);
5547 mono_class_setup_supertypes (klass
);
5549 for (i
= 0; i
< m_class_get_idepth (klass
); ++i
) {
5550 if (parent
== mono_class_get_generic_type_definition (m_class_get_supertypes (klass
) [i
]))
5554 if (MONO_CLASS_IS_INTERFACE_INTERNAL (parent
) && class_implements_interface_ignore_generics (klass
, parent
))
5560 * Subtype can only access parent members with family protection if the site object
5561 * is subclass of Subtype. For example:
5562 * class A { protected int x; }
5564 * void valid_access () {
5568 * void invalid_access () {
5575 is_valid_family_access (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
*context_klass
)
5577 if (MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5578 /* Can happen with default interface methods */
5579 if (!class_implements_interface_ignore_generics (access_klass
, member_klass
))
5581 } else if (member_klass
!= access_klass
&& MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5582 /* Can happen with default interface methods */
5583 if (!mono_interface_implements_interface (access_klass
, member_klass
))
5586 if (!mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
))
5590 if (context_klass
== NULL
)
5592 /*if access_klass is not member_klass context_klass must be type compat*/
5593 if (access_klass
!= member_klass
&& !mono_class_has_parent_and_ignore_generics (context_klass
, access_klass
))
5599 can_access_internals (MonoAssembly
*accessing
, MonoAssembly
* accessed
)
5602 if (accessing
== accessed
)
5604 if (!accessed
|| !accessing
)
5607 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
5608 * anywhere so untrusted friends are not safe to access platform's code internals */
5609 if (mono_security_core_clr_enabled ()) {
5610 if (!mono_security_core_clr_can_access_internals (accessing
->image
, accessed
->image
))
5614 mono_assembly_load_friends (accessed
);
5615 for (tmp
= accessed
->friend_assembly_names
; tmp
; tmp
= tmp
->next
) {
5616 MonoAssemblyName
*friend_
= (MonoAssemblyName
*)tmp
->data
;
5617 /* Be conservative with checks */
5620 if (g_ascii_strcasecmp (accessing
->aname
.name
, friend_
->name
))
5622 if (friend_
->public_key_token
[0]) {
5623 if (!accessing
->aname
.public_key_token
[0])
5625 if (!mono_public_tokens_are_equal (friend_
->public_key_token
, accessing
->aname
.public_key_token
))
5634 * If klass is a generic type or if it is derived from a generic type, return the
5635 * MonoClass of the generic definition
5636 * Returns NULL if not found
5639 get_generic_definition_class (MonoClass
*klass
)
5642 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5643 if (gklass
&& gklass
->container_class
)
5644 return gklass
->container_class
;
5645 klass
= m_class_get_parent (klass
);
5651 can_access_instantiation (MonoClass
*access_klass
, MonoGenericInst
*ginst
)
5654 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
5655 MonoType
*type
= ginst
->type_argv
[i
];
5656 switch (type
->type
) {
5657 case MONO_TYPE_SZARRAY
:
5658 if (!can_access_type (access_klass
, type
->data
.klass
))
5661 case MONO_TYPE_ARRAY
:
5662 if (!can_access_type (access_klass
, type
->data
.array
->eklass
))
5666 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
->data
.type
)))
5669 case MONO_TYPE_CLASS
:
5670 case MONO_TYPE_VALUETYPE
:
5671 case MONO_TYPE_GENERICINST
:
5672 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
)))
5682 can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
)
5686 if (access_klass
== member_klass
)
5689 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5690 MonoAssembly
*member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5692 if (access_klass_assembly
&& m_class_get_image (access_klass
)->assembly
->corlib_internal
)
5695 if (m_class_get_element_class (access_klass
) && !m_class_is_enumtype (access_klass
)) {
5696 access_klass
= m_class_get_element_class (access_klass
);
5697 access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5700 if (m_class_get_element_class (member_klass
) && !m_class_is_enumtype (member_klass
)) {
5701 member_klass
= m_class_get_element_class (member_klass
);
5702 member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5705 access_level
= mono_class_get_flags (member_klass
) & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5707 if (mono_type_is_generic_argument (m_class_get_byval_arg (member_klass
)))
5710 if (mono_class_is_ginst (member_klass
) && !can_access_instantiation (access_klass
, mono_class_get_generic_class (member_klass
)->context
.class_inst
))
5713 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
)))
5716 /*Non nested type with nested visibility. We just fail it.*/
5717 if (access_level
>= TYPE_ATTRIBUTE_NESTED_PRIVATE
&& access_level
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
&& m_class_get_nested_in (member_klass
) == NULL
)
5720 MonoClass
*member_klass_nested_in
= m_class_get_nested_in (member_klass
);
5721 switch (access_level
) {
5722 case TYPE_ATTRIBUTE_NOT_PUBLIC
:
5723 return can_access_internals (access_klass_assembly
, member_klass_assembly
);
5725 case TYPE_ATTRIBUTE_PUBLIC
:
5728 case TYPE_ATTRIBUTE_NESTED_PUBLIC
:
5729 return member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5731 case TYPE_ATTRIBUTE_NESTED_PRIVATE
:
5732 return is_nesting_type (member_klass
, access_klass
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5734 case TYPE_ATTRIBUTE_NESTED_FAMILY
:
5735 return mono_class_has_parent_and_ignore_generics (access_klass
, m_class_get_nested_in (member_klass
));
5737 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY
:
5738 return can_access_internals (access_klass_assembly
, member_klass_assembly
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5740 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM
:
5741 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) &&
5742 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5744 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
:
5745 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) ||
5746 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5751 /* FIXME: check visibility of type, too */
5753 can_access_member (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
* context_klass
, int access_level
)
5755 MonoClass
*member_generic_def
;
5756 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5757 if (access_klass_assembly
&& access_klass_assembly
->corlib_internal
)
5760 MonoGenericClass
*access_gklass
= mono_class_try_get_generic_class (access_klass
);
5761 if (((access_gklass
&& access_gklass
->container_class
) ||
5762 mono_class_is_gtd (access_klass
)) &&
5763 (member_generic_def
= get_generic_definition_class (member_klass
))) {
5764 MonoClass
*access_container
;
5766 if (mono_class_is_gtd (access_klass
))
5767 access_container
= access_klass
;
5769 access_container
= access_gklass
->container_class
;
5771 if (can_access_member (access_container
, member_generic_def
, context_klass
, access_level
))
5775 MonoImage
*member_klass_image
= m_class_get_image (member_klass
);
5776 /* Partition I 8.5.3.2 */
5777 /* the access level values are the same for fields and methods */
5778 switch (access_level
) {
5779 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED
:
5780 /* same compilation unit */
5781 return m_class_get_image (access_klass
) == member_klass_image
;
5782 case FIELD_ATTRIBUTE_PRIVATE
:
5783 return access_klass
== member_klass
;
5784 case FIELD_ATTRIBUTE_FAM_AND_ASSEM
:
5785 if (is_valid_family_access (access_klass
, member_klass
, context_klass
) &&
5786 can_access_internals (access_klass_assembly
, member_klass_image
->assembly
))
5789 case FIELD_ATTRIBUTE_ASSEMBLY
:
5790 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5791 case FIELD_ATTRIBUTE_FAMILY
:
5792 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5795 case FIELD_ATTRIBUTE_FAM_OR_ASSEM
:
5796 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5798 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5799 case FIELD_ATTRIBUTE_PUBLIC
:
5806 * mono_method_can_access_field:
5807 * \param method Method that will attempt to access the field
5808 * \param field the field to access
5810 * Used to determine if a method is allowed to access the specified field.
5812 * \returns TRUE if the given \p method is allowed to access the \p field while following
5813 * the accessibility rules of the CLI.
5816 mono_method_can_access_field (MonoMethod
*method
, MonoClassField
*field
)
5818 /* FIXME: check all overlapping fields */
5819 int can
= can_access_member (method
->klass
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5821 MonoClass
*nested
= m_class_get_nested_in (method
->klass
);
5823 can
= can_access_member (nested
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5826 nested
= m_class_get_nested_in (nested
);
5833 mono_method_get_method_definition (MonoMethod
*method
)
5835 while (method
->is_inflated
)
5836 method
= ((MonoMethodInflated
*)method
)->declaring
;
5841 * mono_method_can_access_method:
5842 * \param method Method that will attempt to access the other method
5843 * \param called the method that we want to probe for accessibility.
5845 * Used to determine if the \p method is allowed to access the specified \p called method.
5847 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
5848 * the accessibility rules of the CLI.
5851 mono_method_can_access_method (MonoMethod
*method
, MonoMethod
*called
)
5853 method
= mono_method_get_method_definition (method
);
5854 called
= mono_method_get_method_definition (called
);
5855 return mono_method_can_access_method_full (method
, called
, NULL
);
5859 * mono_method_can_access_method_full:
5860 * @method: The caller method
5861 * @called: The called method
5862 * @context_klass: The static type on stack of the owner @called object used
5864 * This function must be used with instance calls, as they have more strict family accessibility.
5865 * It can be used with static methods, but context_klass should be NULL.
5867 * Returns: TRUE if caller have proper visibility and acessibility to @called
5870 mono_method_can_access_method_full (MonoMethod
*method
, MonoMethod
*called
, MonoClass
*context_klass
)
5872 /* Wrappers are except from access checks */
5873 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| called
->wrapper_type
!= MONO_WRAPPER_NONE
)
5876 MonoClass
*access_class
= method
->klass
;
5877 MonoClass
*member_class
= called
->klass
;
5878 int can
= can_access_member (access_class
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5880 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5882 can
= can_access_member (nested
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5885 nested
= m_class_get_nested_in (nested
);
5892 can
= can_access_type (access_class
, member_class
);
5894 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5896 can
= can_access_type (nested
, member_class
);
5899 nested
= m_class_get_nested_in (nested
);
5906 if (called
->is_inflated
) {
5907 MonoMethodInflated
* infl
= (MonoMethodInflated
*)called
;
5908 if (infl
->context
.method_inst
&& !can_access_instantiation (access_class
, infl
->context
.method_inst
))
5917 * mono_method_can_access_field_full:
5918 * @method: The caller method
5919 * @field: The accessed field
5920 * @context_klass: The static type on stack of the owner @field object used
5922 * This function must be used with instance fields, as they have more strict family accessibility.
5923 * It can be used with static fields, but context_klass should be NULL.
5925 * Returns: TRUE if caller have proper visibility and acessibility to @field
5928 mono_method_can_access_field_full (MonoMethod
*method
, MonoClassField
*field
, MonoClass
*context_klass
)
5930 MonoClass
*access_class
= method
->klass
;
5931 MonoClass
*member_class
= field
->parent
;
5932 /* FIXME: check all overlapping fields */
5933 int can
= can_access_member (access_class
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5935 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5937 can
= can_access_member (nested
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5940 nested
= m_class_get_nested_in (nested
);
5947 can
= can_access_type (access_class
, member_class
);
5949 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5951 can
= can_access_type (nested
, member_class
);
5954 nested
= m_class_get_nested_in (nested
);
5964 * mono_class_can_access_class:
5965 * @source_class: The source class
5966 * @target_class: The accessed class
5968 * This function returns is @target_class is visible to @source_class
5970 * Returns: TRUE if source have proper visibility and acessibility to target
5973 mono_class_can_access_class (MonoClass
*source_class
, MonoClass
*target_class
)
5975 return can_access_type (source_class
, target_class
);
5979 * mono_type_is_valid_enum_basetype:
5980 * \param type The MonoType to check
5981 * \returns TRUE if the type can be used as the basetype of an enum
5983 gboolean
mono_type_is_valid_enum_basetype (MonoType
* type
) {
5984 switch (type
->type
) {
5987 case MONO_TYPE_BOOLEAN
:
5990 case MONO_TYPE_CHAR
:
6008 * mono_class_is_valid_enum:
6009 * \param klass An enum class to be validated
6011 * This method verify the required properties an enum should have.
6013 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
6014 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
6015 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
6017 * \returns TRUE if the informed enum class is valid
6020 mono_class_is_valid_enum (MonoClass
*klass
)
6022 MonoClassField
* field
;
6023 gpointer iter
= NULL
;
6024 gboolean found_base_field
= FALSE
;
6026 g_assert (m_class_is_enumtype (klass
));
6027 MonoClass
*klass_parent
= m_class_get_parent (klass
);
6028 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
6029 if (!klass_parent
|| strcmp (m_class_get_name (klass_parent
), "Enum") || strcmp (m_class_get_name_space (klass_parent
), "System") ) {
6033 if (!mono_class_is_auto_layout (klass
))
6036 while ((field
= mono_class_get_fields_internal (klass
, &iter
))) {
6037 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
6038 if (found_base_field
)
6040 found_base_field
= TRUE
;
6041 if (!mono_type_is_valid_enum_basetype (field
->type
))
6046 if (!found_base_field
)
6049 if (mono_class_get_method_count (klass
) > 0)
6056 mono_generic_class_is_generic_type_definition (MonoGenericClass
*gklass
)
6058 return gklass
->context
.class_inst
== mono_class_get_generic_container (gklass
->container_class
)->context
.class_inst
;
6062 mono_field_resolve_type (MonoClassField
*field
, MonoError
*error
)
6064 MonoClass
*klass
= field
->parent
;
6065 MonoImage
*image
= m_class_get_image (klass
);
6066 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
6068 int field_idx
= field
- m_class_get_fields (klass
);
6073 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
6074 MonoType
*gtype
= mono_field_get_type_checked (gfield
, error
);
6075 if (!mono_error_ok (error
)) {
6076 char *full_name
= mono_type_get_full_name (gtd
);
6077 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
));
6081 ftype
= mono_class_inflate_generic_type_no_copy (image
, gtype
, mono_class_get_context (klass
), error
);
6082 if (!mono_error_ok (error
)) {
6083 char *full_name
= mono_type_get_full_name (klass
);
6084 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
));
6089 guint32 cols
[MONO_FIELD_SIZE
];
6090 MonoGenericContainer
*container
= NULL
;
6091 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
6093 /*FIXME, in theory we do not lazy load SRE fields*/
6094 g_assert (!image_is_dynamic (image
));
6096 if (mono_class_is_gtd (klass
)) {
6097 container
= mono_class_get_generic_container (klass
);
6099 container
= mono_class_get_generic_container (gtd
);
6100 g_assert (container
);
6103 /* first_field_idx and idx points into the fieldptr table */
6104 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
6106 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
)) {
6107 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
6111 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
6113 mono_metadata_decode_value (sig
, &sig
);
6114 /* FIELD signature == 0x06 */
6115 g_assert (*sig
== 0x06);
6117 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
6119 char *full_name
= mono_type_get_full_name (klass
);
6120 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
));
6124 mono_memory_barrier ();
6125 field
->type
= ftype
;
6129 mono_field_resolve_flags (MonoClassField
*field
)
6131 MonoClass
*klass
= field
->parent
;
6132 MonoImage
*image
= m_class_get_image (klass
);
6133 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
6134 int field_idx
= field
- m_class_get_fields (klass
);
6137 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
6138 return mono_field_get_flags (gfield
);
6140 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
6142 /*FIXME, in theory we do not lazy load SRE fields*/
6143 g_assert (!image_is_dynamic (image
));
6145 return mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_FLAGS
);
6150 * mono_class_get_fields_lazy:
6151 * \param klass the MonoClass to act on
6153 * This routine is an iterator routine for retrieving the fields in a class.
6154 * Only minimal information about fields are loaded. Accessors must be used
6155 * for all MonoClassField returned.
6157 * You must pass a gpointer that points to zero and is treated as an opaque handle to
6158 * iterate over all of the elements. When no more values are
6159 * available, the return value is NULL.
6161 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
6164 mono_class_get_fields_lazy (MonoClass
* klass
, gpointer
*iter
)
6166 MonoClassField
* field
;
6170 mono_class_setup_basic_field_info (klass
);
6171 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
6174 /* start from the first */
6175 if (mono_class_get_field_count (klass
)) {
6176 *iter
= &klass_fields
[0];
6177 return (MonoClassField
*)*iter
;
6183 field
= (MonoClassField
*)*iter
;
6185 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
6187 return (MonoClassField
*)*iter
;
6193 mono_class_full_name (MonoClass
*klass
)
6195 return mono_type_full_name (m_class_get_byval_arg (klass
));
6198 /* Declare all shared lazy type lookup functions */
6199 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle
, "System.Runtime.InteropServices", "SafeHandle")
6202 * mono_method_get_base_method:
6203 * \param method a method
6204 * \param definition if true, get the definition
6205 * \param error set on failure
6207 * Given a virtual method associated with a subclass, return the corresponding
6208 * method from an ancestor. If \p definition is FALSE, returns the method in the
6209 * superclass of the given method. If \p definition is TRUE, return the method
6210 * in the ancestor class where it was first declared. The type arguments will
6211 * be inflated in the ancestor classes. If the method is not associated with a
6212 * class, or isn't virtual, returns the method itself. On failure returns NULL
6213 * and sets \p error.
6216 mono_method_get_base_method (MonoMethod
*method
, gboolean definition
, MonoError
*error
)
6218 MonoClass
*klass
, *parent
;
6219 MonoGenericContext
*generic_inst
= NULL
;
6220 MonoMethod
*result
= NULL
;
6223 if (method
->klass
== NULL
)
6226 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
6227 MONO_CLASS_IS_INTERFACE_INTERNAL (method
->klass
) ||
6228 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
6231 slot
= mono_method_get_vtable_slot (method
);
6235 klass
= method
->klass
;
6236 if (mono_class_is_ginst (klass
)) {
6237 generic_inst
= mono_class_get_context (klass
);
6238 klass
= mono_class_get_generic_class (klass
)->container_class
;
6243 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6244 for (parent
= m_class_get_parent (klass
); parent
!= NULL
; parent
= m_class_get_parent (parent
)) {
6245 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6246 or klass is the generic container class and generic_inst is the instantiation.
6248 when we go to the parent, if the parent is an open constructed type, we need to
6249 replace the type parameters by the definitions from the generic_inst, and then take it
6250 apart again into the klass and the generic_inst.
6252 For cases like this:
6253 class C<T> : B<T, int> {
6254 public override void Foo () { ... }
6256 class B<U,V> : A<HashMap<U,V>> {
6257 public override void Foo () { ... }
6260 public virtual void Foo () { ... }
6263 if at each iteration the parent isn't open, we can skip inflating it. if at some
6264 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6267 MonoGenericContext
*parent_inst
= NULL
;
6268 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (parent
))) {
6269 parent
= mono_class_inflate_generic_class_checked (parent
, generic_inst
, error
);
6270 return_val_if_nok (error
, NULL
);
6272 if (mono_class_is_ginst (parent
)) {
6273 parent_inst
= mono_class_get_context (parent
);
6274 parent
= mono_class_get_generic_class (parent
)->container_class
;
6277 mono_class_setup_vtable (parent
);
6278 if (m_class_get_vtable_size (parent
) <= slot
)
6281 generic_inst
= parent_inst
;
6284 klass
= m_class_get_parent (klass
);
6287 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (klass
))) {
6288 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6289 return_val_if_nok (error
, NULL
);
6291 generic_inst
= NULL
;
6293 if (mono_class_is_ginst (klass
)) {
6294 generic_inst
= mono_class_get_context (klass
);
6295 klass
= mono_class_get_generic_class (klass
)->container_class
;
6301 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6302 return_val_if_nok (error
, NULL
);
6305 if (klass
== method
->klass
)
6308 /*This is possible if definition == FALSE.
6309 * Do it here to be really sure we don't read invalid memory.
6311 if (slot
>= m_class_get_vtable_size (klass
))
6314 mono_class_setup_vtable (klass
);
6316 result
= m_class_get_vtable (klass
) [slot
];
6317 if (result
== NULL
) {
6318 /* It is an abstract method */
6319 gboolean found
= FALSE
;
6320 gpointer iter
= NULL
;
6321 while ((result
= mono_class_get_methods (klass
, &iter
))) {
6322 if (result
->slot
== slot
) {
6327 /* found might be FALSE if we looked in an abstract class
6328 * that doesn't override an abstract method of its
6330 * abstract class Base {
6331 * public abstract void Foo ();
6333 * abstract class Derived : Base { }
6334 * class Child : Derived {
6335 * public override void Foo () { }
6338 * if m was Child.Foo and we ask for the base method,
6339 * then we get here with klass == Derived and found == FALSE
6341 /* but it shouldn't be the case that if we're looking
6342 * for the definition and didn't find a result; the
6343 * loop above should've taken us as far as we could
6345 g_assert (!(definition
&& !found
));
6350 g_assert (result
!= NULL
);