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 (eclass
== mono_defaults
.object_class
)) {
3829 mono_class_is_assignable_from_checked (eclass
, eoclass
, result
, error
);
3831 } else if (mono_class_is_nullable (klass
)) {
3832 if (mono_class_is_nullable (oklass
))
3833 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), m_class_get_cast_class (oklass
), result
, error
);
3835 mono_class_is_assignable_from_checked (m_class_get_cast_class (klass
), oklass
, result
, error
);
3837 } else if (klass
== mono_defaults
.object_class
) {
3838 if (m_class_get_class_kind (oklass
) == MONO_CLASS_POINTER
)
3845 *result
= mono_class_has_parent (oklass
, klass
);
3848 /*Check if @oklass is variant compatible with @klass.*/
3850 mono_class_is_variant_compatible_slow (MonoClass
*klass
, MonoClass
*oklass
)
3853 MonoType
**klass_argv
, **oklass_argv
;
3854 MonoClass
*klass_gtd
= mono_class_get_generic_type_definition (klass
);
3855 MonoGenericContainer
*container
= mono_class_get_generic_container (klass_gtd
);
3857 /*Viable candidates are instances of the same generic interface*/
3858 if (mono_class_get_generic_type_definition (oklass
) != klass_gtd
|| oklass
== klass_gtd
)
3861 klass_argv
= &mono_class_get_generic_class (klass
)->context
.class_inst
->type_argv
[0];
3862 oklass_argv
= &mono_class_get_generic_class (oklass
)->context
.class_inst
->type_argv
[0];
3864 for (j
= 0; j
< container
->type_argc
; ++j
) {
3865 MonoClass
*param1_class
= mono_class_from_mono_type_internal (klass_argv
[j
]);
3866 MonoClass
*param2_class
= mono_class_from_mono_type_internal (oklass_argv
[j
]);
3868 if (m_class_is_valuetype (param1_class
) != m_class_is_valuetype (param2_class
))
3872 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
3873 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
3875 if (param1_class
!= param2_class
) {
3876 if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_VARIANT
) {
3877 if (!mono_class_is_assignable_from_slow (param1_class
, param2_class
))
3879 } else if (mono_generic_container_get_param_info (container
, j
)->flags
& MONO_GEN_PARAM_COVARIANT
) {
3880 if (!mono_class_is_assignable_from_slow (param2_class
, param1_class
))
3888 /*Check if @candidate implements the interface @target*/
3890 mono_class_implement_interface_slow (MonoClass
*target
, MonoClass
*candidate
)
3894 gboolean is_variant
= mono_class_has_variant_generic_params (target
);
3896 if (is_variant
&& MONO_CLASS_IS_INTERFACE_INTERNAL (candidate
)) {
3897 if (mono_class_is_variant_compatible_slow (target
, candidate
))
3902 if (candidate
== target
)
3905 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
3906 if (image_is_dynamic (m_class_get_image (candidate
)) && !m_class_was_typebuilder (candidate
)) {
3907 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info_raw (candidate
); /* FIXME use handles */
3909 if (tb
&& tb
->interfaces
) {
3910 for (j
= mono_array_length_internal (tb
->interfaces
) - 1; j
>= 0; --j
) {
3911 MonoReflectionType
*iface
= mono_array_get_internal (tb
->interfaces
, MonoReflectionType
*, j
);
3912 MonoClass
*iface_class
;
3914 /* we can't realize the type here since it can do pretty much anything. */
3917 iface_class
= mono_class_from_mono_type_internal (iface
->type
);
3918 if (iface_class
== target
)
3920 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, iface_class
))
3922 if (mono_class_implement_interface_slow (target
, iface_class
))
3927 /*setup_interfaces don't mono_class_init_internal anything*/
3928 /*FIXME this doesn't handle primitive type arrays.
3929 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
3930 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
3932 mono_class_setup_interfaces (candidate
, error
);
3933 if (!mono_error_ok (error
)) {
3934 mono_error_cleanup (error
);
3938 int candidate_interface_count
= m_class_get_interface_count (candidate
);
3939 MonoClass
**candidate_interfaces
= m_class_get_interfaces (candidate
);
3940 for (i
= 0; i
< candidate_interface_count
; ++i
) {
3941 if (candidate_interfaces
[i
] == target
)
3944 if (is_variant
&& mono_class_is_variant_compatible_slow (target
, candidate_interfaces
[i
]))
3947 if (mono_class_implement_interface_slow (target
, candidate_interfaces
[i
]))
3951 candidate
= m_class_get_parent (candidate
);
3952 } while (candidate
);
3958 * Check if @oklass can be assigned to @klass.
3959 * This function does the same as mono_class_is_assignable_from_internal but is safe to be used from mono_class_init_internal context.
3962 mono_class_is_assignable_from_slow (MonoClass
*target
, MonoClass
*candidate
)
3964 if (candidate
== target
)
3966 if (target
== mono_defaults
.object_class
)
3969 if (mono_class_has_parent (candidate
, target
))
3972 /*If target is not an interface there is no need to check them.*/
3973 if (MONO_CLASS_IS_INTERFACE_INTERNAL (target
))
3974 return mono_class_implement_interface_slow (target
, candidate
);
3976 if (m_class_is_delegate (target
) && mono_class_has_variant_generic_params (target
))
3977 return mono_class_is_variant_compatible (target
, candidate
, FALSE
);
3979 if (m_class_get_rank (target
)) {
3980 MonoClass
*eclass
, *eoclass
;
3982 if (m_class_get_rank (target
) != m_class_get_rank (candidate
))
3985 /* vectors vs. one dimensional arrays */
3986 if (m_class_get_byval_arg (target
)->type
!= m_class_get_byval_arg (candidate
)->type
)
3989 eclass
= m_class_get_cast_class (target
);
3990 eoclass
= m_class_get_cast_class (candidate
);
3993 * a is b does not imply a[] is b[] when a is a valuetype, and
3994 * b is a reference type.
3997 if (m_class_is_valuetype (eoclass
)) {
3998 if ((eclass
== mono_defaults
.enum_class
) ||
3999 (eclass
== m_class_get_parent (mono_defaults
.enum_class
)) ||
4000 (eclass
== mono_defaults
.object_class
))
4004 return mono_class_is_assignable_from_slow (eclass
, eoclass
);
4006 /*FIXME properly handle nullables */
4007 /*FIXME properly handle (M)VAR */
4012 * mono_generic_param_get_base_type:
4014 * Return the base type of the given generic parameter from its constraints.
4016 * Could be another generic parameter, or it could be Object or ValueType.
4019 mono_generic_param_get_base_type (MonoClass
*klass
)
4021 MonoType
*type
= m_class_get_byval_arg (klass
);
4022 g_assert (mono_type_is_generic_argument (type
));
4024 MonoGenericParam
*gparam
= type
->data
.generic_param
;
4026 MonoClass
**constraints
= mono_generic_container_get_param_info (gparam
->owner
, gparam
->num
)->constraints
;
4028 MonoClass
*base_class
= mono_defaults
.object_class
;
4032 for (i
= 0; constraints
[i
]; ++i
) {
4033 MonoClass
*constraint
= constraints
[i
];
4035 if (MONO_CLASS_IS_INTERFACE_INTERNAL (constraint
))
4038 MonoType
*constraint_type
= m_class_get_byval_arg (constraint
);
4039 if (mono_type_is_generic_argument (constraint_type
)) {
4040 MonoGenericParam
*constraint_param
= constraint_type
->data
.generic_param
;
4041 MonoGenericParamInfo
*constraint_info
= mono_generic_param_info (constraint_param
);
4042 if ((constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT
) == 0 &&
4043 (constraint_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) == 0)
4047 base_class
= constraint
;
4052 if (base_class
== mono_defaults
.object_class
)
4054 MonoGenericParamInfo
*gparam_info
= mono_generic_param_info (gparam
);
4055 if ((gparam_info
->flags
& GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT
) != 0) {
4056 base_class
= mono_class_get_valuetype_class ();
4064 * mono_class_get_cctor:
4065 * \param klass A MonoClass pointer
4067 * \returns The static constructor of \p klass if it exists, NULL otherwise.
4070 mono_class_get_cctor (MonoClass
*klass
)
4072 MonoMethod
*result
= NULL
;
4074 MonoCachedClassInfo cached_info
;
4076 if (image_is_dynamic (m_class_get_image (klass
))) {
4078 * has_cctor is not set for these classes because mono_class_init_internal () is
4081 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
4082 mono_error_assert_msg_ok (error
, "Could not lookup class cctor in dynamic image");
4086 mono_class_init_internal (klass
);
4088 if (!m_class_has_cctor (klass
))
4091 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
4092 result
= mono_class_get_inflated_method (klass
, mono_class_get_cctor (mono_class_get_generic_class (klass
)->container_class
), error
);
4093 mono_error_assert_msg_ok (error
, "Could not lookup inflated class cctor"); /* FIXME do proper error handling */
4097 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
4098 result
= mono_get_method_checked (m_class_get_image (klass
), cached_info
.cctor_token
, klass
, NULL
, error
);
4099 mono_error_assert_msg_ok (error
, "Could not lookup class cctor from cached metadata");
4103 result
= mono_class_get_method_from_name_checked (klass
, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME
, error
);
4104 mono_error_assert_msg_ok (error
, "Could not lookup class cctor");
4109 * mono_class_get_finalizer:
4110 * \param klass: The MonoClass pointer
4112 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
4115 mono_class_get_finalizer (MonoClass
*klass
)
4117 MonoCachedClassInfo cached_info
;
4119 if (!m_class_is_inited (klass
))
4120 mono_class_init_internal (klass
);
4121 if (!mono_class_has_finalizer (klass
))
4124 if (mono_class_get_cached_class_info (klass
, &cached_info
)) {
4126 MonoMethod
*result
= mono_get_method_checked (cached_info
.finalize_image
, cached_info
.finalize_token
, NULL
, NULL
, error
);
4127 mono_error_assert_msg_ok (error
, "Could not lookup finalizer from cached metadata");
4130 mono_class_setup_vtable (klass
);
4131 return m_class_get_vtable (klass
) [mono_class_get_object_finalize_slot ()];
4136 * mono_class_needs_cctor_run:
4137 * \param klass the MonoClass pointer
4138 * \param caller a MonoMethod describing the caller
4140 * Determines whenever the class has a static constructor and whenever it
4141 * needs to be called when executing CALLER.
4144 mono_class_needs_cctor_run (MonoClass
*klass
, MonoMethod
*caller
)
4148 method
= mono_class_get_cctor (klass
);
4150 return (method
== caller
) ? FALSE
: TRUE
;
4156 * mono_class_array_element_size:
4159 * \returns The number of bytes an element of type \p klass uses when stored into an array.
4162 mono_class_array_element_size (MonoClass
*klass
)
4164 MonoType
*type
= m_class_get_byval_arg (klass
);
4167 switch (type
->type
) {
4170 case MONO_TYPE_BOOLEAN
:
4174 case MONO_TYPE_CHAR
:
4183 case MONO_TYPE_CLASS
:
4184 case MONO_TYPE_STRING
:
4185 case MONO_TYPE_OBJECT
:
4186 case MONO_TYPE_SZARRAY
:
4187 case MONO_TYPE_ARRAY
:
4188 return TARGET_SIZEOF_VOID_P
;
4193 case MONO_TYPE_VALUETYPE
:
4194 if (m_class_is_enumtype (type
->data
.klass
)) {
4195 type
= mono_class_enum_basetype_internal (type
->data
.klass
);
4196 klass
= m_class_get_element_class (klass
);
4199 return mono_class_value_size (klass
, NULL
);
4200 case MONO_TYPE_GENERICINST
:
4201 type
= m_class_get_byval_arg (type
->data
.generic_class
->container_class
);
4204 case MONO_TYPE_MVAR
: {
4207 return mono_type_size (type
, &align
);
4209 case MONO_TYPE_VOID
:
4213 g_error ("unknown type 0x%02x in mono_class_array_element_size", type
->type
);
4219 * mono_array_element_size:
4220 * \param ac pointer to a \c MonoArrayClass
4222 * \returns The size of single array element.
4224 * LOCKING: Acquires the loader lock.
4227 mono_array_element_size (MonoClass
*ac
)
4229 g_assert (m_class_get_rank (ac
));
4230 if (G_UNLIKELY (!m_class_is_size_inited (ac
))) {
4231 mono_class_setup_fields (ac
);
4233 return m_class_get_sizes (ac
).element_size
;
4240 mono_ldtoken (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4241 MonoGenericContext
*context
)
4244 gpointer res
= mono_ldtoken_checked (image
, token
, handle_class
, context
, error
);
4245 mono_error_assert_ok (error
);
4250 mono_ldtoken_checked (MonoImage
*image
, guint32 token
, MonoClass
**handle_class
,
4251 MonoGenericContext
*context
, MonoError
*error
)
4255 if (image_is_dynamic (image
)) {
4256 MonoClass
*tmp_handle_class
;
4257 gpointer obj
= mono_lookup_dynamic_token_class (image
, token
, TRUE
, &tmp_handle_class
, context
, error
);
4259 mono_error_assert_ok (error
);
4260 g_assert (tmp_handle_class
);
4262 *handle_class
= tmp_handle_class
;
4264 if (tmp_handle_class
== mono_defaults
.typehandle_class
)
4265 return m_class_get_byval_arg ((MonoClass
*)obj
);
4270 switch (token
& 0xff000000) {
4271 case MONO_TOKEN_TYPE_DEF
:
4272 case MONO_TOKEN_TYPE_REF
:
4273 case MONO_TOKEN_TYPE_SPEC
: {
4276 *handle_class
= mono_defaults
.typehandle_class
;
4277 type
= mono_type_get_checked (image
, token
, context
, error
);
4281 mono_class_init_internal (mono_class_from_mono_type_internal (type
));
4282 /* We return a MonoType* as handle */
4285 case MONO_TOKEN_FIELD_DEF
: {
4287 guint32 type
= mono_metadata_typedef_from_field (image
, mono_metadata_token_index (token
));
4289 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4293 *handle_class
= mono_defaults
.fieldhandle_class
;
4294 klass
= mono_class_get_and_inflate_typespec_checked (image
, MONO_TOKEN_TYPE_DEF
| type
, context
, error
);
4298 mono_class_init_internal (klass
);
4299 return mono_class_get_field (klass
, token
);
4301 case MONO_TOKEN_METHOD_DEF
:
4302 case MONO_TOKEN_METHOD_SPEC
: {
4304 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4306 *handle_class
= mono_defaults
.methodhandle_class
;
4312 case MONO_TOKEN_MEMBER_REF
: {
4313 guint32 cols
[MONO_MEMBERREF_SIZE
];
4315 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
4316 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
4317 mono_metadata_decode_blob_size (sig
, &sig
);
4318 if (*sig
== 0x6) { /* it's a field */
4320 MonoClassField
*field
;
4321 field
= mono_field_from_token_checked (image
, token
, &klass
, context
, error
);
4323 *handle_class
= mono_defaults
.fieldhandle_class
;
4327 meth
= mono_get_method_checked (image
, token
, NULL
, context
, error
);
4329 *handle_class
= mono_defaults
.methodhandle_class
;
4334 mono_error_set_bad_image (error
, image
, "Bad ldtoken %x", token
);
4340 mono_lookup_dynamic_token (MonoImage
*image
, guint32 token
, MonoGenericContext
*context
, MonoError
*error
)
4342 MonoClass
*handle_class
;
4344 return mono_reflection_lookup_dynamic_token (image
, token
, TRUE
, &handle_class
, context
, error
);
4348 mono_lookup_dynamic_token_class (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
, MonoError
*error
)
4350 return mono_reflection_lookup_dynamic_token (image
, token
, valid_token
, handle_class
, context
, error
);
4353 static MonoGetCachedClassInfo get_cached_class_info
= NULL
;
4356 mono_install_get_cached_class_info (MonoGetCachedClassInfo func
)
4358 get_cached_class_info
= func
;
4362 mono_class_get_cached_class_info (MonoClass
*klass
, MonoCachedClassInfo
*res
)
4364 if (!get_cached_class_info
)
4367 return get_cached_class_info (klass
, res
);
4371 mono_install_get_class_from_name (MonoGetClassFromName func
)
4373 get_class_from_name
= func
;
4377 * mono_class_get_image:
4379 * Use this method to get the \c MonoImage* where this class came from.
4381 * \returns The image where this class is defined.
4384 mono_class_get_image (MonoClass
*klass
)
4386 return m_class_get_image (klass
);
4390 * mono_class_get_element_class:
4391 * \param klass the \c MonoClass to act on
4393 * Use this function to get the element class of an array.
4395 * \returns The element class of an array.
4398 mono_class_get_element_class (MonoClass
*klass
)
4401 MONO_ENTER_GC_UNSAFE
;
4402 result
= m_class_get_element_class (klass
);
4403 MONO_EXIT_GC_UNSAFE
;
4408 * mono_class_is_valuetype:
4409 * \param klass the \c MonoClass to act on
4411 * Use this method to determine if the provided \c MonoClass* represents a value type,
4412 * or a reference type.
4414 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
4417 mono_class_is_valuetype (MonoClass
*klass
)
4420 MONO_ENTER_GC_UNSAFE
;
4421 result
= m_class_is_valuetype (klass
);
4422 MONO_EXIT_GC_UNSAFE
;
4427 * mono_class_is_enum:
4428 * \param klass the \c MonoClass to act on
4430 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
4432 * \returns TRUE if the \c MonoClass represents an enumeration.
4435 mono_class_is_enum (MonoClass
*klass
)
4438 MONO_ENTER_GC_UNSAFE
;
4439 result
= m_class_is_enumtype (klass
);
4440 MONO_EXIT_GC_UNSAFE
;
4445 * mono_class_enum_basetype_internal:
4446 * \param klass the \c MonoClass to act on
4448 * Use this function to get the underlying type for an enumeration value.
4450 * \returns The underlying type representation for an enumeration.
4453 mono_class_enum_basetype_internal (MonoClass
*klass
)
4455 if (m_class_get_element_class (klass
) == klass
)
4456 /* SRE or broken types */
4458 return m_class_get_byval_arg (m_class_get_element_class (klass
));
4462 * mono_class_enum_basetype:
4463 * \param klass the \c MonoClass to act on
4465 * Use this function to get the underlying type for an enumeration value.
4467 * \returns The underlying type representation for an enumeration.
4470 mono_class_enum_basetype (MonoClass
*klass
)
4473 MONO_ENTER_GC_UNSAFE
;
4474 res
= mono_class_enum_basetype_internal (klass
);
4475 MONO_EXIT_GC_UNSAFE
;
4480 * mono_class_get_parent
4481 * \param klass the \c MonoClass to act on
4483 * \returns The parent class for this class.
4486 mono_class_get_parent (MonoClass
*klass
)
4489 MONO_ENTER_GC_UNSAFE
;
4490 result
= m_class_get_parent (klass
);
4491 MONO_EXIT_GC_UNSAFE
;
4496 * mono_class_get_nesting_type:
4497 * \param klass the \c MonoClass to act on
4499 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
4501 * If the return is NULL, this indicates that this class is not nested.
4503 * \returns The container type where this type is nested or NULL if this type is not a nested type.
4506 mono_class_get_nesting_type (MonoClass
*klass
)
4508 return m_class_get_nested_in (klass
);
4512 * mono_class_get_rank:
4513 * \param klass the MonoClass to act on
4515 * \returns The rank for the array (the number of dimensions).
4518 mono_class_get_rank (MonoClass
*klass
)
4520 return m_class_get_rank (klass
);
4524 * mono_class_get_name
4525 * \param klass the \c MonoClass to act on
4527 * \returns The name of the class.
4530 mono_class_get_name (MonoClass
*klass
)
4533 MONO_ENTER_GC_UNSAFE
;
4534 result
= m_class_get_name (klass
);
4535 MONO_EXIT_GC_UNSAFE
;
4540 * mono_class_get_namespace:
4541 * \param klass the \c MonoClass to act on
4543 * \returns The namespace of the class.
4546 mono_class_get_namespace (MonoClass
*klass
)
4549 MONO_ENTER_GC_UNSAFE
;
4550 result
= m_class_get_name_space (klass
);
4551 MONO_EXIT_GC_UNSAFE
;
4556 * mono_class_get_type:
4557 * \param klass the \c MonoClass to act on
4559 * This method returns the internal \c MonoType representation for the class.
4561 * \returns The \c MonoType from the class.
4564 mono_class_get_type (MonoClass
*klass
)
4566 return m_class_get_byval_arg (klass
);
4570 * mono_class_get_type_token:
4571 * \param klass the \c MonoClass to act on
4573 * This method returns type token for the class.
4575 * \returns The type token for the class.
4578 mono_class_get_type_token (MonoClass
*klass
)
4580 return m_class_get_type_token (klass
);
4584 * mono_class_get_byref_type:
4585 * \param klass the \c MonoClass to act on
4590 mono_class_get_byref_type (MonoClass
*klass
)
4592 return m_class_get_this_arg (klass
);
4596 * mono_class_num_fields:
4597 * \param klass the \c MonoClass to act on
4599 * \returns The number of static and instance fields in the class.
4602 mono_class_num_fields (MonoClass
*klass
)
4604 return mono_class_get_field_count (klass
);
4608 * mono_class_num_methods:
4609 * \param klass the \c MonoClass to act on
4611 * \returns The number of methods in the class.
4614 mono_class_num_methods (MonoClass
*klass
)
4616 return mono_class_get_method_count (klass
);
4620 * mono_class_num_properties
4621 * \param klass the \c MonoClass to act on
4623 * \returns The number of properties in the class.
4626 mono_class_num_properties (MonoClass
*klass
)
4628 mono_class_setup_properties (klass
);
4630 return mono_class_get_property_info (klass
)->count
;
4634 * mono_class_num_events:
4635 * \param klass the \c MonoClass to act on
4637 * \returns The number of events in the class.
4640 mono_class_num_events (MonoClass
*klass
)
4642 mono_class_setup_events (klass
);
4644 return mono_class_get_event_info (klass
)->count
;
4648 * mono_class_get_fields:
4649 * \param klass the \c MonoClass to act on
4651 * This routine is an iterator routine for retrieving the fields in a class.
4653 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4654 * iterate over all of the elements. When no more values are
4655 * available, the return value is NULL.
4657 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
4660 mono_class_get_fields (MonoClass
* klass
, gpointer
*iter
)
4662 MonoClassField
*result
;
4663 MONO_ENTER_GC_UNSAFE
;
4664 result
= mono_class_get_fields_internal (klass
, iter
);
4665 MONO_EXIT_GC_UNSAFE
;
4670 mono_class_get_fields_internal (MonoClass
*klass
, gpointer
*iter
)
4672 MonoClassField
* field
;
4676 mono_class_setup_fields (klass
);
4677 if (mono_class_has_failure (klass
))
4679 /* start from the first */
4680 if (mono_class_get_field_count (klass
)) {
4681 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
4682 *iter
= &klass_fields
[0];
4683 return &klass_fields
[0];
4689 field
= (MonoClassField
*)*iter
;
4691 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
4699 * mono_class_get_methods:
4700 * \param klass the \c MonoClass to act on
4702 * This routine is an iterator routine for retrieving the fields in a class.
4704 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4705 * iterate over all of the elements. When no more values are
4706 * available, the return value is NULL.
4708 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
4711 mono_class_get_methods (MonoClass
* klass
, gpointer
*iter
)
4713 MonoMethod
** method
;
4717 mono_class_setup_methods (klass
);
4719 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
4721 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
4722 * FIXME we should better report this error to the caller
4726 /* start from the first */
4727 if (mono_class_get_method_count (klass
)) {
4728 *iter
= &klass_methods
[0];
4729 return klass_methods
[0];
4735 method
= (MonoMethod
**)*iter
;
4737 if (method
< &m_class_get_methods (klass
) [mono_class_get_method_count (klass
)]) {
4745 * mono_class_get_properties:
4746 * \param klass the \c MonoClass to act on
4748 * This routine is an iterator routine for retrieving the properties in a class.
4750 * You must pass a gpointer that points to zero and is treated as an opaque handle to
4751 * iterate over all of the elements. When no more values are
4752 * available, the return value is NULL.
4754 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
4757 mono_class_get_properties (MonoClass
* klass
, gpointer
*iter
)
4759 MonoProperty
* property
;
4763 mono_class_setup_properties (klass
);
4764 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4765 /* start from the first */
4767 *iter
= &info
->properties
[0];
4768 return (MonoProperty
*)*iter
;
4774 property
= (MonoProperty
*)*iter
;
4776 MonoClassPropertyInfo
*info
= mono_class_get_property_info (klass
);
4777 if (property
< &info
->properties
[info
->count
]) {
4779 return (MonoProperty
*)*iter
;
4785 * mono_class_get_events:
4786 * \param klass the \c MonoClass to act on
4788 * This routine is an iterator routine for retrieving the properties in a class.
4790 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4791 * iterate over all of the elements. When no more values are
4792 * available, the return value is NULL.
4794 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
4797 mono_class_get_events (MonoClass
* klass
, gpointer
*iter
)
4803 mono_class_setup_events (klass
);
4804 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4805 /* start from the first */
4807 *iter
= &info
->events
[0];
4808 return (MonoEvent
*)*iter
;
4814 event
= (MonoEvent
*)*iter
;
4816 MonoClassEventInfo
*info
= mono_class_get_event_info (klass
);
4817 if (event
< &info
->events
[info
->count
]) {
4819 return (MonoEvent
*)*iter
;
4825 * mono_class_get_interfaces
4826 * \param klass the \c MonoClass to act on
4828 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
4830 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4831 * iterate over all of the elements. When no more values are
4832 * available, the return value is NULL.
4834 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
4837 mono_class_get_interfaces (MonoClass
* klass
, gpointer
*iter
)
4844 if (!m_class_is_inited (klass
))
4845 mono_class_init_internal (klass
);
4846 if (!m_class_is_interfaces_inited (klass
)) {
4847 mono_class_setup_interfaces (klass
, error
);
4848 if (!mono_error_ok (error
)) {
4849 mono_error_cleanup (error
);
4853 /* start from the first */
4854 if (m_class_get_interface_count (klass
)) {
4855 *iter
= &m_class_get_interfaces (klass
) [0];
4856 return m_class_get_interfaces (klass
) [0];
4862 iface
= (MonoClass
**)*iter
;
4864 if (iface
< &m_class_get_interfaces (klass
) [m_class_get_interface_count (klass
)]) {
4872 * mono_class_get_nested_types
4873 * \param klass the \c MonoClass to act on
4875 * This routine is an iterator routine for retrieving the nested types of a class.
4876 * This works only if \p klass is non-generic, or a generic type definition.
4878 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
4879 * iterate over all of the elements. When no more values are
4880 * available, the return value is NULL.
4882 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
4885 mono_class_get_nested_types (MonoClass
* klass
, gpointer
*iter
)
4891 if (!m_class_is_nested_classes_inited (klass
))
4892 mono_class_setup_nested_types (klass
);
4895 GList
*nested_classes
= mono_class_get_nested_classes_property (klass
);
4896 /* start from the first */
4897 if (nested_classes
) {
4898 *iter
= nested_classes
;
4899 return (MonoClass
*)nested_classes
->data
;
4901 /* no nested types */
4905 item
= (GList
*)*iter
;
4909 return (MonoClass
*)item
->data
;
4916 * mono_class_is_delegate
4917 * \param klass the \c MonoClass to act on
4919 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
4922 mono_class_is_delegate (MonoClass
*klass
)
4925 MONO_ENTER_GC_UNSAFE
;
4926 result
= m_class_is_delegate (klass
);
4927 MONO_EXIT_GC_UNSAFE
;
4932 * mono_class_implements_interface
4933 * \param klass The MonoClass to act on
4934 * \param interface The interface to check if \p klass implements.
4936 * \returns TRUE if \p klass implements \p interface.
4939 mono_class_implements_interface (MonoClass
* klass
, MonoClass
* iface
)
4941 return mono_class_is_assignable_from_internal (iface
, klass
);
4945 class_implements_interface_ignore_generics (MonoClass
* klass
, MonoClass
* iface
)
4949 if (mono_class_is_ginst (iface
))
4950 iface
= mono_class_get_generic_type_definition (iface
);
4951 while (klass
!= NULL
) {
4952 if (mono_class_is_assignable_from_internal (iface
, klass
))
4954 mono_class_setup_interfaces (klass
, error
);
4955 if (!is_ok (error
)) {
4956 mono_error_cleanup (error
);
4959 MonoClass
**klass_interfaces
= m_class_get_interfaces (klass
);
4960 for (i
= 0; i
< m_class_get_interface_count (klass
); i
++) {
4961 MonoClass
*ic
= klass_interfaces
[i
];
4962 if (mono_class_is_ginst (ic
))
4963 ic
= mono_class_get_generic_type_definition (ic
);
4968 klass
= m_class_get_parent (klass
);
4975 * mono_field_get_name:
4976 * \param field the \c MonoClassField to act on
4978 * \returns The name of the field.
4981 mono_field_get_name (MonoClassField
*field
)
4987 * mono_field_get_type_internal:
4988 * \param field the \c MonoClassField to act on
4989 * \returns \c MonoType of the field.
4992 mono_field_get_type_internal (MonoClassField
*field
)
4994 MonoType
*type
= field
->type
;
4999 type
= mono_field_get_type_checked (field
, error
);
5000 if (!mono_error_ok (error
)) {
5001 mono_trace_warning (MONO_TRACE_TYPE
, "Could not load field's type due to %s", mono_error_get_message (error
));
5002 mono_error_cleanup (error
);
5008 * mono_field_get_type:
5009 * \param field the \c MonoClassField to act on
5010 * \returns \c MonoType of the field.
5013 mono_field_get_type (MonoClassField
*field
)
5015 MonoType
*type
= field
->type
;
5019 MONO_ENTER_GC_UNSAFE
;
5020 type
= mono_field_get_type_internal (field
);
5021 MONO_EXIT_GC_UNSAFE
;
5026 * mono_field_get_type_checked:
5027 * \param field the \c MonoClassField to act on
5028 * \param error used to return any error found while retrieving \p field type
5030 * \returns \c MonoType of the field.
5033 mono_field_get_type_checked (MonoClassField
*field
, MonoError
*error
)
5036 MonoType
*type
= field
->type
;
5039 mono_field_resolve_type (field
, error
);
5044 * mono_field_get_parent:
5045 * \param field the \c MonoClassField to act on
5047 * \returns \c MonoClass where the field was defined.
5050 mono_field_get_parent (MonoClassField
*field
)
5052 return field
->parent
;
5056 * mono_field_get_flags;
5057 * \param field the \c MonoClassField to act on
5059 * The metadata flags for a field are encoded using the
5060 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5062 * \returns The flags for the field.
5065 mono_field_get_flags (MonoClassField
*field
)
5068 return mono_field_resolve_flags (field
);
5069 return field
->type
->attrs
;
5073 * mono_field_get_offset:
5074 * \param field the \c MonoClassField to act on
5076 * \returns The field offset.
5079 mono_field_get_offset (MonoClassField
*field
)
5081 mono_class_setup_fields(field
->parent
);
5082 return field
->offset
;
5086 mono_field_get_rva (MonoClassField
*field
)
5090 MonoClass
*klass
= field
->parent
;
5091 MonoFieldDefaultValue
*def_values
;
5093 g_assert (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
);
5095 def_values
= mono_class_get_field_def_values (klass
);
5097 def_values
= (MonoFieldDefaultValue
*)mono_class_alloc0 (klass
, sizeof (MonoFieldDefaultValue
) * mono_class_get_field_count (klass
));
5099 mono_class_set_field_def_values (klass
, def_values
);
5102 field_index
= mono_field_get_index (field
);
5104 if (!def_values
[field_index
].data
&& !image_is_dynamic (m_class_get_image (klass
))) {
5105 int first_field_idx
= mono_class_get_first_field_idx (klass
);
5106 mono_metadata_field_info (m_class_get_image (field
->parent
), first_field_idx
+ field_index
, NULL
, &rva
, NULL
);
5108 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field
), m_class_get_name (field
->parent
));
5109 def_values
[field_index
].data
= mono_image_rva_map (m_class_get_image (field
->parent
), rva
);
5112 return def_values
[field_index
].data
;
5116 * mono_field_get_data:
5117 * \param field the \c MonoClassField to act on
5119 * \returns A pointer to the metadata constant value or to the field
5120 * data if it has an RVA flag.
5123 mono_field_get_data (MonoClassField
*field
)
5125 if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
) {
5126 MonoTypeEnum def_type
;
5128 return mono_class_get_field_default_value (field
, &def_type
);
5129 } else if (field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
5130 return mono_field_get_rva (field
);
5137 * mono_property_get_name:
5138 * \param prop the \c MonoProperty to act on
5139 * \returns The name of the property
5142 mono_property_get_name (MonoProperty
*prop
)
5148 * mono_property_get_set_method
5149 * \param prop the \c MonoProperty to act on.
5150 * \returns The setter method of the property, a \c MonoMethod.
5153 mono_property_get_set_method (MonoProperty
*prop
)
5159 * mono_property_get_get_method
5160 * \param prop the MonoProperty to act on.
5161 * \returns The getter method of the property (A \c MonoMethod)
5164 mono_property_get_get_method (MonoProperty
*prop
)
5170 * mono_property_get_parent:
5171 * \param prop the \c MonoProperty to act on.
5172 * \returns The \c MonoClass where the property was defined.
5175 mono_property_get_parent (MonoProperty
*prop
)
5177 return prop
->parent
;
5181 * mono_property_get_flags:
5182 * \param prop the \c MonoProperty to act on.
5184 * The metadata flags for a property are encoded using the
5185 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
5187 * \returns The flags for the property.
5190 mono_property_get_flags (MonoProperty
*prop
)
5196 * mono_event_get_name:
5197 * \param event the MonoEvent to act on
5198 * \returns The name of the event.
5201 mono_event_get_name (MonoEvent
*event
)
5207 * mono_event_get_add_method:
5208 * \param event The \c MonoEvent to act on.
5209 * \returns The \c add method for the event, a \c MonoMethod.
5212 mono_event_get_add_method (MonoEvent
*event
)
5218 * mono_event_get_remove_method:
5219 * \param event The \c MonoEvent to act on.
5220 * \returns The \c remove method for the event, a \c MonoMethod.
5223 mono_event_get_remove_method (MonoEvent
*event
)
5225 return event
->remove
;
5229 * mono_event_get_raise_method:
5230 * \param event The \c MonoEvent to act on.
5231 * \returns The \c raise method for the event, a \c MonoMethod.
5234 mono_event_get_raise_method (MonoEvent
*event
)
5236 return event
->raise
;
5240 * mono_event_get_parent:
5241 * \param event the MonoEvent to act on.
5242 * \returns The \c MonoClass where the event is defined.
5245 mono_event_get_parent (MonoEvent
*event
)
5247 return event
->parent
;
5251 * mono_event_get_flags
5252 * \param event the \c MonoEvent to act on.
5254 * The metadata flags for an event are encoded using the
5255 * \c EVENT_* constants. See the \c tabledefs.h file for details.
5257 * \returns The flags for the event.
5260 mono_event_get_flags (MonoEvent
*event
)
5262 return event
->attrs
;
5266 * mono_class_get_method_from_name:
5267 * \param klass where to look for the method
5268 * \param name name of the method
5269 * \param param_count number of parameters. -1 for any number.
5271 * Obtains a \c MonoMethod with a given name and number of parameters.
5272 * It only works if there are no multiple signatures for any given method name.
5275 mono_class_get_method_from_name (MonoClass
*klass
, const char *name
, int param_count
)
5278 MONO_ENTER_GC_UNSAFE
;
5280 result
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, 0, error
);
5281 mono_error_cleanup (error
);
5282 MONO_EXIT_GC_UNSAFE
;
5287 mono_find_method_in_metadata (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5289 MonoImage
*klass_image
= m_class_get_image (klass
);
5290 MonoMethod
*res
= NULL
;
5293 /* Search directly in the metadata to avoid calling setup_methods () */
5294 int first_idx
= mono_class_get_first_method_idx (klass
);
5295 int mcount
= mono_class_get_method_count (klass
);
5296 for (i
= 0; i
< mcount
; ++i
) {
5298 guint32 cols
[MONO_METHOD_SIZE
];
5300 MonoMethodSignature
*sig
;
5302 /* first_idx points into the methodptr table */
5303 mono_metadata_decode_table_row (klass_image
, MONO_TABLE_METHOD
, first_idx
+ i
, cols
, MONO_METHOD_SIZE
);
5305 if (!strcmp (mono_metadata_string_heap (klass_image
, cols
[MONO_METHOD_NAME
]), name
)) {
5306 method
= mono_get_method_checked (klass_image
, MONO_TOKEN_METHOD_DEF
| (first_idx
+ i
+ 1), klass
, NULL
, error
);
5308 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5311 if (param_count
== -1) {
5315 sig
= mono_method_signature_checked (method
, error
);
5317 mono_error_cleanup (error
); /* FIXME don't swallow the error */
5320 if (sig
->param_count
== param_count
) {
5331 * mono_class_get_method_from_name_flags:
5332 * \param klass where to look for the method
5333 * \param name_space name of the method
5334 * \param param_count number of parameters. -1 for any number.
5335 * \param flags flags which must be set in the method
5337 * Obtains a \c MonoMethod with a given name and number of parameters.
5338 * It only works if there are no multiple signatures for any given method name.
5341 mono_class_get_method_from_name_flags (MonoClass
*klass
, const char *name
, int param_count
, int flags
)
5344 MONO_ENTER_GC_UNSAFE
;
5346 method
= mono_class_get_method_from_name_checked (klass
, name
, param_count
, flags
, error
);
5347 mono_error_cleanup (error
);
5348 MONO_EXIT_GC_UNSAFE
;
5353 * mono_class_get_method_from_name_checked:
5354 * \param klass where to look for the method
5355 * \param name_space name of the method
5356 * \param param_count number of parameters. -1 for any number.
5357 * \param flags flags which must be set in the method
5360 * Obtains a \c MonoMethod with a given name and number of parameters.
5361 * It only works if there are no multiple signatures for any given method name.
5364 mono_class_get_method_from_name_checked (MonoClass
*klass
, const char *name
,
5365 int param_count
, int flags
, MonoError
*error
)
5367 MonoMethod
*res
= NULL
;
5370 mono_class_init_internal (klass
);
5372 if (mono_class_is_ginst (klass
) && !m_class_get_methods (klass
)) {
5373 res
= mono_class_get_method_from_name_checked (mono_class_get_generic_class (klass
)->container_class
, name
, param_count
, flags
, error
);
5376 res
= mono_class_inflate_generic_method_full_checked (res
, klass
, mono_class_get_context (klass
), error
);
5381 if (m_class_get_methods (klass
) || !MONO_CLASS_HAS_STATIC_METADATA (klass
)) {
5382 mono_class_setup_methods (klass
);
5384 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
5385 See mono/tests/array_load_exception.il
5386 FIXME we should better report this error to the caller
5388 MonoMethod
**klass_methods
= m_class_get_methods (klass
);
5391 int mcount
= mono_class_get_method_count (klass
);
5392 for (i
= 0; i
< mcount
; ++i
) {
5393 MonoMethod
*method
= klass_methods
[i
];
5395 if (method
->name
[0] == name
[0] &&
5396 !strcmp (name
, method
->name
) &&
5397 (param_count
== -1 || mono_method_signature_internal (method
)->param_count
== param_count
) &&
5398 ((method
->flags
& flags
) == flags
)) {
5405 res
= mono_find_method_in_metadata (klass
, name
, param_count
, flags
);
5412 mono_class_has_failure (const MonoClass
*klass
)
5414 g_assert (klass
!= NULL
);
5415 return m_class_has_failure ((MonoClass
*)klass
) != 0;
5420 * mono_class_set_type_load_failure:
5421 * \param klass class in which the failure was detected
5422 * \param fmt \c printf -style error message string.
5424 * Collect detected failure informaion in the class for later processing.
5425 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
5426 * Note that only the first failure is kept.
5428 * LOCKING: Acquires the loader lock.
5430 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
5433 mono_class_set_type_load_failure (MonoClass
*klass
, const char * fmt
, ...)
5435 ERROR_DECL (prepare_error
);
5438 if (mono_class_has_failure (klass
))
5441 va_start (args
, fmt
);
5442 mono_error_vset_type_load_class (prepare_error
, klass
, fmt
, args
);
5445 MonoErrorBoxed
*box
= mono_error_box (prepare_error
, m_class_get_image (klass
));
5446 mono_error_cleanup (prepare_error
);
5447 return mono_class_set_failure (klass
, box
);
5451 * mono_class_get_exception_for_failure:
5452 * \param klass class in which the failure was detected
5454 * \returns a constructed MonoException than the caller can then throw
5455 * using mono_raise_exception - or NULL if no failure is present (or
5456 * doesn't result in an exception).
5459 mono_class_get_exception_for_failure (MonoClass
*klass
)
5461 if (!mono_class_has_failure (klass
))
5463 ERROR_DECL (unboxed_error
);
5464 mono_error_set_for_class_failure (unboxed_error
, klass
);
5465 return mono_error_convert_to_exception (unboxed_error
);
5469 is_nesting_type (MonoClass
*outer_klass
, MonoClass
*inner_klass
)
5471 outer_klass
= mono_class_get_generic_type_definition (outer_klass
);
5472 inner_klass
= mono_class_get_generic_type_definition (inner_klass
);
5474 if (outer_klass
== inner_klass
)
5476 inner_klass
= m_class_get_nested_in (inner_klass
);
5477 } while (inner_klass
);
5482 mono_class_get_generic_type_definition (MonoClass
*klass
)
5484 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5485 return gklass
? gklass
->container_class
: klass
;
5489 * Check if @klass is a subtype of @parent ignoring generic instantiations.
5491 * Generic instantiations are ignored for all super types of @klass.
5493 * Visibility checks ignoring generic instantiations.
5495 * Class implementing interface visibility checks ignore generic instantiations
5498 mono_class_has_parent_and_ignore_generics (MonoClass
*klass
, MonoClass
*parent
)
5501 klass
= mono_class_get_generic_type_definition (klass
);
5502 parent
= mono_class_get_generic_type_definition (parent
);
5503 mono_class_setup_supertypes (klass
);
5505 for (i
= 0; i
< m_class_get_idepth (klass
); ++i
) {
5506 if (parent
== mono_class_get_generic_type_definition (m_class_get_supertypes (klass
) [i
]))
5510 if (MONO_CLASS_IS_INTERFACE_INTERNAL (parent
) && class_implements_interface_ignore_generics (klass
, parent
))
5516 * Subtype can only access parent members with family protection if the site object
5517 * is subclass of Subtype. For example:
5518 * class A { protected int x; }
5520 * void valid_access () {
5524 * void invalid_access () {
5531 is_valid_family_access (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
*context_klass
)
5533 if (MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && !MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5534 /* Can happen with default interface methods */
5535 if (!class_implements_interface_ignore_generics (access_klass
, member_klass
))
5537 } else if (member_klass
!= access_klass
&& MONO_CLASS_IS_INTERFACE_INTERNAL (member_klass
) && MONO_CLASS_IS_INTERFACE_INTERNAL (access_klass
)) {
5538 /* Can happen with default interface methods */
5539 if (!mono_interface_implements_interface (access_klass
, member_klass
))
5542 if (!mono_class_has_parent_and_ignore_generics (access_klass
, member_klass
))
5546 if (context_klass
== NULL
)
5548 /*if access_klass is not member_klass context_klass must be type compat*/
5549 if (access_klass
!= member_klass
&& !mono_class_has_parent_and_ignore_generics (context_klass
, access_klass
))
5555 can_access_internals (MonoAssembly
*accessing
, MonoAssembly
* accessed
)
5558 if (accessing
== accessed
)
5560 if (!accessed
|| !accessing
)
5563 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
5564 * anywhere so untrusted friends are not safe to access platform's code internals */
5565 if (mono_security_core_clr_enabled ()) {
5566 if (!mono_security_core_clr_can_access_internals (accessing
->image
, accessed
->image
))
5570 mono_assembly_load_friends (accessed
);
5571 for (tmp
= accessed
->friend_assembly_names
; tmp
; tmp
= tmp
->next
) {
5572 MonoAssemblyName
*friend_
= (MonoAssemblyName
*)tmp
->data
;
5573 /* Be conservative with checks */
5576 if (g_ascii_strcasecmp (accessing
->aname
.name
, friend_
->name
))
5578 if (friend_
->public_key_token
[0]) {
5579 if (!accessing
->aname
.public_key_token
[0])
5581 if (!mono_public_tokens_are_equal (friend_
->public_key_token
, accessing
->aname
.public_key_token
))
5590 * If klass is a generic type or if it is derived from a generic type, return the
5591 * MonoClass of the generic definition
5592 * Returns NULL if not found
5595 get_generic_definition_class (MonoClass
*klass
)
5598 MonoGenericClass
*gklass
= mono_class_try_get_generic_class (klass
);
5599 if (gklass
&& gklass
->container_class
)
5600 return gklass
->container_class
;
5601 klass
= m_class_get_parent (klass
);
5607 can_access_instantiation (MonoClass
*access_klass
, MonoGenericInst
*ginst
)
5610 for (i
= 0; i
< ginst
->type_argc
; ++i
) {
5611 MonoType
*type
= ginst
->type_argv
[i
];
5612 switch (type
->type
) {
5613 case MONO_TYPE_SZARRAY
:
5614 if (!can_access_type (access_klass
, type
->data
.klass
))
5617 case MONO_TYPE_ARRAY
:
5618 if (!can_access_type (access_klass
, type
->data
.array
->eklass
))
5622 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
->data
.type
)))
5625 case MONO_TYPE_CLASS
:
5626 case MONO_TYPE_VALUETYPE
:
5627 case MONO_TYPE_GENERICINST
:
5628 if (!can_access_type (access_klass
, mono_class_from_mono_type_internal (type
)))
5638 can_access_type (MonoClass
*access_klass
, MonoClass
*member_klass
)
5642 if (access_klass
== member_klass
)
5645 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5646 MonoAssembly
*member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5648 if (access_klass_assembly
&& m_class_get_image (access_klass
)->assembly
->corlib_internal
)
5651 if (m_class_get_element_class (access_klass
) && !m_class_is_enumtype (access_klass
)) {
5652 access_klass
= m_class_get_element_class (access_klass
);
5653 access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5656 if (m_class_get_element_class (member_klass
) && !m_class_is_enumtype (member_klass
)) {
5657 member_klass
= m_class_get_element_class (member_klass
);
5658 member_klass_assembly
= m_class_get_image (member_klass
)->assembly
;
5661 access_level
= mono_class_get_flags (member_klass
) & TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5663 if (mono_type_is_generic_argument (m_class_get_byval_arg (member_klass
)))
5666 if (mono_class_is_ginst (member_klass
) && !can_access_instantiation (access_klass
, mono_class_get_generic_class (member_klass
)->context
.class_inst
))
5669 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
)))
5672 /*Non nested type with nested visibility. We just fail it.*/
5673 if (access_level
>= TYPE_ATTRIBUTE_NESTED_PRIVATE
&& access_level
<= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
&& m_class_get_nested_in (member_klass
) == NULL
)
5676 MonoClass
*member_klass_nested_in
= m_class_get_nested_in (member_klass
);
5677 switch (access_level
) {
5678 case TYPE_ATTRIBUTE_NOT_PUBLIC
:
5679 return can_access_internals (access_klass_assembly
, member_klass_assembly
);
5681 case TYPE_ATTRIBUTE_PUBLIC
:
5684 case TYPE_ATTRIBUTE_NESTED_PUBLIC
:
5685 return member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5687 case TYPE_ATTRIBUTE_NESTED_PRIVATE
:
5688 return is_nesting_type (member_klass
, access_klass
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5690 case TYPE_ATTRIBUTE_NESTED_FAMILY
:
5691 return mono_class_has_parent_and_ignore_generics (access_klass
, m_class_get_nested_in (member_klass
));
5693 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY
:
5694 return can_access_internals (access_klass_assembly
, member_klass_assembly
) && member_klass_nested_in
&& can_access_type (access_klass
, member_klass_nested_in
);
5696 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM
:
5697 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) &&
5698 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5700 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM
:
5701 return can_access_internals (access_klass_assembly
, m_class_get_image (member_klass_nested_in
)->assembly
) ||
5702 mono_class_has_parent_and_ignore_generics (access_klass
, member_klass_nested_in
);
5707 /* FIXME: check visibility of type, too */
5709 can_access_member (MonoClass
*access_klass
, MonoClass
*member_klass
, MonoClass
* context_klass
, int access_level
)
5711 MonoClass
*member_generic_def
;
5712 MonoAssembly
*access_klass_assembly
= m_class_get_image (access_klass
)->assembly
;
5713 if (access_klass_assembly
&& access_klass_assembly
->corlib_internal
)
5716 MonoGenericClass
*access_gklass
= mono_class_try_get_generic_class (access_klass
);
5717 if (((access_gklass
&& access_gklass
->container_class
) ||
5718 mono_class_is_gtd (access_klass
)) &&
5719 (member_generic_def
= get_generic_definition_class (member_klass
))) {
5720 MonoClass
*access_container
;
5722 if (mono_class_is_gtd (access_klass
))
5723 access_container
= access_klass
;
5725 access_container
= access_gklass
->container_class
;
5727 if (can_access_member (access_container
, member_generic_def
, context_klass
, access_level
))
5731 MonoImage
*member_klass_image
= m_class_get_image (member_klass
);
5732 /* Partition I 8.5.3.2 */
5733 /* the access level values are the same for fields and methods */
5734 switch (access_level
) {
5735 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED
:
5736 /* same compilation unit */
5737 return m_class_get_image (access_klass
) == member_klass_image
;
5738 case FIELD_ATTRIBUTE_PRIVATE
:
5739 return access_klass
== member_klass
;
5740 case FIELD_ATTRIBUTE_FAM_AND_ASSEM
:
5741 if (is_valid_family_access (access_klass
, member_klass
, context_klass
) &&
5742 can_access_internals (access_klass_assembly
, member_klass_image
->assembly
))
5745 case FIELD_ATTRIBUTE_ASSEMBLY
:
5746 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5747 case FIELD_ATTRIBUTE_FAMILY
:
5748 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5751 case FIELD_ATTRIBUTE_FAM_OR_ASSEM
:
5752 if (is_valid_family_access (access_klass
, member_klass
, context_klass
))
5754 return can_access_internals (access_klass_assembly
, member_klass_image
->assembly
);
5755 case FIELD_ATTRIBUTE_PUBLIC
:
5762 * mono_method_can_access_field:
5763 * \param method Method that will attempt to access the field
5764 * \param field the field to access
5766 * Used to determine if a method is allowed to access the specified field.
5768 * \returns TRUE if the given \p method is allowed to access the \p field while following
5769 * the accessibility rules of the CLI.
5772 mono_method_can_access_field (MonoMethod
*method
, MonoClassField
*field
)
5774 /* FIXME: check all overlapping fields */
5775 int can
= can_access_member (method
->klass
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5777 MonoClass
*nested
= m_class_get_nested_in (method
->klass
);
5779 can
= can_access_member (nested
, field
->parent
, NULL
, mono_field_get_type_internal (field
)->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5782 nested
= m_class_get_nested_in (nested
);
5789 mono_method_get_method_definition (MonoMethod
*method
)
5791 while (method
->is_inflated
)
5792 method
= ((MonoMethodInflated
*)method
)->declaring
;
5797 * mono_method_can_access_method:
5798 * \param method Method that will attempt to access the other method
5799 * \param called the method that we want to probe for accessibility.
5801 * Used to determine if the \p method is allowed to access the specified \p called method.
5803 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
5804 * the accessibility rules of the CLI.
5807 mono_method_can_access_method (MonoMethod
*method
, MonoMethod
*called
)
5809 method
= mono_method_get_method_definition (method
);
5810 called
= mono_method_get_method_definition (called
);
5811 return mono_method_can_access_method_full (method
, called
, NULL
);
5815 * mono_method_can_access_method_full:
5816 * @method: The caller method
5817 * @called: The called method
5818 * @context_klass: The static type on stack of the owner @called object used
5820 * This function must be used with instance calls, as they have more strict family accessibility.
5821 * It can be used with static methods, but context_klass should be NULL.
5823 * Returns: TRUE if caller have proper visibility and acessibility to @called
5826 mono_method_can_access_method_full (MonoMethod
*method
, MonoMethod
*called
, MonoClass
*context_klass
)
5828 /* Wrappers are except from access checks */
5829 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
|| called
->wrapper_type
!= MONO_WRAPPER_NONE
)
5832 MonoClass
*access_class
= method
->klass
;
5833 MonoClass
*member_class
= called
->klass
;
5834 int can
= can_access_member (access_class
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5836 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5838 can
= can_access_member (nested
, member_class
, context_klass
, called
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
);
5841 nested
= m_class_get_nested_in (nested
);
5848 can
= can_access_type (access_class
, member_class
);
5850 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5852 can
= can_access_type (nested
, member_class
);
5855 nested
= m_class_get_nested_in (nested
);
5862 if (called
->is_inflated
) {
5863 MonoMethodInflated
* infl
= (MonoMethodInflated
*)called
;
5864 if (infl
->context
.method_inst
&& !can_access_instantiation (access_class
, infl
->context
.method_inst
))
5873 * mono_method_can_access_field_full:
5874 * @method: The caller method
5875 * @field: The accessed field
5876 * @context_klass: The static type on stack of the owner @field object used
5878 * This function must be used with instance fields, as they have more strict family accessibility.
5879 * It can be used with static fields, but context_klass should be NULL.
5881 * Returns: TRUE if caller have proper visibility and acessibility to @field
5884 mono_method_can_access_field_full (MonoMethod
*method
, MonoClassField
*field
, MonoClass
*context_klass
)
5886 MonoClass
*access_class
= method
->klass
;
5887 MonoClass
*member_class
= field
->parent
;
5888 /* FIXME: check all overlapping fields */
5889 int can
= can_access_member (access_class
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5891 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5893 can
= can_access_member (nested
, member_class
, context_klass
, field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
);
5896 nested
= m_class_get_nested_in (nested
);
5903 can
= can_access_type (access_class
, member_class
);
5905 MonoClass
*nested
= m_class_get_nested_in (access_class
);
5907 can
= can_access_type (nested
, member_class
);
5910 nested
= m_class_get_nested_in (nested
);
5920 * mono_class_can_access_class:
5921 * @source_class: The source class
5922 * @target_class: The accessed class
5924 * This function returns is @target_class is visible to @source_class
5926 * Returns: TRUE if source have proper visibility and acessibility to target
5929 mono_class_can_access_class (MonoClass
*source_class
, MonoClass
*target_class
)
5931 return can_access_type (source_class
, target_class
);
5935 * mono_type_is_valid_enum_basetype:
5936 * \param type The MonoType to check
5937 * \returns TRUE if the type can be used as the basetype of an enum
5939 gboolean
mono_type_is_valid_enum_basetype (MonoType
* type
) {
5940 switch (type
->type
) {
5943 case MONO_TYPE_BOOLEAN
:
5946 case MONO_TYPE_CHAR
:
5964 * mono_class_is_valid_enum:
5965 * \param klass An enum class to be validated
5967 * This method verify the required properties an enum should have.
5969 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
5970 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
5971 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
5973 * \returns TRUE if the informed enum class is valid
5976 mono_class_is_valid_enum (MonoClass
*klass
)
5978 MonoClassField
* field
;
5979 gpointer iter
= NULL
;
5980 gboolean found_base_field
= FALSE
;
5982 g_assert (m_class_is_enumtype (klass
));
5983 MonoClass
*klass_parent
= m_class_get_parent (klass
);
5984 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
5985 if (!klass_parent
|| strcmp (m_class_get_name (klass_parent
), "Enum") || strcmp (m_class_get_name_space (klass_parent
), "System") ) {
5989 if (!mono_class_is_auto_layout (klass
))
5992 while ((field
= mono_class_get_fields_internal (klass
, &iter
))) {
5993 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)) {
5994 if (found_base_field
)
5996 found_base_field
= TRUE
;
5997 if (!mono_type_is_valid_enum_basetype (field
->type
))
6002 if (!found_base_field
)
6005 if (mono_class_get_method_count (klass
) > 0)
6012 mono_generic_class_is_generic_type_definition (MonoGenericClass
*gklass
)
6014 return gklass
->context
.class_inst
== mono_class_get_generic_container (gklass
->container_class
)->context
.class_inst
;
6018 mono_field_resolve_type (MonoClassField
*field
, MonoError
*error
)
6020 MonoClass
*klass
= field
->parent
;
6021 MonoImage
*image
= m_class_get_image (klass
);
6022 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
6024 int field_idx
= field
- m_class_get_fields (klass
);
6029 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
6030 MonoType
*gtype
= mono_field_get_type_checked (gfield
, error
);
6031 if (!mono_error_ok (error
)) {
6032 char *full_name
= mono_type_get_full_name (gtd
);
6033 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
));
6037 ftype
= mono_class_inflate_generic_type_no_copy (image
, gtype
, mono_class_get_context (klass
), error
);
6038 if (!mono_error_ok (error
)) {
6039 char *full_name
= mono_type_get_full_name (klass
);
6040 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
));
6045 guint32 cols
[MONO_FIELD_SIZE
];
6046 MonoGenericContainer
*container
= NULL
;
6047 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
6049 /*FIXME, in theory we do not lazy load SRE fields*/
6050 g_assert (!image_is_dynamic (image
));
6052 if (mono_class_is_gtd (klass
)) {
6053 container
= mono_class_get_generic_container (klass
);
6055 container
= mono_class_get_generic_container (gtd
);
6056 g_assert (container
);
6059 /* first_field_idx and idx points into the fieldptr table */
6060 mono_metadata_decode_table_row (image
, MONO_TABLE_FIELD
, idx
, cols
, MONO_FIELD_SIZE
);
6062 if (!mono_verifier_verify_field_signature (image
, cols
[MONO_FIELD_SIGNATURE
], error
)) {
6063 mono_class_set_type_load_failure (klass
, "%s", mono_error_get_message (error
));
6067 sig
= mono_metadata_blob_heap (image
, cols
[MONO_FIELD_SIGNATURE
]);
6069 mono_metadata_decode_value (sig
, &sig
);
6070 /* FIELD signature == 0x06 */
6071 g_assert (*sig
== 0x06);
6073 ftype
= mono_metadata_parse_type_checked (image
, container
, cols
[MONO_FIELD_FLAGS
], FALSE
, sig
+ 1, &sig
, error
);
6075 char *full_name
= mono_type_get_full_name (klass
);
6076 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
));
6080 mono_memory_barrier ();
6081 field
->type
= ftype
;
6085 mono_field_resolve_flags (MonoClassField
*field
)
6087 MonoClass
*klass
= field
->parent
;
6088 MonoImage
*image
= m_class_get_image (klass
);
6089 MonoClass
*gtd
= mono_class_is_ginst (klass
) ? mono_class_get_generic_type_definition (klass
) : NULL
;
6090 int field_idx
= field
- m_class_get_fields (klass
);
6093 MonoClassField
*gfield
= &m_class_get_fields (gtd
) [field_idx
];
6094 return mono_field_get_flags (gfield
);
6096 int idx
= mono_class_get_first_field_idx (klass
) + field_idx
;
6098 /*FIXME, in theory we do not lazy load SRE fields*/
6099 g_assert (!image_is_dynamic (image
));
6101 return mono_metadata_decode_table_row_col (image
, MONO_TABLE_FIELD
, idx
, MONO_FIELD_FLAGS
);
6106 * mono_class_get_fields_lazy:
6107 * \param klass the MonoClass to act on
6109 * This routine is an iterator routine for retrieving the fields in a class.
6110 * Only minimal information about fields are loaded. Accessors must be used
6111 * for all MonoClassField returned.
6113 * You must pass a gpointer that points to zero and is treated as an opaque handle to
6114 * iterate over all of the elements. When no more values are
6115 * available, the return value is NULL.
6117 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
6120 mono_class_get_fields_lazy (MonoClass
* klass
, gpointer
*iter
)
6122 MonoClassField
* field
;
6126 mono_class_setup_basic_field_info (klass
);
6127 MonoClassField
*klass_fields
= m_class_get_fields (klass
);
6130 /* start from the first */
6131 if (mono_class_get_field_count (klass
)) {
6132 *iter
= &klass_fields
[0];
6133 return (MonoClassField
*)*iter
;
6139 field
= (MonoClassField
*)*iter
;
6141 if (field
< &m_class_get_fields (klass
) [mono_class_get_field_count (klass
)]) {
6143 return (MonoClassField
*)*iter
;
6149 mono_class_full_name (MonoClass
*klass
)
6151 return mono_type_full_name (m_class_get_byval_arg (klass
));
6154 /* Declare all shared lazy type lookup functions */
6155 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle
, "System.Runtime.InteropServices", "SafeHandle")
6158 * mono_method_get_base_method:
6159 * \param method a method
6160 * \param definition if true, get the definition
6161 * \param error set on failure
6163 * Given a virtual method associated with a subclass, return the corresponding
6164 * method from an ancestor. If \p definition is FALSE, returns the method in the
6165 * superclass of the given method. If \p definition is TRUE, return the method
6166 * in the ancestor class where it was first declared. The type arguments will
6167 * be inflated in the ancestor classes. If the method is not associated with a
6168 * class, or isn't virtual, returns the method itself. On failure returns NULL
6169 * and sets \p error.
6172 mono_method_get_base_method (MonoMethod
*method
, gboolean definition
, MonoError
*error
)
6174 MonoClass
*klass
, *parent
;
6175 MonoGenericContext
*generic_inst
= NULL
;
6176 MonoMethod
*result
= NULL
;
6179 if (method
->klass
== NULL
)
6182 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
6183 MONO_CLASS_IS_INTERFACE_INTERNAL (method
->klass
) ||
6184 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
6187 slot
= mono_method_get_vtable_slot (method
);
6191 klass
= method
->klass
;
6192 if (mono_class_is_ginst (klass
)) {
6193 generic_inst
= mono_class_get_context (klass
);
6194 klass
= mono_class_get_generic_class (klass
)->container_class
;
6199 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6200 for (parent
= m_class_get_parent (klass
); parent
!= NULL
; parent
= m_class_get_parent (parent
)) {
6201 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6202 or klass is the generic container class and generic_inst is the instantiation.
6204 when we go to the parent, if the parent is an open constructed type, we need to
6205 replace the type parameters by the definitions from the generic_inst, and then take it
6206 apart again into the klass and the generic_inst.
6208 For cases like this:
6209 class C<T> : B<T, int> {
6210 public override void Foo () { ... }
6212 class B<U,V> : A<HashMap<U,V>> {
6213 public override void Foo () { ... }
6216 public virtual void Foo () { ... }
6219 if at each iteration the parent isn't open, we can skip inflating it. if at some
6220 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6223 MonoGenericContext
*parent_inst
= NULL
;
6224 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (parent
))) {
6225 parent
= mono_class_inflate_generic_class_checked (parent
, generic_inst
, error
);
6226 return_val_if_nok (error
, NULL
);
6228 if (mono_class_is_ginst (parent
)) {
6229 parent_inst
= mono_class_get_context (parent
);
6230 parent
= mono_class_get_generic_class (parent
)->container_class
;
6233 mono_class_setup_vtable (parent
);
6234 if (m_class_get_vtable_size (parent
) <= slot
)
6237 generic_inst
= parent_inst
;
6240 klass
= m_class_get_parent (klass
);
6243 if (mono_class_is_open_constructed_type (m_class_get_byval_arg (klass
))) {
6244 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6245 return_val_if_nok (error
, NULL
);
6247 generic_inst
= NULL
;
6249 if (mono_class_is_ginst (klass
)) {
6250 generic_inst
= mono_class_get_context (klass
);
6251 klass
= mono_class_get_generic_class (klass
)->container_class
;
6257 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, error
);
6258 return_val_if_nok (error
, NULL
);
6261 if (klass
== method
->klass
)
6264 /*This is possible if definition == FALSE.
6265 * Do it here to be really sure we don't read invalid memory.
6267 if (slot
>= m_class_get_vtable_size (klass
))
6270 mono_class_setup_vtable (klass
);
6272 result
= m_class_get_vtable (klass
) [slot
];
6273 if (result
== NULL
) {
6274 /* It is an abstract method */
6275 gboolean found
= FALSE
;
6276 gpointer iter
= NULL
;
6277 while ((result
= mono_class_get_methods (klass
, &iter
))) {
6278 if (result
->slot
== slot
) {
6283 /* found might be FALSE if we looked in an abstract class
6284 * that doesn't override an abstract method of its
6286 * abstract class Base {
6287 * public abstract void Foo ();
6289 * abstract class Derived : Base { }
6290 * class Child : Derived {
6291 * public override void Foo () { }
6294 * if m was Child.Foo and we ask for the base method,
6295 * then we get here with klass == Derived and found == FALSE
6297 /* but it shouldn't be the case that if we're looking
6298 * for the definition and didn't find a result; the
6299 * loop above should've taken us as far as we could
6301 g_assert (!(definition
&& !found
));
6306 g_assert (result
!= NULL
);