2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* Low level lock which protects data structures in this module */
56 static mono_mutex_t classes_mutex;
58 /* Function supplied by the runtime to find classes by name using information from the AOT file */
59 static MonoGetClassFromName get_class_from_name = NULL;
61 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
62 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
63 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
64 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
65 static int generic_array_methods (MonoClass *class);
66 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
68 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
69 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
70 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
71 static guint32 mono_field_resolve_flags (MonoClassField *field);
72 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
73 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
76 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
80 We use gclass recording to allow recursive system f types to be referenced by a parent.
82 Given the following type hierarchy:
84 class TextBox : TextBoxBase<TextBox> {}
85 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
86 class TextInput<T> : Input<T> where T: TextInput<T> {}
89 The runtime tries to load TextBoxBase<>.
90 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
91 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
92 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
94 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
95 at this point, iow, both are registered in the type map and both and a NULL parent. This means
96 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
98 To fix that what we do is to record all generic instantes created while resolving the parent of
99 any generic type definition and, after resolved, correct the parent field if needed.
102 static int record_gclass_instantiation;
103 static GSList *gclass_recorded_list;
104 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
109 mono_locks_acquire (&classes_mutex, ClassesLock);
113 classes_unlock (void)
115 mono_locks_release (&classes_mutex, ClassesLock);
119 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
122 enable_gclass_recording (void)
124 ++record_gclass_instantiation;
128 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
131 disable_gclass_recording (gclass_record_func func, void *user_data)
133 GSList **head = &gclass_recorded_list;
135 g_assert (record_gclass_instantiation > 0);
136 --record_gclass_instantiation;
139 GSList *node = *head;
140 if (func ((MonoClass*)node->data, user_data)) {
142 g_slist_free_1 (node);
148 /* We automatically discard all recorded gclasses when disabled. */
149 if (!record_gclass_instantiation && gclass_recorded_list) {
150 g_slist_free (gclass_recorded_list);
151 gclass_recorded_list = NULL;
156 * mono_class_from_typeref:
157 * @image: a MonoImage
158 * @type_token: a TypeRef token
160 * Creates the MonoClass* structure representing the type defined by
161 * the typeref token valid inside @image.
162 * Returns: the MonoClass* representing the typeref token, NULL ifcould
166 mono_class_from_typeref (MonoImage *image, guint32 type_token)
169 MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
170 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
175 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
177 guint32 cols [MONO_TYPEREF_SIZE];
178 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
180 const char *name, *nspace;
181 MonoClass *res = NULL;
184 mono_error_init (error);
186 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
189 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
191 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
192 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
194 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
195 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
196 case MONO_RESOLUTION_SCOPE_MODULE:
198 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
199 This is not the observed behavior of existing implementations.
200 The defacto behavior is that it's just a typedef in disguise.
202 /* a typedef in disguise */
203 res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
206 case MONO_RESOLUTION_SCOPE_MODULEREF:
207 module = mono_image_load_module (image, idx);
209 res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
212 case MONO_RESOLUTION_SCOPE_TYPEREF: {
213 MonoClass *enclosing;
216 if (idx == mono_metadata_token_index (type_token)) {
217 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
221 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
222 if (!mono_error_ok (error))
225 if (enclosing->nested_classes_inited && enclosing->ext) {
226 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
227 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
229 if (strcmp (res->name, name) == 0)
233 /* Don't call mono_class_init as we might've been called by it recursively */
234 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
236 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
237 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
238 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
240 if (strcmp (nname, name) == 0)
241 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
243 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
246 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
249 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
253 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
254 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
258 if (!image->references || !image->references [idx - 1])
259 mono_assembly_load_reference (image, idx - 1);
260 g_assert (image->references [idx - 1]);
262 /* If the assembly did not load, register this as a type load exception */
263 if (image->references [idx - 1] == REFERENCE_MISSING){
264 MonoAssemblyName aname;
267 mono_assembly_get_assemblyref (image, idx - 1, &aname);
268 human_name = mono_stringify_assembly_name (&aname);
269 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
273 res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
276 /* Generic case, should be avoided for when a better error is possible. */
277 if (!res && mono_error_ok (error)) {
278 char *name = mono_class_name_from_token (image, type_token);
279 char *assembly = mono_assembly_name_from_token (image, type_token);
280 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
287 mono_image_memdup (MonoImage *image, void *data, guint size)
289 void *res = mono_image_alloc (image, size);
290 memcpy (res, data, size);
294 /* Copy everything mono_metadata_free_array free. */
296 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
299 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
301 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
303 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
305 a = g_memdup (a, sizeof (MonoArrayType));
307 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
309 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
314 /* Copy everything mono_metadata_free_method_signature free. */
316 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
320 sig = mono_metadata_signature_dup_full (image, sig);
322 sig->ret = mono_metadata_type_dup (image, sig->ret);
323 for (i = 0; i < sig->param_count; ++i)
324 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
330 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
332 MonoAssembly *ta = klass->image->assembly;
335 name = mono_stringify_assembly_name (&ta->aname);
336 g_string_append_printf (str, ", %s", name);
341 mono_type_name_check_byref (MonoType *type, GString *str)
344 g_string_append_c (str, '&');
348 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
349 MonoTypeNameFormat format)
353 switch (type->type) {
354 case MONO_TYPE_ARRAY: {
355 int i, rank = type->data.array->rank;
356 MonoTypeNameFormat nested_format;
358 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
359 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
361 mono_type_get_name_recurse (
362 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
363 g_string_append_c (str, '[');
365 g_string_append_c (str, '*');
366 for (i = 1; i < rank; i++)
367 g_string_append_c (str, ',');
368 g_string_append_c (str, ']');
370 mono_type_name_check_byref (type, str);
372 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
373 _mono_type_get_assembly_name (type->data.array->eklass, str);
376 case MONO_TYPE_SZARRAY: {
377 MonoTypeNameFormat nested_format;
379 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
380 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
382 mono_type_get_name_recurse (
383 &type->data.klass->byval_arg, str, FALSE, nested_format);
384 g_string_append (str, "[]");
386 mono_type_name_check_byref (type, str);
388 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
389 _mono_type_get_assembly_name (type->data.klass, str);
392 case MONO_TYPE_PTR: {
393 MonoTypeNameFormat nested_format;
395 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
396 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
398 mono_type_get_name_recurse (
399 type->data.type, str, FALSE, nested_format);
400 g_string_append_c (str, '*');
402 mono_type_name_check_byref (type, str);
404 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
405 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
410 if (!mono_generic_param_info (type->data.generic_param))
411 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
413 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
415 mono_type_name_check_byref (type, str);
419 klass = mono_class_from_mono_type (type);
420 if (klass->nested_in) {
421 mono_type_get_name_recurse (
422 &klass->nested_in->byval_arg, str, TRUE, format);
423 if (format == MONO_TYPE_NAME_FORMAT_IL)
424 g_string_append_c (str, '.');
426 g_string_append_c (str, '+');
427 } else if (*klass->name_space) {
428 g_string_append (str, klass->name_space);
429 g_string_append_c (str, '.');
431 if (format == MONO_TYPE_NAME_FORMAT_IL) {
432 char *s = strchr (klass->name, '`');
433 int len = s ? s - klass->name : strlen (klass->name);
435 g_string_append_len (str, klass->name, len);
437 g_string_append (str, klass->name);
440 if (klass->generic_class) {
441 MonoGenericClass *gclass = klass->generic_class;
442 MonoGenericInst *inst = gclass->context.class_inst;
443 MonoTypeNameFormat nested_format;
446 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
447 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
449 if (format == MONO_TYPE_NAME_FORMAT_IL)
450 g_string_append_c (str, '<');
452 g_string_append_c (str, '[');
453 for (i = 0; i < inst->type_argc; i++) {
454 MonoType *t = inst->type_argv [i];
457 g_string_append_c (str, ',');
458 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
459 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
460 g_string_append_c (str, '[');
461 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
462 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
463 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
464 g_string_append_c (str, ']');
466 if (format == MONO_TYPE_NAME_FORMAT_IL)
467 g_string_append_c (str, '>');
469 g_string_append_c (str, ']');
470 } else if (klass->generic_container &&
471 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
472 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
475 if (format == MONO_TYPE_NAME_FORMAT_IL)
476 g_string_append_c (str, '<');
478 g_string_append_c (str, '[');
479 for (i = 0; i < klass->generic_container->type_argc; i++) {
481 g_string_append_c (str, ',');
482 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
484 if (format == MONO_TYPE_NAME_FORMAT_IL)
485 g_string_append_c (str, '>');
487 g_string_append_c (str, ']');
490 mono_type_name_check_byref (type, str);
492 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
493 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
494 _mono_type_get_assembly_name (klass, str);
500 * mono_type_get_name_full:
502 * @format: the format for the return string.
505 * Returns: the string representation in a number of formats:
507 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
508 * returned in the formatrequired by System.Reflection, this is the
509 * inverse of mono_reflection_parse_type ().
511 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
512 * be used by the IL assembler.
514 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
516 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
519 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
523 result = g_string_new ("");
525 mono_type_get_name_recurse (type, result, FALSE, format);
527 return g_string_free (result, FALSE);
531 * mono_type_get_full_name:
534 * Returns: the string representation for type as required by System.Reflection.
535 * The inverse of mono_reflection_parse_type ().
538 mono_type_get_full_name (MonoClass *class)
540 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
544 * mono_type_get_name:
547 * Returns: the string representation for type as it would be represented in IL code.
550 mono_type_get_name (MonoType *type)
552 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
556 * mono_type_get_underlying_type:
559 * Returns: the MonoType for the underlying integer type if @type
560 * is an enum and byref is false, otherwise the type itself.
563 mono_type_get_underlying_type (MonoType *type)
565 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
566 return mono_class_enum_basetype (type->data.klass);
567 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
568 return mono_class_enum_basetype (type->data.generic_class->container_class);
573 * mono_class_is_open_constructed_type:
576 * Returns TRUE if type represents a generics open constructed type.
577 * IOW, not all type parameters required for the instantiation have
578 * been provided or it's a generic type definition.
580 * An open constructed type means it's a non realizable type. Not to
581 * be mixed up with an abstract type - we can't cast or dispatch to
582 * an open type, for example.
585 mono_class_is_open_constructed_type (MonoType *t)
591 case MONO_TYPE_SZARRAY:
592 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
593 case MONO_TYPE_ARRAY:
594 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
596 return mono_class_is_open_constructed_type (t->data.type);
597 case MONO_TYPE_GENERICINST:
598 return t->data.generic_class->context.class_inst->is_open;
599 case MONO_TYPE_CLASS:
600 case MONO_TYPE_VALUETYPE:
601 return t->data.klass->generic_container != NULL;
608 This is a simple function to catch the most common bad instances of generic types.
609 Specially those that might lead to further failures in the runtime.
612 is_valid_generic_argument (MonoType *type)
614 switch (type->type) {
616 //case MONO_TYPE_TYPEDBYREF:
623 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
625 mono_error_init (error);
627 switch (type->type) {
628 case MONO_TYPE_MVAR: {
630 int num = mono_type_get_generic_param_num (type);
631 MonoGenericInst *inst = context->method_inst;
632 if (!inst || !inst->type_argv)
634 if (num >= inst->type_argc) {
635 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
636 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
637 num, info ? info->name : "", inst->type_argc);
641 if (!is_valid_generic_argument (inst->type_argv [num])) {
642 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
643 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
644 num, info ? info->name : "", inst->type_argv [num]->type);
648 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
649 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
650 * ->byref and ->attrs from @type are propagated to the returned type.
652 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
653 nt->byref = type->byref;
654 nt->attrs = type->attrs;
657 case MONO_TYPE_VAR: {
659 int num = mono_type_get_generic_param_num (type);
660 MonoGenericInst *inst = context->class_inst;
663 if (num >= inst->type_argc) {
664 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
665 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
666 num, info ? info->name : "", inst->type_argc);
669 if (!is_valid_generic_argument (inst->type_argv [num])) {
670 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
671 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
672 num, info ? info->name : "", inst->type_argv [num]->type);
675 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
676 nt->byref = type->byref;
677 nt->attrs = type->attrs;
680 case MONO_TYPE_SZARRAY: {
681 MonoClass *eclass = type->data.klass;
682 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
683 if (!inflated || !mono_error_ok (error))
685 nt = mono_metadata_type_dup (image, type);
686 nt->data.klass = mono_class_from_mono_type (inflated);
687 mono_metadata_free_type (inflated);
690 case MONO_TYPE_ARRAY: {
691 MonoClass *eclass = type->data.array->eklass;
692 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
693 if (!inflated || !mono_error_ok (error))
695 nt = mono_metadata_type_dup (image, type);
696 nt->data.array->eklass = mono_class_from_mono_type (inflated);
697 mono_metadata_free_type (inflated);
700 case MONO_TYPE_GENERICINST: {
701 MonoGenericClass *gclass = type->data.generic_class;
702 MonoGenericInst *inst;
704 if (!gclass->context.class_inst->is_open)
707 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
708 if (!mono_error_ok (error))
710 if (inst != gclass->context.class_inst)
711 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
713 if (gclass == type->data.generic_class)
716 nt = mono_metadata_type_dup (image, type);
717 nt->data.generic_class = gclass;
720 case MONO_TYPE_CLASS:
721 case MONO_TYPE_VALUETYPE: {
722 MonoClass *klass = type->data.klass;
723 MonoGenericContainer *container = klass->generic_container;
724 MonoGenericInst *inst;
725 MonoGenericClass *gclass = NULL;
731 /* We can't use context->class_inst directly, since it can have more elements */
732 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
733 if (!mono_error_ok (error))
735 if (inst == container->context.class_inst)
738 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
740 nt = mono_metadata_type_dup (image, type);
741 nt->type = MONO_TYPE_GENERICINST;
742 nt->data.generic_class = gclass;
752 mono_generic_class_get_context (MonoGenericClass *gclass)
754 return &gclass->context;
758 mono_class_get_context (MonoClass *class)
760 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
764 * mono_class_get_generic_container:
766 * Return the generic container of KLASS which should be a generic type definition.
768 MonoGenericContainer*
769 mono_class_get_generic_container (MonoClass *klass)
771 g_assert (klass->is_generic);
773 return klass->generic_container;
777 * mono_class_get_generic_class:
779 * Return the MonoGenericClass of KLASS, which should be a generic instance.
782 mono_class_get_generic_class (MonoClass *klass)
784 g_assert (klass->is_inflated);
786 return klass->generic_class;
790 * mono_class_inflate_generic_type_with_mempool:
791 * @mempool: a mempool
793 * @context: a generics context
794 * @error: error context
796 * The same as mono_class_inflate_generic_type, but allocates the MonoType
797 * from mempool if it is non-NULL. If it is NULL, the MonoType is
798 * allocated on the heap and is owned by the caller.
799 * The returned type can potentially be the same as TYPE, so it should not be
800 * modified by the caller, and it should be freed using mono_metadata_free_type ().
803 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
805 MonoType *inflated = NULL;
806 mono_error_init (error);
809 inflated = inflate_generic_type (image, type, context, error);
810 if (!mono_error_ok (error))
814 MonoType *shared = mono_metadata_get_shared_type (type);
819 return mono_metadata_type_dup (image, type);
823 mono_stats.inflated_type_count++;
828 * mono_class_inflate_generic_type:
830 * @context: a generics context
832 * If @type is a generic type and @context is not NULL, instantiate it using the
833 * generics context @context.
835 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
836 * on the heap and is owned by the caller. Returns NULL on error.
838 * @deprecated Please use mono_class_inflate_generic_type_checked instead
841 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
845 result = mono_class_inflate_generic_type_checked (type, context, &error);
847 if (!mono_error_ok (&error)) {
848 mono_error_cleanup (&error);
855 * mono_class_inflate_generic_type:
857 * @context: a generics context
858 * @error: error context to use
860 * If @type is a generic type and @context is not NULL, instantiate it using the
861 * generics context @context.
863 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
864 * on the heap and is owned by the caller.
867 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
869 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
873 * mono_class_inflate_generic_type_no_copy:
875 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
879 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
881 MonoType *inflated = NULL;
883 mono_error_init (error);
885 inflated = inflate_generic_type (image, type, context, error);
886 if (!mono_error_ok (error))
893 mono_stats.inflated_type_count++;
898 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
903 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
904 if (!mono_error_ok (error))
907 res = mono_class_from_mono_type (inflated);
908 mono_metadata_free_type (inflated);
913 * mono_class_inflate_generic_class:
915 * Inflate the class GKLASS with CONTEXT.
918 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
923 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
924 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
931 static MonoGenericContext
932 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
934 MonoGenericInst *class_inst = NULL;
935 MonoGenericInst *method_inst = NULL;
936 MonoGenericContext res = { NULL, NULL };
938 mono_error_init (error);
940 if (context->class_inst) {
941 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
942 if (!mono_error_ok (error))
946 if (context->method_inst) {
947 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
948 if (!mono_error_ok (error))
952 res.class_inst = class_inst;
953 res.method_inst = method_inst;
959 * mono_class_inflate_generic_method:
960 * @method: a generic method
961 * @context: a generics context
963 * Instantiate the generic method @method using the generics context @context.
965 * Returns: the new instantiated method
968 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
970 return mono_class_inflate_generic_method_full (method, NULL, context);
974 * mono_class_inflate_generic_method_full:
976 * Instantiate method @method with the generic context @context.
977 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
978 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
981 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
984 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
985 if (!mono_error_ok (&error))
986 /*FIXME do proper error handling - on this case, kill this function. */
987 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
993 * mono_class_inflate_generic_method_full_checked:
994 * Same as mono_class_inflate_generic_method_full but return failure using @error.
997 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1000 MonoMethodInflated *iresult, *cached;
1001 MonoMethodSignature *sig;
1002 MonoGenericContext tmp_context;
1003 gboolean is_mb_open = FALSE;
1005 mono_error_init (error);
1007 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1008 while (method->is_inflated) {
1009 MonoGenericContext *method_context = mono_method_get_context (method);
1010 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1012 tmp_context = inflate_generic_context (method_context, context, error);
1013 if (!mono_error_ok (error))
1015 context = &tmp_context;
1017 if (mono_metadata_generic_context_equal (method_context, context))
1020 method = imethod->declaring;
1024 * A method only needs to be inflated if the context has argument for which it is
1027 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1028 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1031 if (!((method->is_generic && context->method_inst) ||
1032 (method->klass->generic_container && context->class_inst)))
1036 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1037 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1038 * This is opposite to the way non-SRE MethodInfos behave.
1040 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1042 * void Example<T> () {
1046 * In Example, the method token must be encoded as: "void Example<!!0>()"
1048 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1049 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1051 * On the other hand, inflating a non-SRE generic method with its own arguments should
1052 * return itself. For example:
1054 * MethodInfo m = ... //m is a generic method definition
1055 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1058 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1059 * what happens with regular methods.
1061 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1062 * everything should behave like a regular type or method.
1065 is_mb_open = method->is_generic &&
1066 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1067 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1069 iresult = g_new0 (MonoMethodInflated, 1);
1070 iresult->context = *context;
1071 iresult->declaring = method;
1072 iresult->method.method.is_mb_open = is_mb_open;
1074 if (!context->method_inst && method->is_generic)
1075 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1077 if (!context->class_inst) {
1078 g_assert (!iresult->declaring->klass->generic_class);
1079 if (iresult->declaring->klass->generic_container)
1080 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1081 else if (iresult->declaring->klass->generic_class)
1082 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1085 mono_loader_lock ();
1086 cached = mono_method_inflated_lookup (iresult, FALSE);
1088 mono_loader_unlock ();
1090 return (MonoMethod*)cached;
1093 mono_stats.inflated_method_count++;
1095 inflated_methods_size += sizeof (MonoMethodInflated);
1097 sig = mono_method_signature (method);
1099 char *name = mono_type_get_full_name (method->klass);
1100 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1106 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1108 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1111 result = (MonoMethod *) iresult;
1112 result->is_inflated = TRUE;
1113 result->is_generic = FALSE;
1114 result->sre_method = FALSE;
1115 result->signature = NULL;
1116 result->is_mb_open = is_mb_open;
1118 if (!context->method_inst) {
1119 /* Set the generic_container of the result to the generic_container of method */
1120 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1122 if (generic_container) {
1123 result->is_generic = 1;
1124 mono_method_set_generic_container (result, generic_container);
1128 if (!klass_hint || !klass_hint->generic_class ||
1129 klass_hint->generic_class->container_class != method->klass ||
1130 klass_hint->generic_class->context.class_inst != context->class_inst)
1133 if (method->klass->generic_container)
1134 result->klass = klass_hint;
1136 if (!result->klass) {
1137 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1138 if (!mono_error_ok (error))
1141 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1143 mono_metadata_free_type (inflated);
1147 * FIXME: This should hold, but it doesn't:
1149 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1150 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1151 * g_assert (result->is_generic);
1154 * Fixing this here causes other things to break, hence a very
1155 * ugly hack in mini-trampolines.c - see
1156 * is_generic_method_definition().
1159 mono_method_inflated_lookup (iresult, TRUE);
1160 mono_loader_unlock ();
1164 mono_loader_unlock ();
1170 * mono_get_inflated_method:
1172 * Obsolete. We keep it around since it's mentioned in the public API.
1175 mono_get_inflated_method (MonoMethod *method)
1181 * mono_method_get_context_general:
1183 * @uninflated: handle uninflated methods?
1185 * Returns the generic context of a method or NULL if it doesn't have
1186 * one. For an inflated method that's the context stored in the
1187 * method. Otherwise it's in the method's generic container or in the
1188 * generic container of the method's class.
1191 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1193 if (method->is_inflated) {
1194 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1195 return &imethod->context;
1199 if (method->is_generic)
1200 return &(mono_method_get_generic_container (method)->context);
1201 if (method->klass->generic_container)
1202 return &method->klass->generic_container->context;
1207 * mono_method_get_context:
1210 * Returns the generic context for method if it's inflated, otherwise
1214 mono_method_get_context (MonoMethod *method)
1216 return mono_method_get_context_general (method, FALSE);
1220 * mono_method_get_generic_container:
1222 * Returns the generic container of METHOD, which should be a generic method definition.
1223 * Returns NULL if METHOD is not a generic method definition.
1224 * LOCKING: Acquires the loader lock.
1226 MonoGenericContainer*
1227 mono_method_get_generic_container (MonoMethod *method)
1229 MonoGenericContainer *container;
1231 if (!method->is_generic)
1234 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1235 g_assert (container);
1241 * mono_method_set_generic_container:
1243 * Sets the generic container of METHOD to CONTAINER.
1244 * LOCKING: Acquires the loader lock.
1247 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1249 g_assert (method->is_generic);
1251 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1255 * mono_class_find_enum_basetype:
1256 * @class: The enum class
1258 * Determine the basetype of an enum by iterating through its fields. We do this
1259 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1262 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1264 MonoGenericContainer *container = NULL;
1265 MonoImage *m = class->image;
1266 const int top = class->field.count;
1269 g_assert (class->enumtype);
1271 mono_error_init (error);
1273 if (class->generic_container)
1274 container = class->generic_container;
1275 else if (class->generic_class) {
1276 MonoClass *gklass = class->generic_class->container_class;
1278 container = gklass->generic_container;
1279 g_assert (container);
1283 * Fetch all the field information.
1285 for (i = 0; i < top; i++){
1287 guint32 cols [MONO_FIELD_SIZE];
1288 int idx = class->field.first + i;
1291 /* class->field.first and idx points into the fieldptr table */
1292 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1294 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1297 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1298 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1302 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1303 mono_metadata_decode_value (sig, &sig);
1304 /* FIELD signature == 0x06 */
1306 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1310 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1312 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1313 mono_error_set_from_loader_error (error);
1315 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1318 if (class->generic_class) {
1319 //FIXME do we leak here?
1320 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1321 if (!mono_error_ok (error))
1323 ftype->attrs = cols [MONO_FIELD_FLAGS];
1328 mono_error_set_type_load_class (error, class, "Could not find base type");
1331 g_assert (!mono_loader_get_last_error ());
1336 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1339 mono_type_has_exceptions (MonoType *type)
1341 switch (type->type) {
1342 case MONO_TYPE_CLASS:
1343 case MONO_TYPE_VALUETYPE:
1344 case MONO_TYPE_SZARRAY:
1345 return type->data.klass->exception_type;
1346 case MONO_TYPE_ARRAY:
1347 return type->data.array->eklass->exception_type;
1348 case MONO_TYPE_GENERICINST:
1349 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1357 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1361 mono_class_alloc (MonoClass *class, int size)
1363 if (class->generic_class)
1364 return mono_image_set_alloc (class->generic_class->owner, size);
1366 return mono_image_alloc (class->image, size);
1370 mono_class_alloc0 (MonoClass *class, int size)
1374 res = mono_class_alloc (class, size);
1375 memset (res, 0, size);
1379 #define mono_class_new0(class,struct_type, n_structs) \
1380 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1383 * mono_class_setup_basic_field_info:
1384 * @class: The class to initialize
1386 * Initializes the class->fields.
1387 * LOCKING: Assumes the loader lock is held.
1390 mono_class_setup_basic_field_info (MonoClass *class)
1392 MonoClassField *field;
1400 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1401 image = class->image;
1402 top = class->field.count;
1404 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1406 * This happens when a generic instance of an unfinished generic typebuilder
1407 * is used as an element type for creating an array type. We can't initialize
1408 * the fields of this class using the fields of gklass, since gklass is not
1409 * finished yet, fields could be added to it later.
1415 mono_class_setup_basic_field_info (gtd);
1417 top = gtd->field.count;
1418 class->field.first = gtd->field.first;
1419 class->field.count = gtd->field.count;
1422 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1425 * Fetch all the field information.
1427 for (i = 0; i < top; i++){
1428 field = &class->fields [i];
1429 field->parent = class;
1432 field->name = mono_field_get_name (>d->fields [i]);
1434 int idx = class->field.first + i;
1435 /* class->field.first and idx points into the fieldptr table */
1436 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1437 /* The name is needed for fieldrefs */
1438 field->name = mono_metadata_string_heap (image, name_idx);
1444 * mono_class_setup_fields:
1445 * @class: The class to initialize
1447 * Initializes the class->fields.
1448 * LOCKING: Assumes the loader lock is held.
1451 mono_class_setup_fields (MonoClass *class)
1454 MonoImage *m = class->image;
1456 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1457 int i, blittable = TRUE;
1458 guint32 real_size = 0;
1459 guint32 packing_size = 0;
1460 gboolean explicit_size;
1461 MonoClassField *field;
1462 MonoGenericContainer *container = NULL;
1463 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1466 * FIXME: We have a race condition here. It's possible that this function returns
1467 * to its caller with `instance_size` set to `0` instead of the actual size. This
1468 * is not a problem when the function is called recursively on the same class,
1469 * because the size will be initialized by the outer invocation. What follows is a
1470 * description of how it can occur in other cases, too. There it is a problem,
1471 * because it can lead to the GC being asked to allocate an object of size `0`,
1472 * which SGen chokes on. The race condition is triggered infrequently by
1473 * `tests/sgen-suspend.cs`.
1475 * This function is called for a class whenever one of its subclasses is inited.
1476 * For example, it's called for every subclass of Object. What it does is this:
1478 * if (class->setup_fields_called)
1481 * class->instance_size = 0;
1483 * class->setup_fields_called = 1;
1484 * ... critical point
1485 * class->instance_size = actual_instance_size;
1487 * The last two steps are sometimes reversed, but that only changes the way in which
1488 * the race condition works.
1490 * Assume thread A goes through this function and makes it to the critical point.
1491 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1492 * immediately, but `instance_size` is incorrect.
1494 * The other case looks like this:
1496 * if (class->setup_fields_called)
1498 * ... critical point X
1499 * class->instance_size = 0;
1500 * ... critical point Y
1501 * class->instance_size = actual_instance_size;
1503 * class->setup_fields_called = 1;
1505 * Assume thread A goes through the function and makes it to critical point X. Now
1506 * thread B runs through the whole of the function, returning, assuming
1507 * `instance_size` is set. At that point thread A gets to run and makes it to
1508 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1511 if (class->setup_fields_called)
1514 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1516 * This happens when a generic instance of an unfinished generic typebuilder
1517 * is used as an element type for creating an array type. We can't initialize
1518 * the fields of this class using the fields of gklass, since gklass is not
1519 * finished yet, fields could be added to it later.
1524 mono_class_setup_basic_field_info (class);
1525 top = class->field.count;
1528 mono_class_setup_fields (gtd);
1529 if (gtd->exception_type) {
1530 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1535 class->instance_size = 0;
1537 class->sizes.class_size = 0;
1539 if (class->parent) {
1540 /* For generic instances, class->parent might not have been initialized */
1541 mono_class_init (class->parent);
1542 if (!class->parent->size_inited) {
1543 mono_class_setup_fields (class->parent);
1544 if (class->parent->exception_type) {
1545 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1549 class->instance_size += class->parent->instance_size;
1550 class->min_align = class->parent->min_align;
1551 /* we use |= since it may have been set already */
1552 class->has_references |= class->parent->has_references;
1553 blittable = class->parent->blittable;
1555 class->instance_size = sizeof (MonoObject);
1556 class->min_align = 1;
1559 /* We can't really enable 16 bytes alignment until the GC supports it.
1560 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1561 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1562 Bug #506144 is an example of this issue.
1564 if (class->simd_type)
1565 class->min_align = 16;
1567 /* Get the real size */
1568 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1570 if (explicit_size) {
1571 if ((packing_size & 0xfffffff0) != 0) {
1572 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1573 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1576 class->packing_size = packing_size;
1577 real_size += class->instance_size;
1581 if (explicit_size && real_size) {
1582 class->instance_size = MAX (real_size, class->instance_size);
1584 class->blittable = blittable;
1585 mono_memory_barrier ();
1586 class->size_inited = 1;
1587 class->fields_inited = 1;
1588 class->setup_fields_called = 1;
1592 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1595 /* Prevent infinite loops if the class references itself */
1596 class->setup_fields_called = 1;
1598 if (class->generic_container) {
1599 container = class->generic_container;
1601 container = gtd->generic_container;
1602 g_assert (container);
1606 * Fetch all the field information.
1608 for (i = 0; i < top; i++){
1609 int idx = class->field.first + i;
1610 field = &class->fields [i];
1612 field->parent = class;
1615 mono_field_resolve_type (field, &error);
1616 if (!mono_error_ok (&error)) {
1617 /*mono_field_resolve_type already failed class*/
1618 mono_error_cleanup (&error);
1622 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1623 g_assert (field->type);
1626 if (mono_field_is_deleted (field))
1629 MonoClassField *gfield = >d->fields [i];
1630 field->offset = gfield->offset;
1632 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1634 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1635 field->offset = offset;
1637 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1638 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1641 if (field->offset < -1) { /*-1 is used to encode special static fields */
1642 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1648 /* Only do these checks if we still think this type is blittable */
1649 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1650 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1653 MonoClass *field_class = mono_class_from_mono_type (field->type);
1655 mono_class_setup_fields (field_class);
1656 if (field_class->exception_type) {
1657 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1661 if (!field_class || !field_class->blittable)
1666 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1667 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1668 blittable = class->element_class->blittable;
1671 if (mono_type_has_exceptions (field->type)) {
1672 char *class_name = mono_type_get_full_name (class);
1673 char *type_name = mono_type_full_name (field->type);
1675 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1676 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1677 g_free (class_name);
1681 /* The def_value of fields is compute lazily during vtable creation */
1684 if (class == mono_defaults.string_class)
1687 class->blittable = blittable;
1689 if (class->enumtype && !mono_class_enum_basetype (class)) {
1690 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1693 if (explicit_size && real_size) {
1694 class->instance_size = MAX (real_size, class->instance_size);
1697 if (class->exception_type)
1699 mono_class_layout_fields (class);
1701 /*valuetypes can't be neither bigger than 1Mb or empty. */
1702 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1703 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1705 mono_memory_barrier ();
1706 class->fields_inited = 1;
1710 * mono_class_setup_fields_locking:
1711 * @class: The class to initialize
1713 * Initializes the class->fields array of fields.
1714 * Aquires the loader lock.
1717 mono_class_setup_fields_locking (MonoClass *class)
1719 /* This can be checked without locks */
1720 if (class->fields_inited)
1722 mono_loader_lock ();
1723 mono_class_setup_fields (class);
1724 mono_loader_unlock ();
1728 * mono_class_has_references:
1730 * Returns whenever @klass->has_references is set, initializing it if needed.
1731 * Aquires the loader lock.
1734 mono_class_has_references (MonoClass *klass)
1736 if (klass->init_pending) {
1737 /* Be conservative */
1740 mono_class_init (klass);
1742 return klass->has_references;
1747 * mono_type_get_basic_type_from_generic:
1750 * Returns a closed type corresponding to the possibly open type
1754 mono_type_get_basic_type_from_generic (MonoType *type)
1756 /* When we do generic sharing we let type variables stand for reference types. */
1757 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1758 return &mono_defaults.object_class->byval_arg;
1763 * mono_class_layout_fields:
1766 * Compute the placement of fields inside an object or struct, according to
1767 * the layout rules and set the following fields in @class:
1768 * - has_references (if the class contains instance references firled or structs that contain references)
1769 * - has_static_refs (same, but for static fields)
1770 * - instance_size (size of the object in memory)
1771 * - class_size (size needed for the static fields)
1772 * - size_inited (flag set when the instance_size is set)
1774 * LOCKING: this is supposed to be called with the loader lock held.
1777 mono_class_layout_fields (MonoClass *class)
1780 const int top = class->field.count;
1781 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1782 guint32 pass, passes, real_size;
1783 gboolean gc_aware_layout = FALSE;
1784 gboolean has_static_fields = FALSE;
1785 MonoClassField *field;
1788 * When we do generic sharing we need to have layout
1789 * information for open generic classes (either with a generic
1790 * context containing type variables or with a generic
1791 * container), so we don't return in that case anymore.
1795 * Enable GC aware auto layout: in this mode, reference
1796 * fields are grouped together inside objects, increasing collector
1798 * Requires that all classes whose layout is known to native code be annotated
1799 * with [StructLayout (LayoutKind.Sequential)]
1800 * Value types have gc_aware_layout disabled by default, as per
1801 * what the default is for other runtimes.
1803 /* corlib is missing [StructLayout] directives in many places */
1804 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1805 if (!class->valuetype)
1806 gc_aware_layout = TRUE;
1809 /* Compute klass->has_references */
1811 * Process non-static fields first, since static fields might recursively
1812 * refer to the class itself.
1814 for (i = 0; i < top; i++) {
1817 field = &class->fields [i];
1819 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1820 ftype = mono_type_get_underlying_type (field->type);
1821 ftype = mono_type_get_basic_type_from_generic (ftype);
1822 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1823 class->has_references = TRUE;
1827 for (i = 0; i < top; i++) {
1830 field = &class->fields [i];
1832 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1833 ftype = mono_type_get_underlying_type (field->type);
1834 ftype = mono_type_get_basic_type_from_generic (ftype);
1835 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1836 class->has_static_refs = TRUE;
1840 for (i = 0; i < top; i++) {
1843 field = &class->fields [i];
1845 ftype = mono_type_get_underlying_type (field->type);
1846 ftype = mono_type_get_basic_type_from_generic (ftype);
1847 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1848 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1849 class->has_static_refs = TRUE;
1851 class->has_references = TRUE;
1856 * Compute field layout and total size (not considering static fields)
1860 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1861 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1863 if (gc_aware_layout)
1868 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1871 if (class->parent) {
1872 mono_class_setup_fields (class->parent);
1873 if (class->parent->exception_type) {
1874 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1877 real_size = class->parent->instance_size;
1879 real_size = sizeof (MonoObject);
1882 for (pass = 0; pass < passes; ++pass) {
1883 for (i = 0; i < top; i++){
1888 field = &class->fields [i];
1890 if (mono_field_is_deleted (field))
1892 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1895 ftype = mono_type_get_underlying_type (field->type);
1896 ftype = mono_type_get_basic_type_from_generic (ftype);
1897 if (gc_aware_layout) {
1898 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1907 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1908 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1909 /* This field is a hack inserted by MCS to empty structures */
1913 size = mono_type_size (field->type, &align);
1915 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1916 align = class->packing_size ? MIN (class->packing_size, align): align;
1917 /* if the field has managed references, we need to force-align it
1920 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1921 align = MAX (align, sizeof (gpointer));
1923 class->min_align = MAX (align, class->min_align);
1924 field->offset = real_size;
1926 field->offset += align - 1;
1927 field->offset &= ~(align - 1);
1929 /*TypeBuilders produce all sort of weird things*/
1930 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1931 real_size = field->offset + size;
1934 class->instance_size = MAX (real_size, class->instance_size);
1936 if (class->instance_size & (class->min_align - 1)) {
1937 class->instance_size += class->min_align - 1;
1938 class->instance_size &= ~(class->min_align - 1);
1942 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1944 for (i = 0; i < top; i++) {
1949 field = &class->fields [i];
1952 * There must be info about all the fields in a type if it
1953 * uses explicit layout.
1956 if (mono_field_is_deleted (field))
1958 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1961 size = mono_type_size (field->type, &align);
1962 align = class->packing_size ? MIN (class->packing_size, align): align;
1963 class->min_align = MAX (align, class->min_align);
1966 * When we get here, field->offset is already set by the
1967 * loader (for either runtime fields or fields loaded from metadata).
1968 * The offset is from the start of the object: this works for both
1969 * classes and valuetypes.
1971 field->offset += sizeof (MonoObject);
1972 ftype = mono_type_get_underlying_type (field->type);
1973 ftype = mono_type_get_basic_type_from_generic (ftype);
1974 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1975 if (field->offset % sizeof (gpointer)) {
1976 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1983 real_size = MAX (real_size, size + field->offset);
1985 class->instance_size = MAX (real_size, class->instance_size);
1986 if (class->instance_size & (class->min_align - 1)) {
1987 class->instance_size += class->min_align - 1;
1988 class->instance_size &= ~(class->min_align - 1);
1993 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1995 * For small structs, set min_align to at least the struct size to improve
1996 * performance, and since the JIT memset/memcpy code assumes this and generates
1997 * unaligned accesses otherwise. See #78990 for a testcase.
1999 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2000 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2003 mono_memory_barrier ();
2004 class->size_inited = 1;
2007 * Compute static field layout and size
2009 for (i = 0; i < top; i++){
2013 field = &class->fields [i];
2015 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2017 if (mono_field_is_deleted (field))
2020 if (mono_type_has_exceptions (field->type)) {
2021 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2025 has_static_fields = TRUE;
2027 size = mono_type_size (field->type, &align);
2028 field->offset = class->sizes.class_size;
2029 /*align is always non-zero here*/
2030 field->offset += align - 1;
2031 field->offset &= ~(align - 1);
2032 class->sizes.class_size = field->offset + size;
2035 if (has_static_fields && class->sizes.class_size == 0)
2036 /* Simplify code which depends on class_size != 0 if the class has static fields */
2037 class->sizes.class_size = 8;
2041 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2045 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2046 method->klass = class;
2047 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2048 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2049 method->signature = sig;
2050 method->name = name;
2053 if (name [0] == '.') {
2054 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2056 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2062 * mono_class_setup_methods:
2065 * Initializes the 'methods' array in CLASS.
2066 * Calling this method should be avoided if possible since it allocates a lot
2067 * of long-living MonoMethod structures.
2068 * Methods belonging to an interface are assigned a sequential slot starting
2071 * On failure this function sets class->exception_type
2074 mono_class_setup_methods (MonoClass *class)
2077 MonoMethod **methods;
2082 if (class->generic_class) {
2084 MonoClass *gklass = class->generic_class->container_class;
2086 mono_class_init (gklass);
2087 if (!gklass->exception_type)
2088 mono_class_setup_methods (gklass);
2089 if (gklass->exception_type) {
2090 /* FIXME make exception_data less opaque so it's possible to dup it here */
2091 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2095 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2096 count = gklass->method.count;
2097 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2099 for (i = 0; i < count; i++) {
2100 methods [i] = mono_class_inflate_generic_method_full_checked (
2101 gklass->methods [i], class, mono_class_get_context (class), &error);
2102 if (!mono_error_ok (&error)) {
2103 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2104 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2107 mono_error_cleanup (&error);
2111 } else if (class->rank) {
2113 MonoMethod *amethod;
2114 MonoMethodSignature *sig;
2115 int count_generic = 0, first_generic = 0;
2118 count = 3 + (class->rank > 1? 2: 1);
2120 mono_class_setup_interfaces (class, &error);
2121 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2123 if (class->interface_count) {
2124 count_generic = generic_array_methods (class);
2125 first_generic = count;
2126 count += class->interface_count * count_generic;
2129 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2131 sig = mono_metadata_signature_alloc (class->image, class->rank);
2132 sig->ret = &mono_defaults.void_class->byval_arg;
2133 sig->pinvoke = TRUE;
2134 sig->hasthis = TRUE;
2135 for (i = 0; i < class->rank; ++i)
2136 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2138 amethod = create_array_method (class, ".ctor", sig);
2139 methods [method_num++] = amethod;
2140 if (class->rank > 1) {
2141 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2142 sig->ret = &mono_defaults.void_class->byval_arg;
2143 sig->pinvoke = TRUE;
2144 sig->hasthis = TRUE;
2145 for (i = 0; i < class->rank * 2; ++i)
2146 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2148 amethod = create_array_method (class, ".ctor", sig);
2149 methods [method_num++] = amethod;
2151 /* element Get (idx11, [idx2, ...]) */
2152 sig = mono_metadata_signature_alloc (class->image, class->rank);
2153 sig->ret = &class->element_class->byval_arg;
2154 sig->pinvoke = TRUE;
2155 sig->hasthis = TRUE;
2156 for (i = 0; i < class->rank; ++i)
2157 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2158 amethod = create_array_method (class, "Get", sig);
2159 methods [method_num++] = amethod;
2160 /* element& Address (idx11, [idx2, ...]) */
2161 sig = mono_metadata_signature_alloc (class->image, class->rank);
2162 sig->ret = &class->element_class->this_arg;
2163 sig->pinvoke = TRUE;
2164 sig->hasthis = TRUE;
2165 for (i = 0; i < class->rank; ++i)
2166 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2167 amethod = create_array_method (class, "Address", sig);
2168 methods [method_num++] = amethod;
2169 /* void Set (idx11, [idx2, ...], element) */
2170 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2171 sig->ret = &mono_defaults.void_class->byval_arg;
2172 sig->pinvoke = TRUE;
2173 sig->hasthis = TRUE;
2174 for (i = 0; i < class->rank; ++i)
2175 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2176 sig->params [i] = &class->element_class->byval_arg;
2177 amethod = create_array_method (class, "Set", sig);
2178 methods [method_num++] = amethod;
2180 for (i = 0; i < class->interface_count; i++)
2181 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2183 count = class->method.count;
2184 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2185 for (i = 0; i < count; ++i) {
2186 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2187 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2191 if (MONO_CLASS_IS_INTERFACE (class)) {
2193 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2194 for (i = 0; i < count; ++i) {
2195 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2196 methods [i]->slot = slot++;
2200 mono_image_lock (class->image);
2202 if (!class->methods) {
2203 class->method.count = count;
2205 /* Needed because of the double-checking locking pattern */
2206 mono_memory_barrier ();
2208 class->methods = methods;
2211 mono_image_unlock (class->image);
2215 * mono_class_get_method_by_index:
2217 * Returns class->methods [index], initializing class->methods if neccesary.
2219 * LOCKING: Acquires the loader lock.
2222 mono_class_get_method_by_index (MonoClass *class, int index)
2224 /* Avoid calling setup_methods () if possible */
2225 if (class->generic_class && !class->methods) {
2226 MonoClass *gklass = class->generic_class->container_class;
2229 m = mono_class_inflate_generic_method_full (
2230 gklass->methods [index], class, mono_class_get_context (class));
2232 * If setup_methods () is called later for this class, no duplicates are created,
2233 * since inflate_generic_method guarantees that only one instance of a method
2234 * is created for each context.
2237 mono_class_setup_methods (class);
2238 g_assert (m == class->methods [index]);
2242 mono_class_setup_methods (class);
2243 if (class->exception_type) /*FIXME do proper error handling*/
2245 g_assert (index >= 0 && index < class->method.count);
2246 return class->methods [index];
2251 * mono_class_get_inflated_method:
2253 * Given an inflated class CLASS and a method METHOD which should be a method of
2254 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2257 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2259 MonoClass *gklass = class->generic_class->container_class;
2262 g_assert (method->klass == gklass);
2264 mono_class_setup_methods (gklass);
2265 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2267 for (i = 0; i < gklass->method.count; ++i) {
2268 if (gklass->methods [i] == method) {
2270 return class->methods [i];
2272 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2280 * mono_class_get_vtable_entry:
2282 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2283 * LOCKING: Acquires the loader lock.
2286 mono_class_get_vtable_entry (MonoClass *class, int offset)
2290 if (class->rank == 1) {
2292 * szarrays do not overwrite any methods of Array, so we can avoid
2293 * initializing their vtables in some cases.
2295 mono_class_setup_vtable (class->parent);
2296 if (offset < class->parent->vtable_size)
2297 return class->parent->vtable [offset];
2300 if (class->generic_class) {
2301 MonoClass *gklass = class->generic_class->container_class;
2302 mono_class_setup_vtable (gklass);
2303 m = gklass->vtable [offset];
2305 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2307 mono_class_setup_vtable (class);
2308 if (class->exception_type)
2310 m = class->vtable [offset];
2317 * mono_class_get_vtable_size:
2319 * Return the vtable size for KLASS.
2322 mono_class_get_vtable_size (MonoClass *klass)
2324 mono_class_setup_vtable (klass);
2326 return klass->vtable_size;
2330 * mono_class_setup_properties:
2332 * Initialize class->ext.property and class->ext.properties.
2334 * This method can fail the class.
2337 mono_class_setup_properties (MonoClass *class)
2339 guint startm, endm, i, j;
2340 guint32 cols [MONO_PROPERTY_SIZE];
2341 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2342 MonoProperty *properties;
2346 if (class->ext && class->ext->properties)
2349 if (class->generic_class) {
2350 MonoClass *gklass = class->generic_class->container_class;
2352 mono_class_init (gklass);
2353 mono_class_setup_properties (gklass);
2354 if (gklass->exception_type) {
2355 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2359 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2361 for (i = 0; i < gklass->ext->property.count; i++) {
2362 MonoProperty *prop = &properties [i];
2364 *prop = gklass->ext->properties [i];
2367 prop->get = mono_class_inflate_generic_method_full (
2368 prop->get, class, mono_class_get_context (class));
2370 prop->set = mono_class_inflate_generic_method_full (
2371 prop->set, class, mono_class_get_context (class));
2373 prop->parent = class;
2376 first = gklass->ext->property.first;
2377 count = gklass->ext->property.count;
2379 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2380 count = last - first;
2383 mono_class_setup_methods (class);
2384 if (class->exception_type)
2388 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2389 for (i = first; i < last; ++i) {
2390 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2391 properties [i - first].parent = class;
2392 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2393 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2395 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2396 for (j = startm; j < endm; ++j) {
2399 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2401 if (class->image->uncompressed_metadata)
2402 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2403 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2405 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2407 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2408 case METHOD_SEMANTIC_SETTER:
2409 properties [i - first].set = method;
2411 case METHOD_SEMANTIC_GETTER:
2412 properties [i - first].get = method;
2421 mono_class_alloc_ext (class);
2423 mono_image_lock (class->image);
2425 if (class->ext->properties) {
2426 /* We leak 'properties' which was allocated from the image mempool */
2427 mono_image_unlock (class->image);
2431 class->ext->property.first = first;
2432 class->ext->property.count = count;
2434 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2435 mono_memory_barrier ();
2437 /* Leave this assignment as the last op in the function */
2438 class->ext->properties = properties;
2440 mono_image_unlock (class->image);
2444 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2446 MonoMethod **om, **retval;
2449 for (om = methods, count = 0; *om; ++om, ++count)
2452 retval = g_new0 (MonoMethod*, count + 1);
2454 for (om = methods, count = 0; *om; ++om, ++count)
2455 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2460 /*This method can fail the class.*/
2462 mono_class_setup_events (MonoClass *class)
2465 guint startm, endm, i, j;
2466 guint32 cols [MONO_EVENT_SIZE];
2467 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2471 if (class->ext && class->ext->events)
2474 if (class->generic_class) {
2475 MonoClass *gklass = class->generic_class->container_class;
2476 MonoGenericContext *context;
2478 mono_class_setup_events (gklass);
2479 if (gklass->exception_type) {
2480 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2484 first = gklass->ext->event.first;
2485 count = gklass->ext->event.count;
2487 events = mono_class_new0 (class, MonoEvent, count);
2490 context = mono_class_get_context (class);
2492 for (i = 0; i < count; i++) {
2493 MonoEvent *event = &events [i];
2494 MonoEvent *gevent = &gklass->ext->events [i];
2496 event->parent = class;
2497 event->name = gevent->name;
2498 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2499 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2500 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2501 #ifndef MONO_SMALL_CONFIG
2502 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2504 event->attrs = gevent->attrs;
2507 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2508 count = last - first;
2511 mono_class_setup_methods (class);
2512 if (class->exception_type) {
2513 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2518 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2519 for (i = first; i < last; ++i) {
2520 MonoEvent *event = &events [i - first];
2522 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2523 event->parent = class;
2524 event->attrs = cols [MONO_EVENT_FLAGS];
2525 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2527 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2528 for (j = startm; j < endm; ++j) {
2531 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2533 if (class->image->uncompressed_metadata)
2534 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2535 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2537 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2539 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2540 case METHOD_SEMANTIC_ADD_ON:
2541 event->add = method;
2543 case METHOD_SEMANTIC_REMOVE_ON:
2544 event->remove = method;
2546 case METHOD_SEMANTIC_FIRE:
2547 event->raise = method;
2549 case METHOD_SEMANTIC_OTHER: {
2550 #ifndef MONO_SMALL_CONFIG
2553 if (event->other == NULL) {
2554 event->other = g_new0 (MonoMethod*, 2);
2556 while (event->other [n])
2558 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2560 event->other [n] = method;
2561 /* NULL terminated */
2562 event->other [n + 1] = NULL;
2573 mono_class_alloc_ext (class);
2575 mono_image_lock (class->image);
2577 if (class->ext->events) {
2578 mono_image_unlock (class->image);
2582 class->ext->event.first = first;
2583 class->ext->event.count = count;
2585 /* Flush any pending writes as we do double checked locking on class->ext.events */
2586 mono_memory_barrier ();
2588 /* Leave this assignment as the last op in the function */
2589 class->ext->events = events;
2591 mono_image_unlock (class->image);
2595 * Global pool of interface IDs, represented as a bitset.
2596 * LOCKING: Protected by the classes lock.
2598 static MonoBitSet *global_interface_bitset = NULL;
2601 * mono_unload_interface_ids:
2602 * @bitset: bit set of interface IDs
2604 * When an image is unloaded, the interface IDs associated with
2605 * the image are put back in the global pool of IDs so the numbers
2609 mono_unload_interface_ids (MonoBitSet *bitset)
2612 mono_bitset_sub (global_interface_bitset, bitset);
2617 mono_unload_interface_id (MonoClass *class)
2619 if (global_interface_bitset && class->interface_id) {
2621 mono_bitset_clear (global_interface_bitset, class->interface_id);
2627 * mono_get_unique_iid:
2630 * Assign a unique integer ID to the interface represented by @class.
2631 * The ID will positive and as small as possible.
2632 * LOCKING: Acquires the classes lock.
2633 * Returns: the new ID.
2636 mono_get_unique_iid (MonoClass *class)
2640 g_assert (MONO_CLASS_IS_INTERFACE (class));
2644 if (!global_interface_bitset) {
2645 global_interface_bitset = mono_bitset_new (128, 0);
2648 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2650 int old_size = mono_bitset_size (global_interface_bitset);
2651 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2652 mono_bitset_free (global_interface_bitset);
2653 global_interface_bitset = new_set;
2656 mono_bitset_set (global_interface_bitset, iid);
2657 /* set the bit also in the per-image set */
2658 if (!class->generic_class) {
2659 if (class->image->interface_bitset) {
2660 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2661 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2662 mono_bitset_free (class->image->interface_bitset);
2663 class->image->interface_bitset = new_set;
2666 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2668 mono_bitset_set (class->image->interface_bitset, iid);
2673 #ifndef MONO_SMALL_CONFIG
2674 if (mono_print_vtable) {
2676 char *type_name = mono_type_full_name (&class->byval_arg);
2677 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2678 generic_id = class->generic_class->context.class_inst->id;
2679 g_assert (generic_id != 0);
2683 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2688 g_assert (iid <= 65535);
2693 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2698 mono_class_setup_interfaces (klass, error);
2699 if (!mono_error_ok (error))
2702 for (i = 0; i < klass->interface_count; i++) {
2703 ic = klass->interfaces [i];
2706 *res = g_ptr_array_new ();
2707 g_ptr_array_add (*res, ic);
2708 mono_class_init (ic);
2709 if (ic->exception_type) {
2710 mono_error_set_type_load_class (error, ic, "Error Loading class");
2714 collect_implemented_interfaces_aux (ic, res, error);
2715 if (!mono_error_ok (error))
2721 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2723 GPtrArray *res = NULL;
2725 collect_implemented_interfaces_aux (klass, &res, error);
2726 if (!mono_error_ok (error)) {
2728 g_ptr_array_free (res, TRUE);
2735 compare_interface_ids (const void *p_key, const void *p_element) {
2736 const MonoClass *key = p_key;
2737 const MonoClass *element = *(MonoClass**) p_element;
2739 return (key->interface_id - element->interface_id);
2742 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2744 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2745 MonoClass **result = mono_binary_search (
2747 klass->interfaces_packed,
2748 klass->interface_offsets_count,
2749 sizeof (MonoClass *),
2750 compare_interface_ids);
2752 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2758 static gboolean mono_array_class_implements_magic_interface (MonoClass *iface, MonoClass *array_class);
2761 mono_class_array_get_magic_iface_offset (MonoClass *iface, MonoClass *array_class)
2766 if (!mono_array_class_implements_magic_interface (iface, array_class))
2769 gtd = mono_class_get_generic_type_definition (iface);
2771 for (i = 0; i < array_class->interface_offsets_count; i++) {
2772 if (mono_class_get_generic_type_definition (array_class->interfaces_packed [i]) == gtd) {
2773 return array_class->interface_offsets_packed [i];
2781 * mono_class_interface_offset_with_variance:
2783 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2784 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2786 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2788 * FIXME figure out MS disambiguation rules and fix this function.
2791 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2792 int i = mono_class_interface_offset (klass, itf);
2793 *non_exact_match = FALSE;
2797 i = mono_class_array_get_magic_iface_offset (itf, klass);
2799 *non_exact_match = TRUE;
2803 if (!mono_class_has_variant_generic_params (itf))
2806 for (i = 0; i < klass->interface_offsets_count; i++) {
2807 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2808 *non_exact_match = TRUE;
2809 return klass->interface_offsets_packed [i];
2817 print_implemented_interfaces (MonoClass *klass) {
2820 GPtrArray *ifaces = NULL;
2822 int ancestor_level = 0;
2824 name = mono_type_get_full_name (klass);
2825 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2828 for (i = 0; i < klass->interface_offsets_count; i++)
2829 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2830 klass->interfaces_packed [i]->interface_id,
2831 klass->interface_offsets_packed [i],
2832 klass->interfaces_packed [i]->method.count,
2833 klass->interfaces_packed [i]->name_space,
2834 klass->interfaces_packed [i]->name );
2835 printf ("Interface flags: ");
2836 for (i = 0; i <= klass->max_interface_id; i++)
2837 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2838 printf ("(%d,T)", i);
2840 printf ("(%d,F)", i);
2842 printf ("Dump interface flags:");
2843 #ifdef COMPRESSED_INTERFACE_BITMAP
2845 const uint8_t* p = klass->interface_bitmap;
2846 i = klass->max_interface_id;
2848 printf (" %d x 00 %02X", p [0], p [1]);
2854 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2855 printf (" %02X", klass->interface_bitmap [i]);
2858 while (klass != NULL) {
2859 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2860 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2861 if (!mono_error_ok (&error)) {
2862 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2863 mono_error_cleanup (&error);
2864 } else if (ifaces) {
2865 for (i = 0; i < ifaces->len; i++) {
2866 MonoClass *ic = g_ptr_array_index (ifaces, i);
2867 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2868 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2870 mono_class_interface_offset (klass, ic),
2875 g_ptr_array_free (ifaces, TRUE);
2878 klass = klass->parent;
2883 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2886 args [0] = &arg0->byval_arg;
2888 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2892 array_class_get_if_rank (MonoClass *class, guint rank)
2894 return rank ? mono_array_class_get (class, rank) : class;
2898 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2900 valuetype_types [0] = eclass;
2901 if (eclass == mono_defaults.int16_class)
2902 valuetype_types [1] = mono_defaults.uint16_class;
2903 else if (eclass == mono_defaults.uint16_class)
2904 valuetype_types [1] = mono_defaults.int16_class;
2905 else if (eclass == mono_defaults.int32_class)
2906 valuetype_types [1] = mono_defaults.uint32_class;
2907 else if (eclass == mono_defaults.uint32_class)
2908 valuetype_types [1] = mono_defaults.int32_class;
2909 else if (eclass == mono_defaults.int64_class)
2910 valuetype_types [1] = mono_defaults.uint64_class;
2911 else if (eclass == mono_defaults.uint64_class)
2912 valuetype_types [1] = mono_defaults.int64_class;
2913 else if (eclass == mono_defaults.byte_class)
2914 valuetype_types [1] = mono_defaults.sbyte_class;
2915 else if (eclass == mono_defaults.sbyte_class)
2916 valuetype_types [1] = mono_defaults.byte_class;
2917 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2918 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2921 /* this won't be needed once bug #325495 is completely fixed
2922 * though we'll need something similar to know which interfaces to allow
2923 * in arrays when they'll be lazyly created
2925 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2926 * MS returns diferrent types based on which instance is called. For example:
2927 * object obj = new byte[10][];
2928 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2929 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2932 * Fixing this should kill quite some code, save some bits and improve compatibility.
2935 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2937 MonoClass *eclass = class->element_class;
2938 static MonoClass* generic_icollection_class = NULL;
2939 static MonoClass* generic_ienumerable_class = NULL;
2940 static MonoClass* generic_ienumerator_class = NULL;
2941 static MonoClass* generic_ireadonlylist_class = NULL;
2942 static MonoClass* generic_ireadonlycollection_class = NULL;
2943 MonoClass *valuetype_types[2] = { NULL, NULL };
2944 MonoClass **interfaces = NULL;
2945 int i, nifaces, interface_count, real_count, original_rank;
2947 gboolean internal_enumerator;
2948 gboolean eclass_is_valuetype;
2950 internal_enumerator = FALSE;
2951 eclass_is_valuetype = FALSE;
2952 original_rank = eclass->rank;
2953 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2954 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2956 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2958 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2959 original_rank = eclass->rank;
2961 eclass = eclass->element_class;
2962 internal_enumerator = TRUE;
2963 *is_enumerator = TRUE;
2969 /* disable interface generiation for all arrays. */
2975 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2976 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2978 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2980 if (!generic_icollection_class) {
2981 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2982 "System.Collections.Generic", "ICollection`1");
2983 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2984 "System.Collections.Generic", "IEnumerable`1");
2985 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2986 "System.Collections.Generic", "IEnumerator`1");
2987 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2988 "System.Collections.Generic", "IReadOnlyList`1");
2989 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2990 "System.Collections.Generic", "IReadOnlyCollection`1");
2993 mono_class_init (eclass);
2996 * Arrays in 2.0 need to implement a number of generic interfaces
2997 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2998 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2999 * We collect the types needed to build the
3000 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3001 * the generic interfaces needed to implement.
3003 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3004 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3006 if (eclass->valuetype) {
3007 nifaces = generic_ireadonlylist_class ? 5 : 3;
3008 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3010 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3011 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3012 if (internal_enumerator) {
3014 if (valuetype_types [1])
3018 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3019 interfaces [0] = valuetype_types [0];
3020 if (valuetype_types [1])
3021 interfaces [nifaces] = valuetype_types [1];
3023 eclass_is_valuetype = TRUE;
3026 int idepth = eclass->idepth;
3027 if (!internal_enumerator)
3029 nifaces = generic_ireadonlylist_class ? 2 : 3;
3031 // FIXME: This doesn't seem to work/required for generic params
3032 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3033 mono_class_setup_interface_offsets (eclass);
3035 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3036 /* we add object for interfaces and the supertypes for the other
3037 * types. The last of the supertypes is the element class itself which we
3038 * already created the explicit interfaces for (so we include it for IEnumerator
3039 * and exclude it for arrays).
3041 if (MONO_CLASS_IS_INTERFACE (eclass))
3044 interface_count += idepth;
3045 if (eclass->rank && eclass->element_class->valuetype) {
3046 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3047 if (valuetype_types [1])
3050 /* IList, ICollection, IEnumerable, IReadOnlyList */
3051 interface_count *= nifaces;
3052 real_count = interface_count;
3053 if (internal_enumerator) {
3054 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3055 if (valuetype_types [1])
3058 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3059 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3060 interfaces [0] = mono_defaults.object_class;
3064 for (i = 0; i < idepth; i++) {
3065 mono_class_init (eclass->supertypes [i]);
3066 interfaces [j] = eclass->supertypes [i];
3070 if (all_interfaces) {
3071 for (i = 0; i < eclass->interface_offsets_count; i++) {
3072 interfaces [j] = eclass->interfaces_packed [i];
3076 for (i = 0; i < eclass->interface_count; i++) {
3077 interfaces [j] = eclass->interfaces [i];
3081 if (valuetype_types [1]) {
3082 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3087 /* instantiate the generic interfaces */
3088 for (i = 0; i < interface_count; i += nifaces) {
3089 MonoClass *iface = interfaces [i];
3091 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3092 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3094 if (eclass->valuetype) {
3095 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3096 if (generic_ireadonlylist_class) {
3097 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3098 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3101 if (!generic_ireadonlylist_class)
3102 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3105 if (internal_enumerator) {
3107 /* instantiate IEnumerator<iface> */
3108 for (i = 0; i < interface_count; i++) {
3109 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3111 j = interface_count;
3112 if (!eclass_is_valuetype) {
3113 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3114 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3117 for (i = 0; i < eclass->idepth; i++) {
3118 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3122 for (i = 0; i < eclass->interface_offsets_count; i++) {
3123 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3127 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3129 if (valuetype_types [1])
3130 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3134 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3135 for (i = 0; i < real_count; ++i) {
3136 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3137 g_print ("%s implements %s\n", type_name, name);
3148 find_array_interface (MonoClass *klass, const char *name)
3151 for (i = 0; i < klass->interface_count; ++i) {
3152 if (strcmp (klass->interfaces [i]->name, name) == 0)
3159 * Return the number of virtual methods.
3160 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3161 * Return -1 on failure.
3162 * FIXME It would be nice if this information could be cached somewhere.
3165 count_virtual_methods (MonoClass *class)
3169 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3171 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3172 mono_class_setup_methods (class);
3173 if (class->exception_type)
3176 for (i = 0; i < class->method.count; ++i) {
3177 flags = class->methods [i]->flags;
3178 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3182 for (i = 0; i < class->method.count; ++i) {
3183 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3185 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3193 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3201 m = (l + num_ifaces) / 2;
3202 if (interfaces_full [m] == ic)
3204 if (l == num_ifaces)
3206 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3215 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3217 int i = find_interface (num_ifaces, interfaces_full, ic);
3219 return interface_offsets_full [i];
3224 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3226 int i = find_interface (num_ifaces, interfaces_full, ic);
3230 interface_offsets_full [i] = offset;
3233 for (i = 0; i < num_ifaces; ++i) {
3234 if (interfaces_full [i]) {
3236 if (interfaces_full [i]->interface_id < ic->interface_id)
3239 while (end < num_ifaces && interfaces_full [end]) end++;
3240 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3241 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3243 interfaces_full [i] = ic;
3244 interface_offsets_full [i] = offset;
3250 #ifdef COMPRESSED_INTERFACE_BITMAP
3253 * Compressed interface bitmap design.
3255 * Interface bitmaps take a large amount of memory, because their size is
3256 * linear with the maximum interface id assigned in the process (each interface
3257 * is assigned a unique id as it is loaded). The number of interface classes
3258 * is high because of the many implicit interfaces implemented by arrays (we'll
3259 * need to lazy-load them in the future).
3260 * Most classes implement a very small number of interfaces, so the bitmap is
3261 * sparse. This bitmap needs to be checked by interface casts, so access to the
3262 * needed bit must be fast and doable with few jit instructions.
3264 * The current compression format is as follows:
3265 * *) it is a sequence of one or more two-byte elements
3266 * *) the first byte in the element is the count of empty bitmap bytes
3267 * at the current bitmap position
3268 * *) the second byte in the element is an actual bitmap byte at the current
3271 * As an example, the following compressed bitmap bytes:
3272 * 0x07 0x01 0x00 0x7
3273 * correspond to the following bitmap:
3274 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3276 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3277 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3278 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3282 * mono_compress_bitmap:
3283 * @dest: destination buffer
3284 * @bitmap: bitmap buffer
3285 * @size: size of @bitmap in bytes
3287 * This is a mono internal function.
3288 * The @bitmap data is compressed into a format that is small but
3289 * still searchable in few instructions by the JIT and runtime.
3290 * The compressed data is stored in the buffer pointed to by the
3291 * @dest array. Passing a #NULL value for @dest allows to just compute
3292 * the size of the buffer.
3293 * This compression algorithm assumes the bits set in the bitmap are
3294 * few and far between, like in interface bitmaps.
3295 * Returns: the size of the compressed bitmap in bytes.
3298 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3302 const uint8_t *end = bitmap + size;
3303 while (bitmap < end) {
3304 if (*bitmap || numz == 255) {
3328 * mono_class_interface_match:
3329 * @bitmap: a compressed bitmap buffer
3330 * @id: the index to check in the bitmap
3332 * This is a mono internal function.
3333 * Checks if a bit is set in a compressed interface bitmap. @id must
3334 * be already checked for being smaller than the maximum id encoded in the
3337 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3341 mono_class_interface_match (const uint8_t *bitmap, int id)
3344 id -= bitmap [0] * 8;
3348 return bitmap [1] & (1 << id);
3357 * LOCKING: this is supposed to be called with the loader lock held.
3358 * Return -1 on failure and set exception_type
3361 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3365 int i, j, max_iid, num_ifaces;
3366 MonoClass **interfaces_full = NULL;
3367 int *interface_offsets_full = NULL;
3369 GPtrArray **ifaces_array = NULL;
3370 int interface_offsets_count;
3371 MonoClass **array_interfaces = NULL;
3372 int num_array_interfaces;
3373 int is_enumerator = FALSE;
3375 mono_class_setup_supertypes (class);
3377 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3378 * implicit interfaces have the property that they are assigned the same slot in the
3379 * vtables for compatible interfaces
3381 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3382 g_assert (!(num_array_interfaces > 0 && !is_enumerator));
3384 /* compute maximum number of slots and maximum interface id */
3386 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3387 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3388 for (j = 0; j < class->idepth; j++) {
3389 k = class->supertypes [j];
3390 num_ifaces += k->interface_count;
3391 for (i = 0; i < k->interface_count; i++) {
3392 ic = k->interfaces [i];
3395 mono_class_init (ic);
3397 if (max_iid < ic->interface_id)
3398 max_iid = ic->interface_id;
3400 ifaces = mono_class_get_implemented_interfaces (k, &error);
3401 if (!mono_error_ok (&error)) {
3402 char *name = mono_type_get_full_name (k);
3403 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3405 mono_error_cleanup (&error);
3410 num_ifaces += ifaces->len;
3411 for (i = 0; i < ifaces->len; ++i) {
3412 ic = g_ptr_array_index (ifaces, i);
3413 if (max_iid < ic->interface_id)
3414 max_iid = ic->interface_id;
3416 ifaces_array [j] = ifaces;
3420 for (i = 0; i < num_array_interfaces; ++i) {
3421 ic = array_interfaces [i];
3422 mono_class_init (ic);
3423 if (max_iid < ic->interface_id)
3424 max_iid = ic->interface_id;
3427 if (MONO_CLASS_IS_INTERFACE (class)) {
3429 if (max_iid < class->interface_id)
3430 max_iid = class->interface_id;
3432 class->max_interface_id = max_iid;
3433 /* compute vtable offset for interfaces */
3434 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3435 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3437 for (i = 0; i < num_ifaces; i++) {
3438 interface_offsets_full [i] = -1;
3441 /* skip the current class */
3442 for (j = 0; j < class->idepth - 1; j++) {
3443 k = class->supertypes [j];
3444 ifaces = ifaces_array [j];
3447 for (i = 0; i < ifaces->len; ++i) {
3449 ic = g_ptr_array_index (ifaces, i);
3451 /*Force the sharing of interface offsets between parent and subtypes.*/
3452 io = mono_class_interface_offset (k, ic);
3454 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3459 g_assert (class == class->supertypes [class->idepth - 1]);
3460 ifaces = ifaces_array [class->idepth - 1];
3462 for (i = 0; i < ifaces->len; ++i) {
3464 ic = g_ptr_array_index (ifaces, i);
3465 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3467 count = count_virtual_methods (ic);
3469 char *name = mono_type_get_full_name (ic);
3470 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3479 if (MONO_CLASS_IS_INTERFACE (class))
3480 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3482 if (num_array_interfaces) {
3483 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3484 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3485 g_assert (ienumerator_offset >= 0);
3486 for (i = 0; i < num_array_interfaces; ++i) {
3487 ic = array_interfaces [i];
3488 if (strcmp (ic->name, "IEnumerator`1") == 0)
3489 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3491 g_assert_not_reached ();
3492 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/
3496 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3497 if (interface_offsets_full [i] != -1) {
3498 interface_offsets_count ++;
3503 * We might get called multiple times:
3504 * - mono_class_init ()
3505 * - mono_class_setup_vtable ().
3506 * - mono_class_setup_interface_offsets ().
3507 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3508 * means we have to overwrite those when called from other places (#4440).
3510 if (class->interfaces_packed && !overwrite) {
3511 g_assert (class->interface_offsets_count == interface_offsets_count);
3515 class->interface_offsets_count = interface_offsets_count;
3516 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3517 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3518 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3519 #ifdef COMPRESSED_INTERFACE_BITMAP
3520 bitmap = g_malloc0 (bsize);
3522 bitmap = mono_class_alloc0 (class, bsize);
3524 for (i = 0; i < interface_offsets_count; i++) {
3525 int id = interfaces_full [i]->interface_id;
3526 bitmap [id >> 3] |= (1 << (id & 7));
3527 class->interfaces_packed [i] = interfaces_full [i];
3528 class->interface_offsets_packed [i] = interface_offsets_full [i];
3529 /*if (num_array_interfaces)
3530 g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&class->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
3532 #ifdef COMPRESSED_INTERFACE_BITMAP
3533 i = mono_compress_bitmap (NULL, bitmap, bsize);
3534 class->interface_bitmap = mono_class_alloc0 (class, i);
3535 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3538 class->interface_bitmap = bitmap;
3543 g_free (interfaces_full);
3544 g_free (interface_offsets_full);
3545 g_free (array_interfaces);
3546 for (i = 0; i < class->idepth; i++) {
3547 ifaces = ifaces_array [i];
3549 g_ptr_array_free (ifaces, TRUE);
3551 g_free (ifaces_array);
3553 //printf ("JUST DONE: ");
3554 //print_implemented_interfaces (class);
3560 * Setup interface offsets for interfaces.
3562 * - class->max_interface_id
3563 * - class->interface_offsets_count
3564 * - class->interfaces_packed
3565 * - class->interface_offsets_packed
3566 * - class->interface_bitmap
3568 * This function can fail @class.
3571 mono_class_setup_interface_offsets (MonoClass *class)
3573 mono_loader_lock ();
3575 setup_interface_offsets (class, 0, FALSE);
3577 mono_loader_unlock ();
3580 /*Checks if @klass has @parent as one of it's parents type gtd
3584 * Bar<T> : Foo<Bar<Bar<T>>>
3588 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3590 klass = mono_class_get_generic_type_definition (klass);
3591 parent = mono_class_get_generic_type_definition (parent);
3592 mono_class_setup_supertypes (klass);
3593 mono_class_setup_supertypes (parent);
3595 return klass->idepth >= parent->idepth &&
3596 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3600 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3602 MonoGenericInst *ginst;
3604 if (!class->generic_class) {
3605 mono_class_setup_vtable_full (class, in_setup);
3606 return class->exception_type == 0;
3609 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3610 if (class->generic_class->container_class->exception_type) {
3611 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3615 ginst = class->generic_class->context.class_inst;
3616 for (i = 0; i < ginst->type_argc; ++i) {
3618 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3620 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3621 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3622 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3624 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3625 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3633 * mono_class_setup_vtable:
3635 * Creates the generic vtable of CLASS.
3636 * Initializes the following fields in MonoClass:
3639 * Plus all the fields initialized by setup_interface_offsets ().
3640 * If there is an error during vtable construction, class->exception_type is set.
3642 * LOCKING: Acquires the loader lock.
3645 mono_class_setup_vtable (MonoClass *class)
3647 mono_class_setup_vtable_full (class, NULL);
3651 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3653 MonoMethod **overrides;
3654 MonoGenericContext *context;
3662 if (MONO_CLASS_IS_INTERFACE (class)) {
3663 /* This sets method->slot for all methods if this is an interface */
3664 mono_class_setup_methods (class);
3668 if (class->exception_type)
3671 if (g_list_find (in_setup, class))
3674 mono_loader_lock ();
3676 if (class->vtable) {
3677 mono_loader_unlock ();
3681 mono_stats.generic_vtable_count ++;
3682 in_setup = g_list_prepend (in_setup, class);
3684 if (class->generic_class) {
3685 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3686 mono_loader_unlock ();
3687 g_list_remove (in_setup, class);
3691 context = mono_class_get_context (class);
3692 type_token = class->generic_class->container_class->type_token;
3694 context = (MonoGenericContext *) class->generic_container;
3695 type_token = class->type_token;
3698 if (image_is_dynamic (class->image)) {
3699 /* Generic instances can have zero method overrides without causing any harm.
3700 * This is true since we don't do layout all over again for them, we simply inflate
3701 * the layout of the parent.
3703 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3705 /* The following call fails if there are missing methods in the type */
3706 /* FIXME it's probably a good idea to avoid this for generic instances. */
3707 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3711 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3713 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3717 mono_loader_unlock ();
3718 g_list_remove (in_setup, class);
3723 #define DEBUG_INTERFACE_VTABLE_CODE 0
3724 #define TRACE_INTERFACE_VTABLE_CODE 0
3725 #define VERIFY_INTERFACE_VTABLE_CODE 0
3726 #define VTABLE_SELECTOR (1)
3728 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3729 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3730 if (!(VTABLE_SELECTOR)) break; \
3734 #define DEBUG_INTERFACE_VTABLE(stmt)
3737 #if TRACE_INTERFACE_VTABLE_CODE
3738 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3739 if (!(VTABLE_SELECTOR)) break; \
3743 #define TRACE_INTERFACE_VTABLE(stmt)
3746 #if VERIFY_INTERFACE_VTABLE_CODE
3747 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3748 if (!(VTABLE_SELECTOR)) break; \
3752 #define VERIFY_INTERFACE_VTABLE(stmt)
3756 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3758 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3762 GString *res = g_string_new ("");
3764 g_string_append_c (res, '(');
3765 for (i = 0; i < sig->param_count; ++i) {
3767 g_string_append_c (res, ',');
3768 mono_type_get_desc (res, sig->params [i], include_namespace);
3770 g_string_append (res, ")=>");
3771 if (sig->ret != NULL) {
3772 mono_type_get_desc (res, sig->ret, include_namespace);
3774 g_string_append (res, "NULL");
3777 g_string_free (res, FALSE);
3781 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3782 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3783 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3784 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3792 is_wcf_hack_disabled (void)
3794 static gboolean disabled;
3795 static gboolean inited = FALSE;
3797 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3804 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
3805 MonoMethodSignature *cmsig, *imsig;
3806 if (strcmp (im->name, cm->name) == 0) {
3807 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3808 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3811 if (! slot_is_empty) {
3812 if (require_newslot) {
3813 if (! interface_is_explicitly_implemented_by_class) {
3814 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3817 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3818 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3822 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3825 cmsig = mono_method_signature (cm);
3826 imsig = mono_method_signature (im);
3827 if (!cmsig || !imsig) {
3828 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3832 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3833 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3834 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3835 TRACE_INTERFACE_VTABLE (printf ("]"));
3838 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3839 /* CAS - SecurityAction.InheritanceDemand on interface */
3840 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3841 mono_secman_inheritancedemand_method (cm, im);
3844 if (mono_security_core_clr_enabled ())
3845 mono_security_core_clr_check_override (class, cm, im);
3847 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3848 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3849 char *body_name = mono_method_full_name (cm, TRUE);
3850 char *decl_name = mono_method_full_name (im, TRUE);
3851 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
3859 MonoClass *ic = im->klass;
3860 const char *ic_name_space = ic->name_space;
3861 const char *ic_name = ic->name;
3864 if (! require_newslot) {
3865 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3868 if (cm->klass->rank == 0) {
3869 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3872 cmsig = mono_method_signature (cm);
3873 imsig = mono_method_signature (im);
3874 if (!cmsig || !imsig) {
3875 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3879 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3880 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3881 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3882 TRACE_INTERFACE_VTABLE (printf ("]"));
3885 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3886 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3889 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3890 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3893 if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0) && (strcmp (ic_name, "IReadOnlyList`1") != 0) && (strcmp (ic_name, "IReadOnlyCollection`1") != 0))) {
3894 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3898 subname = strstr (cm->name, ic_name_space);
3899 if (subname != cm->name) {
3900 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3903 subname += strlen (ic_name_space);
3904 if (subname [0] != '.') {
3905 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3909 if (strstr (subname, ic_name) != subname) {
3910 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3913 subname += strlen (ic_name);
3914 if (subname [0] != '.') {
3915 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3919 if (strcmp (subname, im->name) != 0) {
3920 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3924 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3925 /* CAS - SecurityAction.InheritanceDemand on interface */
3926 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3927 mono_secman_inheritancedemand_method (cm, im);
3930 if (mono_security_core_clr_enabled ())
3931 mono_security_core_clr_check_override (class, cm, im);
3933 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3934 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3935 char *body_name = mono_method_full_name (cm, TRUE);
3936 char *decl_name = mono_method_full_name (im, TRUE);
3937 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
3947 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3949 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3950 MonoMethod *method = key;
3951 MonoMethod *override = value;
3952 MonoClass *method_class = mono_method_get_class (method);
3953 MonoClass *override_class = mono_method_get_class (override);
3955 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3956 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3957 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3960 print_overrides (GHashTable *override_map, const char *message) {
3962 printf ("Override map \"%s\" START:\n", message);
3963 g_hash_table_foreach (override_map, foreach_override, NULL);
3964 printf ("Override map \"%s\" END.\n", message);
3966 printf ("Override map \"%s\" EMPTY.\n", message);
3970 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3971 char *full_name = mono_type_full_name (&class->byval_arg);
3975 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3977 if (print_interfaces) {
3978 print_implemented_interfaces (class);
3979 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3982 if (class->parent) {
3983 parent_size = class->parent->vtable_size;
3987 for (i = 0; i < size; ++i) {
3988 MonoMethod *cm = vtable [i];
3989 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3990 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3992 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4000 #if VERIFY_INTERFACE_VTABLE_CODE
4002 mono_method_try_get_vtable_index (MonoMethod *method)
4004 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4005 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4006 if (imethod->declaring->is_generic)
4007 return imethod->declaring->slot;
4009 return method->slot;
4013 mono_class_verify_vtable (MonoClass *class)
4016 char *full_name = mono_type_full_name (&class->byval_arg);
4018 printf ("*** Verifying VTable of class '%s' \n", full_name);
4022 if (!class->methods)
4025 for (i = 0; i < class->method.count; ++i) {
4026 MonoMethod *cm = class->methods [i];
4029 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4033 full_name = mono_method_full_name (cm, TRUE);
4035 slot = mono_method_try_get_vtable_index (cm);
4037 if (slot >= class->vtable_size) {
4038 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4042 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4043 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4044 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4045 g_free (other_name);
4048 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4055 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4057 char *method_signature;
4060 for (index = 0; index < onum; ++index) {
4061 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4062 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4064 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4065 type_name = mono_type_full_name (&class->byval_arg);
4066 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4067 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4068 g_free (method_signature);
4070 mono_class_setup_methods (class);
4071 if (class->exception_type) {
4072 char *name = mono_type_get_full_name (class);
4073 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4077 for (index = 0; index < class->method.count; ++index) {
4078 MonoMethod *cm = class->methods [index];
4079 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4081 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4082 g_free (method_signature);
4087 mono_method_get_method_definition (MonoMethod *method)
4089 while (method->is_inflated)
4090 method = ((MonoMethodInflated*)method)->declaring;
4095 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4099 for (i = 0; i < onum; ++i) {
4100 MonoMethod *decl = overrides [i * 2];
4101 MonoMethod *body = overrides [i * 2 + 1];
4103 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4104 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4108 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4109 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4110 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4112 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4116 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4117 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4118 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4120 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4124 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4125 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4129 body = mono_method_get_method_definition (body);
4130 decl = mono_method_get_method_definition (decl);
4132 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4133 char *body_name = mono_method_full_name (body, TRUE);
4134 char *decl_name = mono_method_full_name (decl, TRUE);
4135 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4145 mono_class_need_stelemref_method (MonoClass *class)
4147 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4151 * LOCKING: this is supposed to be called with the loader lock held.
4154 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4158 MonoMethod **vtable;
4159 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4160 GPtrArray *ifaces = NULL;
4161 GHashTable *override_map = NULL;
4162 gboolean security_enabled = mono_security_enabled ();
4164 gpointer class_iter;
4165 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4166 int first_non_interface_slot;
4168 GSList *virt_methods = NULL, *l;
4169 int stelemref_slot = 0;
4174 if (overrides && !verify_class_overrides (class, overrides, onum))
4177 ifaces = mono_class_get_implemented_interfaces (class, &error);
4178 if (!mono_error_ok (&error)) {
4179 char *name = mono_type_get_full_name (class);
4180 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4182 mono_error_cleanup (&error);
4184 } else if (ifaces) {
4185 for (i = 0; i < ifaces->len; i++) {
4186 MonoClass *ic = g_ptr_array_index (ifaces, i);
4187 max_vtsize += ic->method.count;
4189 g_ptr_array_free (ifaces, TRUE);
4193 if (class->parent) {
4194 mono_class_init (class->parent);
4195 mono_class_setup_vtable_full (class->parent, in_setup);
4197 if (class->parent->exception_type) {
4198 char *name = mono_type_get_full_name (class->parent);
4199 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4204 max_vtsize += class->parent->vtable_size;
4205 cur_slot = class->parent->vtable_size;
4208 max_vtsize += class->method.count;
4210 /*Array have a slot for stelemref*/
4211 if (mono_class_need_stelemref_method (class)) {
4212 stelemref_slot = cur_slot;
4217 vtable = alloca (sizeof (gpointer) * max_vtsize);
4218 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4220 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4222 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4223 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4226 max_iid = class->max_interface_id;
4227 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4229 /* Optimized version for generic instances */
4230 if (class->generic_class) {
4232 MonoClass *gklass = class->generic_class->container_class;
4235 mono_class_setup_vtable_full (gklass, in_setup);
4236 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4237 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4241 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4242 class->vtable_size = gklass->vtable_size;
4243 for (i = 0; i < gklass->vtable_size; ++i)
4244 if (gklass->vtable [i]) {
4245 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4246 if (!mono_error_ok (&error)) {
4247 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4248 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4250 mono_error_cleanup (&error);
4254 tmp [i]->slot = gklass->vtable [i]->slot;
4256 mono_memory_barrier ();
4257 class->vtable = tmp;
4259 /* Have to set method->slot for abstract virtual methods */
4260 if (class->methods && gklass->methods) {
4261 for (i = 0; i < class->method.count; ++i)
4262 if (class->methods [i]->slot == -1)
4263 class->methods [i]->slot = gklass->methods [i]->slot;
4269 if (class->parent && class->parent->vtable_size) {
4270 MonoClass *parent = class->parent;
4273 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4275 // Also inherit parent interface vtables, just as a starting point.
4276 // This is needed otherwise bug-77127.exe fails when the property methods
4277 // have different names in the iterface and the class, because for child
4278 // classes the ".override" information is not used anymore.
4279 for (i = 0; i < parent->interface_offsets_count; i++) {
4280 MonoClass *parent_interface = parent->interfaces_packed [i];
4281 int interface_offset = mono_class_interface_offset (class, parent_interface);
4282 /*FIXME this is now dead code as this condition will never hold true.
4283 Since interface offsets are inherited then the offset of an interface implemented
4284 by a parent will never be the out of it's vtable boundary.
4286 if (interface_offset >= parent->vtable_size) {
4287 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4290 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4291 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4292 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4293 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4294 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4295 parent_interface_offset + j, parent_interface_offset, j,
4296 interface_offset + j, interface_offset, j));
4303 /*Array have a slot for stelemref*/
4304 if (mono_class_need_stelemref_method (class)) {
4305 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4307 method->slot = stelemref_slot;
4309 g_assert (method->slot == stelemref_slot);
4311 vtable [stelemref_slot] = method;
4314 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4315 /* override interface methods */
4316 for (i = 0; i < onum; i++) {
4317 MonoMethod *decl = overrides [i*2];
4318 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4320 dslot = mono_method_get_vtable_slot (decl);
4322 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4326 dslot += mono_class_interface_offset (class, decl->klass);
4327 vtable [dslot] = overrides [i*2 + 1];
4328 vtable [dslot]->slot = dslot;
4330 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4332 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4334 if (mono_security_core_clr_enabled ())
4335 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4338 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4339 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4342 * Create a list of virtual methods to avoid calling
4343 * mono_class_get_virtual_methods () which is slow because of the metadata
4347 gpointer iter = NULL;
4350 virt_methods = NULL;
4351 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4352 virt_methods = g_slist_prepend (virt_methods, cm);
4354 if (class->exception_type)
4358 // Loop on all implemented interfaces...
4359 for (i = 0; i < class->interface_offsets_count; i++) {
4360 MonoClass *parent = class->parent;
4362 gboolean interface_is_explicitly_implemented_by_class;
4365 ic = class->interfaces_packed [i];
4366 ic_offset = mono_class_interface_offset (class, ic);
4368 mono_class_setup_methods (ic);
4369 if (ic->exception_type)
4372 // Check if this interface is explicitly implemented (instead of just inherited)
4373 if (parent != NULL) {
4374 int implemented_interfaces_index;
4375 interface_is_explicitly_implemented_by_class = FALSE;
4376 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4377 if (ic == class->interfaces [implemented_interfaces_index]) {
4378 interface_is_explicitly_implemented_by_class = TRUE;
4383 interface_is_explicitly_implemented_by_class = TRUE;
4386 // Loop on all interface methods...
4387 for (im_index = 0; im_index < ic->method.count; im_index++) {
4388 MonoMethod *im = ic->methods [im_index];
4389 int im_slot = ic_offset + im->slot;
4390 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4392 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4395 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4397 // If there is an explicit implementation, just use it right away,
4398 // otherwise look for a matching method
4399 if (override_im == NULL) {
4404 // First look for a suitable method among the class methods
4406 for (l = virt_methods; l; l = l->next) {
4408 TRACE_INTERFACE_VTABLE (printf (" For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL)));
4409 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4410 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4411 vtable [im_slot] = cm;
4412 /* Why do we need this? */
4417 TRACE_INTERFACE_VTABLE (printf ("\n"));
4418 if (class->exception_type) /*Might be set by check_interface_method_override*/
4422 // If the slot is still empty, look in all the inherited virtual methods...
4423 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4424 MonoClass *parent = class->parent;
4425 // Reverse order, so that last added methods are preferred
4426 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4427 MonoMethod *cm = parent->vtable [cm_index];
4429 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf (" For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name));
4430 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4431 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4432 vtable [im_slot] = cm;
4433 /* Why do we need this? */
4439 if (class->exception_type) /*Might be set by check_interface_method_override*/
4441 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4445 g_assert (vtable [im_slot] == override_im);
4450 // If the class is not abstract, check that all its interface slots are full.
4451 // The check is done here and not directly at the end of the loop above because
4452 // it can happen (for injected generic array interfaces) that the same slot is
4453 // processed multiple times (those interfaces have overlapping slots), and it
4454 // will not always be the first pass the one that fills the slot.
4455 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4456 for (i = 0; i < class->interface_offsets_count; i++) {
4460 ic = class->interfaces_packed [i];
4461 ic_offset = mono_class_interface_offset (class, ic);
4463 for (im_index = 0; im_index < ic->method.count; im_index++) {
4464 MonoMethod *im = ic->methods [im_index];
4465 int im_slot = ic_offset + im->slot;
4467 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4470 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4471 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4472 if (vtable [im_slot] == NULL) {
4473 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4480 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4482 for (l = virt_methods; l; l = l->next) {
4485 * If the method is REUSE_SLOT, we must check in the
4486 * base class for a method to override.
4488 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4490 for (k = class->parent; k ; k = k->parent) {
4495 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4496 MonoMethodSignature *cmsig, *m1sig;
4498 cmsig = mono_method_signature (cm);
4499 m1sig = mono_method_signature (m1);
4501 if (!cmsig || !m1sig) {
4502 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4506 if (!strcmp(cm->name, m1->name) &&
4507 mono_metadata_signature_equal (cmsig, m1sig)) {
4509 /* CAS - SecurityAction.InheritanceDemand */
4510 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4511 mono_secman_inheritancedemand_method (cm, m1);
4514 if (mono_security_core_clr_enabled ())
4515 mono_security_core_clr_check_override (class, cm, m1);
4517 slot = mono_method_get_vtable_slot (m1);
4521 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4522 char *body_name = mono_method_full_name (cm, TRUE);
4523 char *decl_name = mono_method_full_name (m1, TRUE);
4524 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4530 g_assert (cm->slot < max_vtsize);
4532 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4533 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4534 mono_method_full_name (m1, 1), m1,
4535 mono_method_full_name (cm, 1), cm));
4536 g_hash_table_insert (override_map, m1, cm);
4540 if (k->exception_type)
4550 /*Non final newslot methods must be given a non-interface vtable slot*/
4551 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4555 cm->slot = cur_slot++;
4557 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4558 vtable [cm->slot] = cm;
4561 /* override non interface methods */
4562 for (i = 0; i < onum; i++) {
4563 MonoMethod *decl = overrides [i*2];
4564 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4565 g_assert (decl->slot != -1);
4566 vtable [decl->slot] = overrides [i*2 + 1];
4567 overrides [i * 2 + 1]->slot = decl->slot;
4569 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4570 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4571 mono_method_full_name (decl, 1), decl,
4572 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4573 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4575 if (mono_security_core_clr_enabled ())
4576 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4581 * If a method occupies more than one place in the vtable, and it is
4582 * overriden, then change the other occurances too.
4587 for (i = 0; i < max_vtsize; ++i)
4589 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4591 cm = g_hash_table_lookup (override_map, vtable [i]);
4596 g_hash_table_destroy (override_map);
4597 override_map = NULL;
4600 g_slist_free (virt_methods);
4601 virt_methods = NULL;
4603 /* Ensure that all vtable slots are filled with concrete instance methods */
4604 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4605 for (i = 0; i < cur_slot; ++i) {
4606 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4607 char *type_name = mono_type_get_full_name (class);
4608 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4609 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4611 g_free (method_name);
4617 if (class->generic_class) {
4618 MonoClass *gklass = class->generic_class->container_class;
4620 mono_class_init (gklass);
4622 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4624 /* Check that the vtable_size value computed in mono_class_init () is correct */
4625 if (class->vtable_size)
4626 g_assert (cur_slot == class->vtable_size);
4627 class->vtable_size = cur_slot;
4630 /* Try to share the vtable with our parent. */
4631 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4632 mono_memory_barrier ();
4633 class->vtable = class->parent->vtable;
4635 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4636 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4637 mono_memory_barrier ();
4638 class->vtable = tmp;
4641 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4642 if (mono_print_vtable) {
4645 print_implemented_interfaces (class);
4647 for (i = 0; i <= max_iid; i++)
4648 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4651 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4652 class->vtable_size, icount);
4654 for (i = 0; i < cur_slot; ++i) {
4659 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4660 mono_method_full_name (cm, TRUE));
4666 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4667 class->name, max_iid);
4669 for (i = 0; i < class->interface_count; i++) {
4670 ic = class->interfaces [i];
4671 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4672 mono_class_interface_offset (class, ic),
4673 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4676 for (k = class->parent; k ; k = k->parent) {
4677 for (i = 0; i < k->interface_count; i++) {
4678 ic = k->interfaces [i];
4679 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4680 mono_class_interface_offset (class, ic),
4681 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4687 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4692 char *name = mono_type_get_full_name (class);
4693 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4696 g_hash_table_destroy (override_map);
4698 g_slist_free (virt_methods);
4703 * mono_method_get_vtable_slot:
4705 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4706 * LOCKING: Acquires the loader lock.
4708 * FIXME Use proper MonoError machinery here.
4711 mono_method_get_vtable_slot (MonoMethod *method)
4713 if (method->slot == -1) {
4714 mono_class_setup_vtable (method->klass);
4715 if (method->klass->exception_type)
4717 if (method->slot == -1) {
4721 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4722 g_assert (method->klass->generic_class);
4723 gklass = method->klass->generic_class->container_class;
4724 mono_class_setup_methods (method->klass);
4725 g_assert (method->klass->methods);
4726 for (i = 0; i < method->klass->method.count; ++i) {
4727 if (method->klass->methods [i] == method)
4730 g_assert (i < method->klass->method.count);
4731 g_assert (gklass->methods);
4732 method->slot = gklass->methods [i]->slot;
4734 g_assert (method->slot != -1);
4736 return method->slot;
4740 * mono_method_get_vtable_index:
4743 * Returns the index into the runtime vtable to access the method or,
4744 * in the case of a virtual generic method, the virtual generic method
4745 * thunk. Returns -1 on failure.
4747 * FIXME Use proper MonoError machinery here.
4750 mono_method_get_vtable_index (MonoMethod *method)
4752 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4753 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4754 if (imethod->declaring->is_generic)
4755 return mono_method_get_vtable_slot (imethod->declaring);
4757 return mono_method_get_vtable_slot (method);
4760 static MonoMethod *default_ghc = NULL;
4761 static MonoMethod *default_finalize = NULL;
4762 static int finalize_slot = -1;
4763 static int ghc_slot = -1;
4766 initialize_object_slots (MonoClass *class)
4771 if (class == mono_defaults.object_class) {
4772 mono_class_setup_vtable (class);
4773 for (i = 0; i < class->vtable_size; ++i) {
4774 MonoMethod *cm = class->vtable [i];
4776 if (!strcmp (cm->name, "GetHashCode"))
4778 else if (!strcmp (cm->name, "Finalize"))
4782 g_assert (ghc_slot > 0);
4783 default_ghc = class->vtable [ghc_slot];
4785 g_assert (finalize_slot > 0);
4786 default_finalize = class->vtable [finalize_slot];
4791 MonoMethod *array_method;
4793 } GenericArrayMethodInfo;
4795 static int generic_array_method_num = 0;
4796 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4799 generic_array_methods (MonoClass *class)
4801 int i, count_generic = 0;
4802 GList *list = NULL, *tmp;
4803 if (generic_array_method_num)
4804 return generic_array_method_num;
4805 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4806 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4807 for (i = 0; i < class->parent->method.count; i++) {
4808 MonoMethod *m = class->parent->methods [i];
4809 if (!strncmp (m->name, "InternalArray__", 15)) {
4811 list = g_list_prepend (list, m);
4814 list = g_list_reverse (list);
4815 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4817 for (tmp = list; tmp; tmp = tmp->next) {
4818 const char *mname, *iname;
4820 MonoMethod *m = tmp->data;
4821 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4822 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4824 generic_array_method_info [i].array_method = m;
4825 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4826 iname = "System.Collections.Generic.ICollection`1.";
4827 mname = m->name + 27;
4828 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4829 iname = "System.Collections.Generic.IEnumerable`1.";
4830 mname = m->name + 27;
4831 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4832 iname = "System.Collections.Generic.IReadOnlyList`1.";
4833 mname = m->name + strlen (ireadonlylist_prefix);
4834 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4835 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4836 mname = m->name + strlen (ireadonlycollection_prefix);
4837 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4838 iname = "System.Collections.Generic.IList`1.";
4839 mname = m->name + 15;
4841 g_assert_not_reached ();
4844 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4845 strcpy (name, iname);
4846 strcpy (name + strlen (iname), mname);
4847 generic_array_method_info [i].name = name;
4850 /*g_print ("array generic methods: %d\n", count_generic);*/
4852 generic_array_method_num = count_generic;
4854 return generic_array_method_num;
4858 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4860 MonoGenericContext tmp_context;
4863 tmp_context.class_inst = NULL;
4864 tmp_context.method_inst = iface->generic_class->context.class_inst;
4865 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4867 for (i = 0; i < generic_array_method_num; i++) {
4868 MonoMethod *m = generic_array_method_info [i].array_method;
4869 MonoMethod *inflated;
4871 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4872 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4877 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4879 int null_length = strlen ("(null)");
4880 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4881 char *s = mono_image_alloc (image, len);
4884 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4885 g_assert (result == len - 1);
4891 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4893 gpointer exception_data = NULL;
4895 switch (error->exception_type) {
4896 case MONO_EXCEPTION_TYPE_LOAD:
4897 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4900 case MONO_EXCEPTION_MISSING_METHOD:
4901 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4904 case MONO_EXCEPTION_MISSING_FIELD: {
4905 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4906 const char *class_name;
4909 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4911 class_name = error->klass->name;
4913 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4916 g_free ((void*)class_name);
4920 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4923 if (error->ref_only)
4924 msg = "Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.";
4926 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4928 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4932 case MONO_EXCEPTION_BAD_IMAGE:
4933 exception_data = error->msg;
4937 g_assert_not_reached ();
4940 mono_class_set_failure (class, error->exception_type, exception_data);
4945 * @class: the class to initialize
4947 * Compute the instance_size, class_size and other infos that cannot be
4948 * computed at mono_class_get() time. Also compute vtable_size if possible.
4949 * Returns TRUE on success or FALSE if there was a problem in loading
4950 * the type (incorrect assemblies, missing assemblies, methods, etc).
4952 * LOCKING: Acquires the loader lock.
4955 mono_class_init (MonoClass *class)
4958 MonoCachedClassInfo cached_info;
4959 gboolean has_cached_info;
4963 /* Double-checking locking pattern */
4964 if (class->inited || class->exception_type)
4965 return class->exception_type == MONO_EXCEPTION_NONE;
4967 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4969 /* We do everything inside the lock to prevent races */
4970 mono_loader_lock ();
4972 if (class->inited || class->exception_type) {
4973 mono_loader_unlock ();
4974 /* Somebody might have gotten in before us */
4975 return class->exception_type == MONO_EXCEPTION_NONE;
4978 if (class->init_pending) {
4979 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4983 class->init_pending = 1;
4985 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4986 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4991 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4992 MonoClass *element_class = class->element_class;
4993 if (!element_class->inited)
4994 mono_class_init (element_class);
4995 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4996 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5001 /* CAS - SecurityAction.InheritanceDemand */
5002 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5003 mono_secman_inheritancedemand_class (class, class->parent);
5006 mono_stats.initialized_class_count++;
5008 if (class->generic_class && !class->generic_class->is_dynamic) {
5009 MonoClass *gklass = class->generic_class->container_class;
5011 mono_stats.generic_class_count++;
5013 class->method = gklass->method;
5014 class->field = gklass->field;
5016 mono_class_init (gklass);
5017 // FIXME: Why is this needed ?
5018 if (!gklass->exception_type)
5019 mono_class_setup_methods (gklass);
5020 if (gklass->exception_type) {
5021 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5025 if (MONO_CLASS_IS_INTERFACE (class))
5026 class->interface_id = mono_get_unique_iid (class);
5029 if (class->parent && !class->parent->inited)
5030 mono_class_init (class->parent);
5032 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5034 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5035 class->nested_classes_inited = TRUE;
5038 * Computes the size used by the fields, and their locations
5040 if (has_cached_info) {
5041 class->instance_size = cached_info.instance_size;
5042 class->sizes.class_size = cached_info.class_size;
5043 class->packing_size = cached_info.packing_size;
5044 class->min_align = cached_info.min_align;
5045 class->blittable = cached_info.blittable;
5046 class->has_references = cached_info.has_references;
5047 class->has_static_refs = cached_info.has_static_refs;
5048 class->no_special_static_fields = cached_info.no_special_static_fields;
5051 if (!class->size_inited){
5052 mono_class_setup_fields (class);
5053 if (class->exception_type || mono_loader_get_last_error ())
5057 /* Initialize arrays */
5059 class->method.count = 3 + (class->rank > 1? 2: 1);
5061 if (class->interface_count) {
5062 int count_generic = generic_array_methods (class);
5063 class->method.count += class->interface_count * count_generic;
5067 mono_class_setup_supertypes (class);
5070 initialize_object_slots (class);
5073 * Initialize the rest of the data without creating a generic vtable if possible.
5074 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5075 * also avoid computing a generic vtable.
5077 if (has_cached_info) {
5079 class->vtable_size = cached_info.vtable_size;
5080 class->has_finalize = cached_info.has_finalize;
5081 class->has_finalize_inited = TRUE;
5082 class->ghcimpl = cached_info.ghcimpl;
5083 class->has_cctor = cached_info.has_cctor;
5084 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5085 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5086 * The first slot if for array with.
5088 static int szarray_vtable_size[2] = { 0 };
5090 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5093 if (!szarray_vtable_size [slot]) {
5094 mono_class_setup_vtable (class);
5095 szarray_vtable_size [slot] = class->vtable_size;
5097 class->vtable_size = szarray_vtable_size[slot];
5099 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5100 MonoClass *gklass = class->generic_class->container_class;
5102 /* Generic instance case */
5103 class->ghcimpl = gklass->ghcimpl;
5104 class->has_cctor = gklass->has_cctor;
5106 mono_class_setup_vtable (gklass);
5107 if (gklass->exception_type) {
5108 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5112 class->vtable_size = gklass->vtable_size;
5116 /* ghcimpl is not currently used
5118 if (class->parent) {
5119 MonoMethod *cmethod = class->vtable [ghc_slot];
5120 if (cmethod->is_inflated)
5121 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5122 if (cmethod == default_ghc) {
5128 /* C# doesn't allow interfaces to have cctors */
5129 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5130 MonoMethod *cmethod = NULL;
5132 if (class->type_token) {
5133 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5134 /* The find_method function ignores the 'flags' argument */
5135 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5136 class->has_cctor = 1;
5138 mono_class_setup_methods (class);
5139 if (class->exception_type)
5142 for (i = 0; i < class->method.count; ++i) {
5143 MonoMethod *method = class->methods [i];
5144 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5145 (strcmp (".cctor", method->name) == 0)) {
5146 class->has_cctor = 1;
5154 if (class->parent) {
5155 int first_iface_slot;
5156 /* This will compute class->parent->vtable_size for some classes */
5157 mono_class_init (class->parent);
5158 if (class->parent->exception_type) {
5159 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5162 if (mono_loader_get_last_error ())
5164 if (!class->parent->vtable_size) {
5165 /* FIXME: Get rid of this somehow */
5166 mono_class_setup_vtable (class->parent);
5167 if (class->parent->exception_type) {
5168 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5171 if (mono_loader_get_last_error ())
5174 first_iface_slot = class->parent->vtable_size;
5175 if (mono_class_need_stelemref_method (class))
5177 setup_interface_offsets (class, first_iface_slot, TRUE);
5179 setup_interface_offsets (class, 0, TRUE);
5182 if (mono_security_core_clr_enabled ())
5183 mono_security_core_clr_check_inheritance (class);
5185 if (mono_loader_get_last_error ()) {
5186 if (class->exception_type == MONO_EXCEPTION_NONE) {
5187 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5189 mono_loader_clear_error ();
5192 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5193 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5198 /* Because of the double-checking locking pattern */
5199 mono_memory_barrier ();
5201 class->init_pending = 0;
5203 mono_loader_unlock ();
5205 if (mono_debugger_class_init_func)
5206 mono_debugger_class_init_func (class);
5208 return class->exception_type == MONO_EXCEPTION_NONE;
5212 * mono_class_has_finalizer:
5214 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5218 mono_class_has_finalizer (MonoClass *klass)
5220 MonoClass *class = klass;
5221 gboolean has_finalize = FALSE;
5223 if (klass->has_finalize_inited)
5224 return klass->has_finalize;
5226 /* Interfaces and valuetypes are not supposed to have finalizers */
5227 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5228 MonoMethod *cmethod = NULL;
5230 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5231 } else if (class->generic_class) {
5232 MonoClass *gklass = class->generic_class->container_class;
5234 has_finalize = mono_class_has_finalizer (gklass);
5235 } else if (class->parent && class->parent->has_finalize) {
5236 has_finalize = TRUE;
5238 if (class->parent) {
5240 * Can't search in metadata for a method named Finalize, because that
5241 * ignores overrides.
5243 mono_class_setup_vtable (class);
5244 if (class->exception_type || mono_loader_get_last_error ())
5247 cmethod = class->vtable [finalize_slot];
5251 g_assert (class->vtable_size > finalize_slot);
5253 if (class->parent) {
5254 if (cmethod->is_inflated)
5255 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5256 if (cmethod != default_finalize)
5257 has_finalize = TRUE;
5263 mono_image_lock (klass->image);
5265 if (!klass->has_finalize_inited) {
5266 klass->has_finalize = has_finalize ? 1 : 0;
5268 mono_memory_barrier ();
5269 klass->has_finalize_inited = TRUE;
5272 mono_image_unlock (klass->image);
5274 return klass->has_finalize;
5278 mono_is_corlib_image (MonoImage *image)
5280 /* FIXME: allow the dynamic case for our compilers and with full trust */
5281 if (image_is_dynamic (image))
5282 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5284 return image == mono_defaults.corlib;
5288 * LOCKING: this assumes the loader lock is held
5291 mono_class_setup_mono_type (MonoClass *class)
5293 const char *name = class->name;
5294 const char *nspace = class->name_space;
5295 gboolean is_corlib = mono_is_corlib_image (class->image);
5297 class->this_arg.byref = 1;
5298 class->this_arg.data.klass = class;
5299 class->this_arg.type = MONO_TYPE_CLASS;
5300 class->byval_arg.data.klass = class;
5301 class->byval_arg.type = MONO_TYPE_CLASS;
5303 if (is_corlib && !strcmp (nspace, "System")) {
5304 if (!strcmp (name, "ValueType")) {
5306 * do not set the valuetype bit for System.ValueType.
5307 * class->valuetype = 1;
5309 class->blittable = TRUE;
5310 } else if (!strcmp (name, "Enum")) {
5312 * do not set the valuetype bit for System.Enum.
5313 * class->valuetype = 1;
5315 class->valuetype = 0;
5316 class->enumtype = 0;
5317 } else if (!strcmp (name, "Object")) {
5318 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5319 } else if (!strcmp (name, "String")) {
5320 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5321 } else if (!strcmp (name, "TypedReference")) {
5322 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5326 if (class->valuetype) {
5327 int t = MONO_TYPE_VALUETYPE;
5329 if (is_corlib && !strcmp (nspace, "System")) {
5332 if (!strcmp (name, "Boolean")) {
5333 t = MONO_TYPE_BOOLEAN;
5334 } else if (!strcmp(name, "Byte")) {
5336 class->blittable = TRUE;
5340 if (!strcmp (name, "Char")) {
5345 if (!strcmp (name, "Double")) {
5347 class->blittable = TRUE;
5351 if (!strcmp (name, "Int32")) {
5353 class->blittable = TRUE;
5354 } else if (!strcmp(name, "Int16")) {
5356 class->blittable = TRUE;
5357 } else if (!strcmp(name, "Int64")) {
5359 class->blittable = TRUE;
5360 } else if (!strcmp(name, "IntPtr")) {
5362 class->blittable = TRUE;
5366 if (!strcmp (name, "Single")) {
5368 class->blittable = TRUE;
5369 } else if (!strcmp(name, "SByte")) {
5371 class->blittable = TRUE;
5375 if (!strcmp (name, "UInt32")) {
5377 class->blittable = TRUE;
5378 } else if (!strcmp(name, "UInt16")) {
5380 class->blittable = TRUE;
5381 } else if (!strcmp(name, "UInt64")) {
5383 class->blittable = TRUE;
5384 } else if (!strcmp(name, "UIntPtr")) {
5386 class->blittable = TRUE;
5390 if (!strcmp (name, "TypedReference")) {
5391 t = MONO_TYPE_TYPEDBYREF;
5392 class->blittable = TRUE;
5396 if (!strcmp (name, "Void")) {
5404 class->this_arg.type = class->byval_arg.type = t;
5407 if (MONO_CLASS_IS_INTERFACE (class))
5408 class->interface_id = mono_get_unique_iid (class);
5414 * COM initialization is delayed until needed.
5415 * However when a [ComImport] attribute is present on a type it will trigger
5416 * the initialization. This is not a problem unless the BCL being executed
5417 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5420 init_com_from_comimport (MonoClass *class)
5422 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5423 if (mono_security_core_clr_enabled ()) {
5424 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5425 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5426 /* but it can not be made available for application (i.e. user code) since all COM calls
5427 * are considered native calls. In this case we fail with a TypeLoadException (just like
5428 * Silverlight 2 does */
5429 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5434 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5436 #endif /*DISABLE_COM*/
5439 * LOCKING: this assumes the loader lock is held
5442 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5444 gboolean system_namespace;
5445 gboolean is_corlib = mono_is_corlib_image (class->image);
5447 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5449 /* if root of the hierarchy */
5450 if (system_namespace && !strcmp (class->name, "Object")) {
5451 class->parent = NULL;
5452 class->instance_size = sizeof (MonoObject);
5455 if (!strcmp (class->name, "<Module>")) {
5456 class->parent = NULL;
5457 class->instance_size = 0;
5461 if (!MONO_CLASS_IS_INTERFACE (class)) {
5462 /* Imported COM Objects always derive from __ComObject. */
5464 if (MONO_CLASS_IS_IMPORT (class)) {
5465 init_com_from_comimport (class);
5466 if (parent == mono_defaults.object_class)
5467 parent = mono_class_get_com_object_class ();
5471 /* set the parent to something useful and safe, but mark the type as broken */
5472 parent = mono_defaults.object_class;
5473 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5476 class->parent = parent;
5478 if (parent->generic_class && !parent->name) {
5480 * If the parent is a generic instance, we may get
5481 * called before it is fully initialized, especially
5482 * before it has its name.
5487 #ifndef DISABLE_REMOTING
5488 class->marshalbyref = parent->marshalbyref;
5489 class->contextbound = parent->contextbound;
5492 class->delegate = parent->delegate;
5494 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5495 mono_class_set_is_com_object (class);
5497 if (system_namespace) {
5498 #ifndef DISABLE_REMOTING
5499 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5500 class->marshalbyref = 1;
5502 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5503 class->contextbound = 1;
5505 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5506 class->delegate = 1;
5509 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5510 (strcmp (class->parent->name_space, "System") == 0)))
5511 class->valuetype = 1;
5512 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5513 class->valuetype = class->enumtype = 1;
5515 /*class->enumtype = class->parent->enumtype; */
5517 /* initialize com types if COM interfaces are present */
5519 if (MONO_CLASS_IS_IMPORT (class))
5520 init_com_from_comimport (class);
5522 class->parent = NULL;
5528 * mono_class_setup_supertypes:
5531 * Build the data structure needed to make fast type checks work.
5532 * This currently sets two fields in @class:
5533 * - idepth: distance between @class and System.Object in the type
5535 * - supertypes: array of classes: each element has a class in the hierarchy
5536 * starting from @class up to System.Object
5538 * LOCKING: This function is atomic, in case of contention we waste memory.
5541 mono_class_setup_supertypes (MonoClass *class)
5544 MonoClass **supertypes;
5546 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5550 if (class->parent && !class->parent->supertypes)
5551 mono_class_setup_supertypes (class->parent);
5553 class->idepth = class->parent->idepth + 1;
5557 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5558 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5560 if (class->parent) {
5561 supertypes [class->idepth - 1] = class;
5562 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5564 supertypes [0] = class;
5567 mono_atomic_store_release (&class->supertypes, supertypes);
5571 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5573 MonoClass *gtd = (MonoClass*)user_data;
5574 /* Only try to fix generic instances of @gtd */
5575 if (gclass->generic_class->container_class != gtd)
5578 /* Check if the generic instance has no parent. */
5579 if (gtd->parent && !gclass->parent)
5580 mono_generic_class_setup_parent (gclass, gtd);
5586 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5588 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5589 mono_error_set_type_load_class (error, class, msg);
5593 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5595 MonoLoaderError *lerror = mono_loader_get_last_error ();
5598 set_failure_from_loader_error (class, lerror);
5599 mono_error_set_from_loader_error (error);
5603 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5604 mono_error_set_type_load_class (error, class, msg);
5609 * mono_class_create_from_typedef:
5610 * @image: image where the token is valid
5611 * @type_token: typedef token
5612 * @error: used to return any error found while creating the type
5614 * Create the MonoClass* representing the specified type token.
5615 * @type_token must be a TypeDef token.
5617 * FIXME: don't return NULL on failure, just the the caller figure it out.
5620 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5622 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5623 MonoClass *class, *parent = NULL;
5624 guint32 cols [MONO_TYPEDEF_SIZE];
5625 guint32 cols_next [MONO_TYPEDEF_SIZE];
5626 guint tidx = mono_metadata_token_index (type_token);
5627 MonoGenericContext *context = NULL;
5628 const char *name, *nspace;
5630 MonoClass **interfaces;
5631 guint32 field_last, method_last;
5632 guint32 nesting_tokeen;
5634 mono_error_init (error);
5636 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5637 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5638 g_assert (!mono_loader_get_last_error ());
5642 mono_loader_lock ();
5644 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5645 mono_loader_unlock ();
5646 g_assert (!mono_loader_get_last_error ());
5650 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5652 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5653 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5655 class = mono_image_alloc0 (image, sizeof (MonoClass));
5658 class->name_space = nspace;
5660 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5662 class->image = image;
5663 class->type_token = type_token;
5664 class->flags = cols [MONO_TYPEDEF_FLAGS];
5666 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5668 classes_size += sizeof (MonoClass);
5671 * Check whether we're a generic type definition.
5673 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5674 if (class->generic_container) {
5675 class->is_generic = 1;
5676 class->generic_container->owner.klass = class;
5677 context = &class->generic_container->context;
5680 if (class->generic_container)
5681 enable_gclass_recording ();
5683 if (cols [MONO_TYPEDEF_EXTENDS]) {
5685 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5687 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5688 /*WARNING: this must satisfy mono_metadata_type_hash*/
5689 class->this_arg.byref = 1;
5690 class->this_arg.data.klass = class;
5691 class->this_arg.type = MONO_TYPE_CLASS;
5692 class->byval_arg.data.klass = class;
5693 class->byval_arg.type = MONO_TYPE_CLASS;
5695 parent = mono_class_get_checked (image, parent_token, error);
5696 if (parent && context) /* Always inflate */
5697 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5699 if (parent == NULL) {
5700 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5701 goto parent_failure;
5704 for (tmp = parent; tmp; tmp = tmp->parent) {
5706 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5707 goto parent_failure;
5709 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5710 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5711 goto parent_failure;
5716 mono_class_setup_parent (class, parent);
5718 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5719 mono_class_setup_mono_type (class);
5721 if (class->generic_container)
5722 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5725 * This might access class->byval_arg for recursion generated by generic constraints,
5726 * so it has to come after setup_mono_type ().
5728 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5729 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5730 if (!mono_error_ok (error)) {
5731 /*FIXME implement a mono_class_set_failure_from_mono_error */
5732 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5733 mono_loader_unlock ();
5734 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5735 g_assert (!mono_loader_get_last_error ());
5740 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5744 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5748 class->cast_class = class->element_class = class;
5750 if (!class->enumtype) {
5751 if (!mono_metadata_interfaces_from_typedef_full (
5752 image, type_token, &interfaces, &icount, FALSE, context)){
5753 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5754 mono_loader_unlock ();
5755 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5759 class->interfaces = interfaces;
5760 class->interface_count = icount;
5761 class->interfaces_inited = 1;
5764 /*g_print ("Load class %s\n", name);*/
5767 * Compute the field and method lists
5769 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5770 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5772 if (tt->rows > tidx){
5773 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5774 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5775 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5777 field_last = image->tables [MONO_TABLE_FIELD].rows;
5778 method_last = image->tables [MONO_TABLE_METHOD].rows;
5781 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5782 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5783 class->field.count = field_last - class->field.first;
5785 class->field.count = 0;
5787 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5788 class->method.count = method_last - class->method.first;
5790 class->method.count = 0;
5792 /* reserve space to store vector pointer in arrays */
5793 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5794 class->instance_size += 2 * sizeof (gpointer);
5795 g_assert (class->field.count == 0);
5798 if (class->enumtype) {
5799 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5800 if (!enum_basetype) {
5801 /*set it to a default value as the whole runtime can't handle this to be null*/
5802 class->cast_class = class->element_class = mono_defaults.int32_class;
5803 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5804 mono_loader_unlock ();
5805 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5806 g_assert (!mono_loader_get_last_error ());
5809 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5813 * If we're a generic type definition, load the constraints.
5814 * We must do this after the class has been constructed to make certain recursive scenarios
5817 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5818 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5819 mono_loader_unlock ();
5820 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5821 g_assert (!mono_loader_get_last_error ());
5825 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5826 if (!strncmp (name, "Vector", 6))
5827 class->simd_type = !strcmp (name + 6, "2d") || !strcmp (name + 6, "2ul") || !strcmp (name + 6, "2l") || !strcmp (name + 6, "4f") || !strcmp (name + 6, "4ui") || !strcmp (name + 6, "4i") || !strcmp (name + 6, "8s") || !strcmp (name + 6, "8us") || !strcmp (name + 6, "16b") || !strcmp (name + 6, "16sb");
5830 mono_loader_unlock ();
5832 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5833 g_assert (!mono_loader_get_last_error ());
5838 mono_class_setup_mono_type (class);
5839 mono_loader_unlock ();
5840 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5841 g_assert (!mono_loader_get_last_error ());
5845 /** is klass Nullable<T>? */
5847 mono_class_is_nullable (MonoClass *klass)
5849 return klass->generic_class != NULL &&
5850 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5854 /** if klass is T? return T */
5856 mono_class_get_nullable_param (MonoClass *klass)
5858 g_assert (mono_class_is_nullable (klass));
5859 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5863 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5867 MonoGenericClass *gclass = klass->generic_class;
5869 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5870 if (!mono_error_ok (&error)) {
5871 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5872 klass->parent = mono_defaults.object_class;
5873 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5874 mono_error_cleanup (&error);
5878 mono_class_setup_parent (klass, klass->parent);
5880 if (klass->enumtype) {
5881 klass->cast_class = gtd->cast_class;
5882 klass->element_class = gtd->element_class;
5888 * Create the `MonoClass' for an instantiation of a generic type.
5889 * We only do this if we actually need it.
5892 mono_generic_class_get_class (MonoGenericClass *gclass)
5894 MonoClass *klass, *gklass;
5896 if (gclass->cached_class)
5897 return gclass->cached_class;
5899 mono_loader_lock ();
5900 if (gclass->cached_class) {
5901 mono_loader_unlock ();
5902 return gclass->cached_class;
5905 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5907 gklass = gclass->container_class;
5909 if (record_gclass_instantiation > 0)
5910 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5912 if (gklass->nested_in) {
5913 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5914 klass->nested_in = gklass->nested_in;
5917 klass->name = gklass->name;
5918 klass->name_space = gklass->name_space;
5920 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5922 klass->image = gklass->image;
5923 klass->flags = gklass->flags;
5924 klass->type_token = gklass->type_token;
5925 klass->field.count = gklass->field.count;
5927 klass->is_inflated = 1;
5928 klass->generic_class = gclass;
5930 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5931 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5932 klass->this_arg.byref = TRUE;
5933 klass->enumtype = gklass->enumtype;
5934 klass->valuetype = gklass->valuetype;
5936 klass->cast_class = klass->element_class = klass;
5938 if (mono_class_is_nullable (klass))
5939 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5942 * We're not interested in the nested classes of a generic instance.
5943 * We use the generic type definition to look for nested classes.
5946 mono_generic_class_setup_parent (klass, gklass);
5948 if (gclass->is_dynamic) {
5951 mono_class_setup_supertypes (klass);
5953 if (klass->enumtype) {
5955 * For enums, gklass->fields might not been set, but instance_size etc. is
5956 * already set in mono_reflection_create_internal_class (). For non-enums,
5957 * these will be computed normally in mono_class_layout_fields ().
5959 klass->instance_size = gklass->instance_size;
5960 klass->sizes.class_size = gklass->sizes.class_size;
5961 mono_memory_barrier ();
5962 klass->size_inited = 1;
5966 mono_memory_barrier ();
5967 gclass->cached_class = klass;
5969 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5971 inflated_classes ++;
5972 inflated_classes_size += sizeof (MonoClass);
5974 mono_loader_unlock ();
5980 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5982 MonoClass *klass, **ptr;
5984 MonoGenericContainer *container = mono_generic_param_owner (param);
5988 image = mono_defaults.corlib;
5990 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5991 classes_size += sizeof (MonoClass);
5994 klass->name = pinfo->name;
5996 int n = mono_generic_param_num (param);
5997 klass->name = mono_image_alloc0 (image, 16);
5998 sprintf ((char*)klass->name, "%d", n);
6003 MonoMethod *omethod = container->owner.method;
6004 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6006 MonoClass *oklass = container->owner.klass;
6007 klass->name_space = oklass ? oklass->name_space : "";
6010 klass->name_space = "";
6013 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6017 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6021 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6022 klass->parent = pinfo->constraints [0];
6024 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6025 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6027 klass->parent = mono_defaults.object_class;
6030 if (count - pos > 0) {
6031 klass->interface_count = count - pos;
6032 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6033 klass->interfaces_inited = TRUE;
6034 for (i = pos; i < count; i++)
6035 klass->interfaces [i - pos] = pinfo->constraints [i];
6038 klass->image = image;
6040 klass->inited = TRUE;
6041 klass->cast_class = klass->element_class = klass;
6042 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6044 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6045 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6046 klass->this_arg.byref = TRUE;
6048 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6049 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6051 /*Init these fields to sane values*/
6052 klass->min_align = 1;
6053 klass->instance_size = sizeof (gpointer);
6054 mono_memory_barrier ();
6055 klass->size_inited = 1;
6057 mono_class_setup_supertypes (klass);
6059 if (count - pos > 0) {
6060 mono_class_setup_vtable (klass->parent);
6061 if (klass->parent->exception_type)
6062 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6064 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6070 #define FAST_CACHE_SIZE 16
6073 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6075 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6076 MonoImage *image = param->image;
6081 if (n < FAST_CACHE_SIZE) {
6083 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6085 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6087 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6088 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6093 * LOCKING: Acquires the loader lock.
6096 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6098 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6099 MonoImage *image = param->image;
6104 if (n < FAST_CACHE_SIZE) {
6106 /* No locking needed */
6107 if (!image->mvar_cache_fast)
6108 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6109 image->mvar_cache_fast [n] = klass;
6111 if (!image->var_cache_fast)
6112 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6113 image->var_cache_fast [n] = klass;
6117 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6119 mono_image_lock (image);
6120 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6122 ht = g_hash_table_new (NULL, NULL);
6123 mono_memory_barrier ();
6125 image->mvar_cache_slow = ht;
6127 image->var_cache_slow = ht;
6129 mono_image_unlock (image);
6132 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6136 * LOCKING: Acquires the loader lock.
6139 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6141 MonoGenericContainer *container = mono_generic_param_owner (param);
6142 MonoGenericParamInfo *pinfo;
6145 mono_loader_lock ();
6148 pinfo = mono_generic_param_info (param);
6149 if (pinfo->pklass) {
6150 mono_loader_unlock ();
6151 return pinfo->pklass;
6157 klass = get_anon_gparam_class (param, is_mvar);
6159 mono_loader_unlock ();
6164 if (!image && container) {
6166 MonoMethod *method = container->owner.method;
6167 image = (method && method->klass) ? method->klass->image : NULL;
6169 MonoClass *klass = container->owner.klass;
6170 // FIXME: 'klass' should not be null
6171 // But, monodis creates GenericContainers without associating a owner to it
6172 image = klass ? klass->image : NULL;
6176 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6178 mono_memory_barrier ();
6181 pinfo->pklass = klass;
6183 set_anon_gparam_class (param, is_mvar, klass);
6185 mono_loader_unlock ();
6187 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6188 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6194 mono_ptr_class_get (MonoType *type)
6197 MonoClass *el_class;
6201 el_class = mono_class_from_mono_type (type);
6202 image = el_class->image;
6204 mono_loader_lock ();
6206 if (!image->ptr_cache)
6207 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6209 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6210 mono_loader_unlock ();
6213 result = mono_image_alloc0 (image, sizeof (MonoClass));
6215 classes_size += sizeof (MonoClass);
6217 result->parent = NULL; /* no parent for PTR types */
6218 result->name_space = el_class->name_space;
6219 name = g_strdup_printf ("%s*", el_class->name);
6220 result->name = mono_image_strdup (image, name);
6223 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6225 result->image = el_class->image;
6226 result->inited = TRUE;
6227 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6228 /* Can pointers get boxed? */
6229 result->instance_size = sizeof (gpointer);
6230 result->cast_class = result->element_class = el_class;
6231 result->blittable = TRUE;
6233 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6234 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6235 result->this_arg.byref = TRUE;
6237 mono_class_setup_supertypes (result);
6239 g_hash_table_insert (image->ptr_cache, el_class, result);
6241 mono_loader_unlock ();
6243 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6249 mono_fnptr_class_get (MonoMethodSignature *sig)
6252 static GHashTable *ptr_hash = NULL;
6254 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6256 mono_loader_lock ();
6259 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6261 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6262 mono_loader_unlock ();
6265 result = g_new0 (MonoClass, 1);
6267 result->parent = NULL; /* no parent for PTR types */
6268 result->name_space = "System";
6269 result->name = "MonoFNPtrFakeClass";
6271 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6273 result->image = mono_defaults.corlib; /* need to fix... */
6274 result->inited = TRUE;
6275 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6276 /* Can pointers get boxed? */
6277 result->instance_size = sizeof (gpointer);
6278 result->cast_class = result->element_class = result;
6279 result->blittable = TRUE;
6281 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6282 result->this_arg.data.method = result->byval_arg.data.method = sig;
6283 result->this_arg.byref = TRUE;
6284 result->blittable = TRUE;
6286 mono_class_setup_supertypes (result);
6288 g_hash_table_insert (ptr_hash, sig, result);
6290 mono_loader_unlock ();
6292 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6298 mono_class_from_mono_type (MonoType *type)
6300 switch (type->type) {
6301 case MONO_TYPE_OBJECT:
6302 return type->data.klass? type->data.klass: mono_defaults.object_class;
6303 case MONO_TYPE_VOID:
6304 return type->data.klass? type->data.klass: mono_defaults.void_class;
6305 case MONO_TYPE_BOOLEAN:
6306 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6307 case MONO_TYPE_CHAR:
6308 return type->data.klass? type->data.klass: mono_defaults.char_class;
6310 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6312 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6314 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6316 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6318 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6320 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6322 return type->data.klass? type->data.klass: mono_defaults.int_class;
6324 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6326 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6328 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6330 return type->data.klass? type->data.klass: mono_defaults.single_class;
6332 return type->data.klass? type->data.klass: mono_defaults.double_class;
6333 case MONO_TYPE_STRING:
6334 return type->data.klass? type->data.klass: mono_defaults.string_class;
6335 case MONO_TYPE_TYPEDBYREF:
6336 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6337 case MONO_TYPE_ARRAY:
6338 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6340 return mono_ptr_class_get (type->data.type);
6341 case MONO_TYPE_FNPTR:
6342 return mono_fnptr_class_get (type->data.method);
6343 case MONO_TYPE_SZARRAY:
6344 return mono_array_class_get (type->data.klass, 1);
6345 case MONO_TYPE_CLASS:
6346 case MONO_TYPE_VALUETYPE:
6347 return type->data.klass;
6348 case MONO_TYPE_GENERICINST:
6349 return mono_generic_class_get_class (type->data.generic_class);
6351 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6352 case MONO_TYPE_MVAR:
6353 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6355 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6356 g_assert_not_reached ();
6363 * mono_type_retrieve_from_typespec
6364 * @image: context where the image is created
6365 * @type_spec: typespec token
6366 * @context: the generic context used to evaluate generic instantiations in
6369 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6371 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6373 *did_inflate = FALSE;
6378 if (context && (context->class_inst || context->method_inst)) {
6379 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6381 if (!mono_error_ok (error)) {
6382 g_assert (!mono_loader_get_last_error ());
6388 *did_inflate = TRUE;
6395 * mono_class_create_from_typespec
6396 * @image: context where the image is created
6397 * @type_spec: typespec token
6398 * @context: the generic context used to evaluate generic instantiations in
6401 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6404 gboolean inflated = FALSE;
6405 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6406 if (!mono_error_ok (error))
6408 ret = mono_class_from_mono_type (t);
6410 mono_metadata_free_type (t);
6415 * mono_bounded_array_class_get:
6416 * @element_class: element class
6417 * @rank: the dimension of the array class
6418 * @bounded: whenever the array has non-zero bounds
6420 * Returns: a class object describing the array with element type @element_type and
6424 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6428 MonoClass *parent = NULL;
6429 GSList *list, *rootlist = NULL;
6432 gboolean corlib_type = FALSE;
6434 g_assert (rank <= 255);
6437 /* bounded only matters for one-dimensional arrays */
6440 image = eclass->image;
6442 if (rank == 1 && !bounded) {
6444 * This case is very frequent not just during compilation because of calls
6445 * from mono_class_from_mono_type (), mono_array_new (),
6446 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6448 mono_mutex_lock (&image->szarray_cache_lock);
6449 if (!image->szarray_cache)
6450 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6451 class = g_hash_table_lookup (image->szarray_cache, eclass);
6452 mono_mutex_unlock (&image->szarray_cache_lock);
6456 mono_loader_lock ();
6458 mono_loader_lock ();
6460 if (!image->array_cache)
6461 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6463 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6464 for (; list; list = list->next) {
6466 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6467 mono_loader_unlock ();
6474 /* for the building corlib use System.Array from it */
6475 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6476 parent = mono_class_from_name (image, "System", "Array");
6479 parent = mono_defaults.array_class;
6480 if (!parent->inited)
6481 mono_class_init (parent);
6484 class = mono_image_alloc0 (image, sizeof (MonoClass));
6486 class->image = image;
6487 class->name_space = eclass->name_space;
6488 nsize = strlen (eclass->name);
6489 name = g_malloc (nsize + 2 + rank + 1);
6490 memcpy (name, eclass->name, nsize);
6493 memset (name + nsize + 1, ',', rank - 1);
6495 name [nsize + rank] = '*';
6496 name [nsize + rank + bounded] = ']';
6497 name [nsize + rank + bounded + 1] = 0;
6498 class->name = mono_image_strdup (image, name);
6501 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6503 classes_size += sizeof (MonoClass);
6505 class->type_token = 0;
6506 /* all arrays are marked serializable and sealed, bug #42779 */
6507 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6508 class->parent = parent;
6509 class->instance_size = mono_class_instance_size (class->parent);
6511 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6512 /*Arrays of those two types are invalid.*/
6513 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6514 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6515 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6516 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6517 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6519 /* element_size -1 is ok as this is not an instantitable type*/
6520 class->sizes.element_size = -1;
6522 class->sizes.element_size = mono_class_array_element_size (eclass);
6524 mono_class_setup_supertypes (class);
6526 if (eclass->generic_class)
6527 mono_class_init (eclass);
6528 if (!eclass->size_inited)
6529 mono_class_setup_fields (eclass);
6530 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6531 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6533 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6537 if (eclass->enumtype)
6538 class->cast_class = eclass->element_class;
6540 class->cast_class = eclass;
6542 switch (class->cast_class->byval_arg.type) {
6544 class->cast_class = mono_defaults.byte_class;
6547 class->cast_class = mono_defaults.int16_class;
6550 #if SIZEOF_VOID_P == 4
6554 class->cast_class = mono_defaults.int32_class;
6557 #if SIZEOF_VOID_P == 8
6561 class->cast_class = mono_defaults.int64_class;
6565 class->element_class = eclass;
6567 if ((rank > 1) || bounded) {
6568 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6569 class->byval_arg.type = MONO_TYPE_ARRAY;
6570 class->byval_arg.data.array = at;
6571 at->eklass = eclass;
6573 /* FIXME: complete.... */
6575 class->byval_arg.type = MONO_TYPE_SZARRAY;
6576 class->byval_arg.data.klass = eclass;
6578 class->this_arg = class->byval_arg;
6579 class->this_arg.byref = 1;
6584 class->generic_container = eclass->generic_container;
6586 if (rank == 1 && !bounded) {
6587 MonoClass *prev_class;
6589 mono_mutex_lock (&image->szarray_cache_lock);
6590 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6592 /* Someone got in before us */
6595 g_hash_table_insert (image->szarray_cache, eclass, class);
6596 mono_mutex_unlock (&image->szarray_cache_lock);
6598 list = g_slist_append (rootlist, class);
6599 g_hash_table_insert (image->array_cache, eclass, list);
6602 mono_loader_unlock ();
6604 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6610 * mono_array_class_get:
6611 * @element_class: element class
6612 * @rank: the dimension of the array class
6614 * Returns: a class object describing the array with element type @element_type and
6618 mono_array_class_get (MonoClass *eclass, guint32 rank)
6620 return mono_bounded_array_class_get (eclass, rank, FALSE);
6624 * mono_class_instance_size:
6627 * Returns: the size of an object instance
6630 mono_class_instance_size (MonoClass *klass)
6632 if (!klass->size_inited)
6633 mono_class_init (klass);
6635 return klass->instance_size;
6639 * mono_class_min_align:
6642 * Returns: minimm alignment requirements
6645 mono_class_min_align (MonoClass *klass)
6647 if (!klass->size_inited)
6648 mono_class_init (klass);
6650 return klass->min_align;
6654 * mono_class_value_size:
6657 * This function is used for value types, and return the
6658 * space and the alignment to store that kind of value object.
6660 * Returns: the size of a value of kind @klass
6663 mono_class_value_size (MonoClass *klass, guint32 *align)
6667 /* fixme: check disable, because we still have external revereces to
6668 * mscorlib and Dummy Objects
6670 /*g_assert (klass->valuetype);*/
6672 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6675 *align = klass->min_align;
6681 * mono_class_data_size:
6684 * Returns: the size of the static class data
6687 mono_class_data_size (MonoClass *klass)
6690 mono_class_init (klass);
6691 /* This can happen with dynamically created types */
6692 if (!klass->fields_inited)
6693 mono_class_setup_fields_locking (klass);
6695 /* in arrays, sizes.class_size is unioned with element_size
6696 * and arrays have no static fields
6700 return klass->sizes.class_size;
6704 * Auxiliary routine to mono_class_get_field
6706 * Takes a field index instead of a field token.
6708 static MonoClassField *
6709 mono_class_get_field_idx (MonoClass *class, int idx)
6711 mono_class_setup_fields_locking (class);
6712 if (class->exception_type)
6716 if (class->image->uncompressed_metadata) {
6718 * class->field.first points to the FieldPtr table, while idx points into the
6719 * Field table, so we have to do a search.
6721 /*FIXME this is broken for types with multiple fields with the same name.*/
6722 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6725 for (i = 0; i < class->field.count; ++i)
6726 if (mono_field_get_name (&class->fields [i]) == name)
6727 return &class->fields [i];
6728 g_assert_not_reached ();
6730 if (class->field.count) {
6731 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6732 return &class->fields [idx - class->field.first];
6736 class = class->parent;
6742 * mono_class_get_field:
6743 * @class: the class to lookup the field.
6744 * @field_token: the field token
6746 * Returns: A MonoClassField representing the type and offset of
6747 * the field, or a NULL value if the field does not belong to this
6751 mono_class_get_field (MonoClass *class, guint32 field_token)
6753 int idx = mono_metadata_token_index (field_token);
6755 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6757 return mono_class_get_field_idx (class, idx - 1);
6761 * mono_class_get_field_from_name:
6762 * @klass: the class to lookup the field.
6763 * @name: the field name
6765 * Search the class @klass and it's parents for a field with the name @name.
6767 * Returns: the MonoClassField pointer of the named field or NULL
6770 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6772 return mono_class_get_field_from_name_full (klass, name, NULL);
6776 * mono_class_get_field_from_name_full:
6777 * @klass: the class to lookup the field.
6778 * @name: the field name
6779 * @type: the type of the fields. This optional.
6781 * Search the class @klass and it's parents for a field with the name @name and type @type.
6783 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6784 * of its generic type definition.
6786 * Returns: the MonoClassField pointer of the named field or NULL
6789 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6793 mono_class_setup_fields_locking (klass);
6794 if (klass->exception_type)
6798 for (i = 0; i < klass->field.count; ++i) {
6799 MonoClassField *field = &klass->fields [i];
6801 if (strcmp (name, mono_field_get_name (field)) != 0)
6805 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6806 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6811 klass = klass->parent;
6817 * mono_class_get_field_token:
6818 * @field: the field we need the token of
6820 * Get the token of a field. Note that the tokesn is only valid for the image
6821 * the field was loaded from. Don't use this function for fields in dynamic types.
6823 * Returns: the token representing the field in the image it was loaded from.
6826 mono_class_get_field_token (MonoClassField *field)
6828 MonoClass *klass = field->parent;
6831 mono_class_setup_fields_locking (klass);
6836 for (i = 0; i < klass->field.count; ++i) {
6837 if (&klass->fields [i] == field) {
6838 int idx = klass->field.first + i + 1;
6840 if (klass->image->uncompressed_metadata)
6841 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6842 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6845 klass = klass->parent;
6848 g_assert_not_reached ();
6853 mono_field_get_index (MonoClassField *field)
6855 int index = field - field->parent->fields;
6857 g_assert (index >= 0 && index < field->parent->field.count);
6863 * mono_class_get_field_default_value:
6865 * Return the default value of the field as a pointer into the metadata blob.
6868 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6871 guint32 constant_cols [MONO_CONSTANT_SIZE];
6873 MonoClass *klass = field->parent;
6875 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6877 if (!klass->ext || !klass->ext->field_def_values) {
6878 MonoFieldDefaultValue *def_values;
6880 mono_class_alloc_ext (klass);
6882 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6884 mono_image_lock (klass->image);
6885 mono_memory_barrier ();
6886 if (!klass->ext->field_def_values)
6887 klass->ext->field_def_values = def_values;
6888 mono_image_unlock (klass->image);
6891 field_index = mono_field_get_index (field);
6893 if (!klass->ext->field_def_values [field_index].data) {
6894 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6898 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6900 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6901 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6902 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6905 *def_type = klass->ext->field_def_values [field_index].def_type;
6906 return klass->ext->field_def_values [field_index].data;
6910 mono_property_get_index (MonoProperty *prop)
6912 int index = prop - prop->parent->ext->properties;
6914 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6920 * mono_class_get_property_default_value:
6922 * Return the default value of the field as a pointer into the metadata blob.
6925 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6928 guint32 constant_cols [MONO_CONSTANT_SIZE];
6929 MonoClass *klass = property->parent;
6931 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6933 * We don't cache here because it is not used by C# so it's quite rare, but
6934 * we still do the lookup in klass->ext because that is where the data
6935 * is stored for dynamic assemblies.
6938 if (image_is_dynamic (klass->image)) {
6939 int prop_index = mono_property_get_index (property);
6940 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6941 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6942 return klass->ext->prop_def_values [prop_index].data;
6946 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6950 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6951 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6952 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6956 mono_class_get_event_token (MonoEvent *event)
6958 MonoClass *klass = event->parent;
6963 for (i = 0; i < klass->ext->event.count; ++i) {
6964 if (&klass->ext->events [i] == event)
6965 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6968 klass = klass->parent;
6971 g_assert_not_reached ();
6976 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6980 gpointer iter = NULL;
6981 while ((p = mono_class_get_properties (klass, &iter))) {
6982 if (! strcmp (name, p->name))
6985 klass = klass->parent;
6991 mono_class_get_property_token (MonoProperty *prop)
6993 MonoClass *klass = prop->parent;
6997 gpointer iter = NULL;
6998 while ((p = mono_class_get_properties (klass, &iter))) {
6999 if (&klass->ext->properties [i] == prop)
7000 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7004 klass = klass->parent;
7007 g_assert_not_reached ();
7012 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7014 const char *name, *nspace;
7015 if (image_is_dynamic (image))
7016 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7018 switch (type_token & 0xff000000){
7019 case MONO_TOKEN_TYPE_DEF: {
7020 guint32 cols [MONO_TYPEDEF_SIZE];
7021 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7022 guint tidx = mono_metadata_token_index (type_token);
7024 if (tidx > tt->rows)
7025 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7027 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7028 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7029 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7030 if (strlen (nspace) == 0)
7031 return g_strdup_printf ("%s", name);
7033 return g_strdup_printf ("%s.%s", nspace, name);
7036 case MONO_TOKEN_TYPE_REF: {
7038 guint32 cols [MONO_TYPEREF_SIZE];
7039 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7040 guint tidx = mono_metadata_token_index (type_token);
7043 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7045 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7046 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7047 mono_error_cleanup (&error);
7051 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7052 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7053 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7054 if (strlen (nspace) == 0)
7055 return g_strdup_printf ("%s", name);
7057 return g_strdup_printf ("%s.%s", nspace, name);
7060 case MONO_TOKEN_TYPE_SPEC:
7061 return g_strdup_printf ("Typespec 0x%08x", type_token);
7063 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7068 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7070 if (image_is_dynamic (image))
7071 return g_strdup_printf ("DynamicAssembly %s", image->name);
7073 switch (type_token & 0xff000000){
7074 case MONO_TOKEN_TYPE_DEF:
7075 if (image->assembly)
7076 return mono_stringify_assembly_name (&image->assembly->aname);
7077 else if (image->assembly_name)
7078 return g_strdup (image->assembly_name);
7079 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7080 case MONO_TOKEN_TYPE_REF: {
7082 MonoAssemblyName aname;
7083 guint32 cols [MONO_TYPEREF_SIZE];
7084 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7085 guint32 idx = mono_metadata_token_index (type_token);
7088 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7090 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7091 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7092 mono_error_cleanup (&error);
7095 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7097 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7098 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7099 case MONO_RESOLUTION_SCOPE_MODULE:
7101 return g_strdup ("");
7102 case MONO_RESOLUTION_SCOPE_MODULEREF:
7104 return g_strdup ("");
7105 case MONO_RESOLUTION_SCOPE_TYPEREF:
7107 return g_strdup ("");
7108 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7109 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7110 return mono_stringify_assembly_name (&aname);
7112 g_assert_not_reached ();
7116 case MONO_TOKEN_TYPE_SPEC:
7118 return g_strdup ("");
7120 g_assert_not_reached ();
7127 * mono_class_get_full:
7128 * @image: the image where the class resides
7129 * @type_token: the token for the class
7130 * @context: the generic context used to evaluate generic instantiations in
7131 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7133 * Returns: the MonoClass that represents @type_token in @image
7136 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7140 class = mono_class_get_checked (image, type_token, &error);
7142 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7143 class = mono_class_inflate_generic_class_checked (class, context, &error);
7146 mono_loader_set_error_from_mono_error (&error);
7147 mono_error_cleanup (&error); /*FIXME don't swallow this error */
7154 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7158 mono_error_init (error);
7159 class = mono_class_get_checked (image, type_token, error);
7161 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7162 class = mono_class_inflate_generic_class_checked (class, context, error);
7167 * mono_class_get_checked:
7168 * @image: the image where the class resides
7169 * @type_token: the token for the class
7170 * @error: error object to return any error
7172 * Returns: the MonoClass that represents @type_token in @image
7175 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7177 MonoClass *class = NULL;
7179 mono_error_init (error);
7181 if (image_is_dynamic (image)) {
7182 int table = mono_metadata_token_table (type_token);
7184 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7185 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7188 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7192 switch (type_token & 0xff000000){
7193 case MONO_TOKEN_TYPE_DEF:
7194 class = mono_class_create_from_typedef (image, type_token, error);
7196 case MONO_TOKEN_TYPE_REF:
7197 class = mono_class_from_typeref_checked (image, type_token, error);
7199 case MONO_TOKEN_TYPE_SPEC:
7200 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7203 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7207 /* Generic case, should be avoided for when a better error is possible. */
7208 if (!class && mono_error_ok (error)) {
7209 char *name = mono_class_name_from_token (image, type_token);
7210 char *assembly = mono_assembly_name_from_token (image, type_token);
7211 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7219 * mono_type_get_checked:
7220 * @image: the image where the type resides
7221 * @type_token: the token for the type
7222 * @context: the generic context used to evaluate generic instantiations in
7223 * @error: Error handling context
7225 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7227 * Returns: the MonoType that represents @type_token in @image
7230 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7232 MonoType *type = NULL;
7233 gboolean inflated = FALSE;
7235 mono_error_init (error);
7237 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7238 if (image_is_dynamic (image))
7239 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7241 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7242 MonoClass *class = mono_class_get_checked (image, type_token, error);
7245 g_assert (!mono_loader_get_last_error ());
7250 return mono_class_get_type (class);
7253 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7256 g_assert (!mono_loader_get_last_error ());
7261 MonoType *tmp = type;
7262 type = mono_class_get_type (mono_class_from_mono_type (type));
7263 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7264 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7265 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7267 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7269 if (type->type != tmp->type)
7272 mono_metadata_free_type (tmp);
7279 mono_class_get (MonoImage *image, guint32 type_token)
7281 return mono_class_get_full (image, type_token, NULL);
7285 * mono_image_init_name_cache:
7287 * Initializes the class name cache stored in image->name_cache.
7289 * LOCKING: Acquires the corresponding image lock.
7292 mono_image_init_name_cache (MonoImage *image)
7294 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7295 guint32 cols [MONO_TYPEDEF_SIZE];
7298 guint32 i, visib, nspace_index;
7299 GHashTable *name_cache2, *nspace_table;
7301 mono_image_lock (image);
7303 if (image->name_cache) {
7304 mono_image_unlock (image);
7308 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7310 if (image_is_dynamic (image)) {
7311 mono_image_unlock (image);
7315 /* Temporary hash table to avoid lookups in the nspace_table */
7316 name_cache2 = g_hash_table_new (NULL, NULL);
7318 for (i = 1; i <= t->rows; ++i) {
7319 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7320 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7322 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7323 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7325 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7327 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7328 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7330 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7331 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7332 if (!nspace_table) {
7333 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7334 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7335 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7338 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7341 /* Load type names from EXPORTEDTYPES table */
7343 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7344 guint32 cols [MONO_EXP_TYPE_SIZE];
7347 for (i = 0; i < t->rows; ++i) {
7348 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7349 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7350 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7352 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7353 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7354 if (!nspace_table) {
7355 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7356 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7357 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7360 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7364 g_hash_table_destroy (name_cache2);
7365 mono_image_unlock (image);
7368 /*FIXME Only dynamic assemblies should allow this operation.*/
7370 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7371 const char *name, guint32 index)
7373 GHashTable *nspace_table;
7374 GHashTable *name_cache;
7377 mono_image_lock (image);
7379 if (!image->name_cache)
7380 mono_image_init_name_cache (image);
7382 name_cache = image->name_cache;
7383 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7384 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7385 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7388 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7389 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7391 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7393 mono_image_unlock (image);
7402 find_nocase (gpointer key, gpointer value, gpointer user_data)
7404 char *name = (char*)key;
7405 FindUserData *data = (FindUserData*)user_data;
7407 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7408 data->value = value;
7412 * mono_class_from_name_case:
7413 * @image: The MonoImage where the type is looked up in
7414 * @name_space: the type namespace
7415 * @name: the type short name.
7416 * @deprecated: use the _checked variant
7418 * Obtains a MonoClass with a given namespace and a given name which
7419 * is located in the given MonoImage. The namespace and name
7420 * lookups are case insensitive.
7423 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7426 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7427 g_assert (!mono_error_ok (&error));
7432 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7434 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7435 guint32 cols [MONO_TYPEDEF_SIZE];
7440 mono_error_init (error);
7442 if (image_is_dynamic (image)) {
7444 FindUserData user_data;
7446 mono_image_lock (image);
7448 if (!image->name_cache)
7449 mono_image_init_name_cache (image);
7451 user_data.key = name_space;
7452 user_data.value = NULL;
7453 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7455 if (user_data.value) {
7456 GHashTable *nspace_table = (GHashTable*)user_data.value;
7458 user_data.key = name;
7459 user_data.value = NULL;
7461 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7463 if (user_data.value)
7464 token = GPOINTER_TO_UINT (user_data.value);
7467 mono_image_unlock (image);
7470 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7476 /* add a cache if needed */
7477 for (i = 1; i <= t->rows; ++i) {
7478 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7479 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7481 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7482 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7484 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7486 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7487 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7488 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7489 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7495 return_nested_in (MonoClass *class, char *nested)
7498 char *s = strchr (nested, '/');
7499 gpointer iter = NULL;
7506 while ((found = mono_class_get_nested_types (class, &iter))) {
7507 if (strcmp (found->name, nested) == 0) {
7509 return return_nested_in (found, s);
7517 search_modules (MonoImage *image, const char *name_space, const char *name)
7519 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7520 MonoImage *file_image;
7525 * The EXPORTEDTYPES table only contains public types, so have to search the
7527 * Note: image->modules contains the contents of the MODULEREF table, while
7528 * the real module list is in the FILE table.
7530 for (i = 0; i < file_table->rows; i++) {
7531 guint32 cols [MONO_FILE_SIZE];
7532 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7533 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7536 file_image = mono_image_load_file_for_image (image, i + 1);
7538 class = mono_class_from_name (file_image, name_space, name);
7548 * mono_class_from_name:
7549 * @image: The MonoImage where the type is looked up in
7550 * @name_space: the type namespace
7551 * @name: the type short name.
7553 * Obtains a MonoClass with a given namespace and a given name which
7554 * is located in the given MonoImage.
7556 * To reference nested classes, use the "/" character as a separator.
7557 * For example use "Foo/Bar" to reference the class Bar that is nested
7558 * inside Foo, like this: "class Foo { class Bar {} }".
7561 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7563 GHashTable *nspace_table;
7564 MonoImage *loaded_image;
7571 if ((nested = strchr (name, '/'))) {
7572 int pos = nested - name;
7573 int len = strlen (name);
7576 memcpy (buf, name, len + 1);
7578 nested = buf + pos + 1;
7582 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7583 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7584 gboolean res = get_class_from_name (image, name_space, name, &class);
7587 class = search_modules (image, name_space, name);
7589 return class ? return_nested_in (class, nested) : NULL;
7595 mono_image_lock (image);
7597 if (!image->name_cache)
7598 mono_image_init_name_cache (image);
7600 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7603 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7605 mono_image_unlock (image);
7607 if (!token && image_is_dynamic (image) && image->modules) {
7608 /* Search modules as well */
7609 for (i = 0; i < image->module_count; ++i) {
7610 MonoImage *module = image->modules [i];
7612 class = mono_class_from_name (module, name_space, name);
7619 class = search_modules (image, name_space, name);
7627 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7628 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7629 guint32 cols [MONO_EXP_TYPE_SIZE];
7632 idx = mono_metadata_token_index (token);
7634 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7636 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7637 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7638 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7641 class = mono_class_from_name (loaded_image, name_space, name);
7643 return return_nested_in (class, nested);
7645 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7646 guint32 assembly_idx;
7648 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7650 mono_assembly_load_reference (image, assembly_idx - 1);
7651 g_assert (image->references [assembly_idx - 1]);
7652 if (image->references [assembly_idx - 1] == (gpointer)-1)
7655 /* FIXME: Cycle detection */
7656 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7658 g_error ("not yet implemented");
7662 token = MONO_TOKEN_TYPE_DEF | token;
7664 class = mono_class_get (image, token);
7666 return return_nested_in (class, nested);
7671 * mono_class_is_subclass_of:
7672 * @klass: class to probe if it is a subclass of another one
7673 * @klassc: the class we suspect is the base class
7674 * @check_interfaces: whether we should perform interface checks
7676 * This method determines whether @klass is a subclass of @klassc.
7678 * If the @check_interfaces flag is set, then if @klassc is an interface
7679 * this method return true if the @klass implements the interface or
7680 * if @klass is an interface, if one of its base classes is @klass.
7682 * If @check_interfaces is false then, then if @klass is not an interface
7683 * then it returns true if the @klass is a subclass of @klassc.
7685 * if @klass is an interface and @klassc is System.Object, then this function
7690 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7691 gboolean check_interfaces)
7693 /*FIXME test for interfaces with variant generic arguments*/
7695 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7696 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7698 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7701 for (i = 0; i < klass->interface_count; i ++) {
7702 MonoClass *ic = klass->interfaces [i];
7707 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7712 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7715 if (klassc == mono_defaults.object_class)
7722 mono_type_is_generic_argument (MonoType *type)
7724 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7728 mono_class_has_variant_generic_params (MonoClass *klass)
7731 MonoGenericContainer *container;
7733 if (!klass->generic_class)
7736 container = klass->generic_class->container_class->generic_container;
7738 for (i = 0; i < container->type_argc; ++i)
7739 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7746 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7748 if (target == candidate)
7751 if (check_for_reference_conv &&
7752 mono_type_is_generic_argument (&target->byval_arg) &&
7753 mono_type_is_generic_argument (&candidate->byval_arg)) {
7754 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7755 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7757 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7760 if (!mono_class_is_assignable_from (target, candidate))
7766 * @container the generic container from the GTD
7767 * @klass: the class to be assigned to
7768 * @oklass: the source class
7770 * Both klass and oklass must be instances of the same generic interface.
7771 * Return true if @klass can be assigned to a @klass variable
7774 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7777 MonoType **klass_argv, **oklass_argv;
7778 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7779 MonoGenericContainer *container = klass_gtd->generic_container;
7781 if (klass == oklass)
7784 /*Viable candidates are instances of the same generic interface*/
7785 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7788 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7789 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7791 for (j = 0; j < container->type_argc; ++j) {
7792 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7793 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7795 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7799 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7800 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7802 if (param1_class != param2_class) {
7803 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7804 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7806 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7807 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7817 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7819 MonoGenericParam *gparam, *ogparam;
7820 MonoGenericParamInfo *tinfo, *cinfo;
7821 MonoClass **candidate_class;
7822 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7825 if (target == candidate)
7827 if (target->byval_arg.type != candidate->byval_arg.type)
7830 gparam = target->byval_arg.data.generic_param;
7831 ogparam = candidate->byval_arg.data.generic_param;
7832 tinfo = mono_generic_param_info (gparam);
7833 cinfo = mono_generic_param_info (ogparam);
7835 class_constraint_satisfied = FALSE;
7836 valuetype_constraint_satisfied = FALSE;
7838 /*candidate must have a super set of target's special constraints*/
7839 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7840 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7842 if (cinfo->constraints) {
7843 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7844 MonoClass *cc = *candidate_class;
7846 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7847 class_constraint_satisfied = TRUE;
7848 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7849 valuetype_constraint_satisfied = TRUE;
7852 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7853 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7855 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7857 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7859 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7860 valuetype_constraint_satisfied)) {
7865 /*candidate type constraints must be a superset of target's*/
7866 if (tinfo->constraints) {
7867 MonoClass **target_class;
7868 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7869 MonoClass *tc = *target_class;
7872 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7873 * check it's constraints since it satisfy the constraint by itself.
7875 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7878 if (!cinfo->constraints)
7881 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7882 MonoClass *cc = *candidate_class;
7884 if (mono_class_is_assignable_from (tc, cc))
7888 * This happens when we have the following:
7890 * Bar<K> where K : IFace
7891 * Foo<T, U> where T : U where U : IFace
7893 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7896 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7897 if (mono_gparam_is_assignable_from (target, cc))
7901 if (!*candidate_class)
7906 /*candidate itself must have a constraint that satisfy target*/
7907 if (cinfo->constraints) {
7908 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7909 MonoClass *cc = *candidate_class;
7910 if (mono_class_is_assignable_from (target, cc))
7918 mono_class_is_magical_array_interface (MonoClass *iface)
7920 static MonoClass* generic_ilist_class = NULL;
7921 static MonoClass* generic_icollection_class = NULL;
7922 static MonoClass* generic_ienumerable_class = NULL;
7923 static MonoClass* generic_ireadonlylist_class = NULL;
7924 static MonoClass* generic_ireadonlycollection_class = NULL;
7926 if (!generic_ilist_class) {
7927 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
7928 "System.Collections.Generic", "ICollection`1");
7929 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
7930 "System.Collections.Generic", "IEnumerable`1");
7931 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
7932 "System.Collections.Generic", "IReadOnlyList`1");
7933 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
7934 "System.Collections.Generic", "IReadOnlyCollection`1");
7936 mono_memory_barrier ();
7937 generic_ilist_class = mono_class_from_name (mono_defaults.corlib,
7938 "System.Collections.Generic", "IList`1");
7941 iface = mono_class_get_generic_type_definition (iface);
7942 return iface == generic_ilist_class ||
7943 iface == generic_icollection_class ||
7944 iface == generic_ienumerable_class ||
7945 iface == generic_ireadonlylist_class ||
7946 iface == generic_ireadonlycollection_class;
7950 lower_valuetype_class_for_array_cast (MonoClass *class)
7952 switch (class->byval_arg.type) {
7955 return mono_defaults.byte_class;
7958 return mono_defaults.int16_class;
7961 return mono_defaults.int32_class;
7964 return mono_defaults.int64_class;
7966 if (class->enumtype && mono_class_enum_basetype (class))
7967 return mono_class_from_mono_type (mono_class_enum_basetype (class));
7973 mono_array_class_implements_magic_interface (MonoClass *iface, MonoClass *array_class)
7975 MonoClass *iface_arg0, *array_arg0;
7977 if (!array_class->rank)
7980 if (!mono_class_is_magical_array_interface (iface))
7984 iface_arg0 = mono_class_from_mono_type (iface->generic_class->context.class_inst->type_argv [0]);
7985 array_arg0 = array_class->element_class;
7986 /* Valuetypes are not compatible with sys.enum, sys.valuetype and sys.object, but mono_class_is_assignable_from will report so. */
7987 if (array_arg0->valuetype) {
7988 if (iface_arg0 == mono_defaults.enum_class || iface_arg0 == mono_defaults.enum_class->parent || iface_arg0 == mono_defaults.object_class)
7992 if (mono_class_is_assignable_from (iface_arg0, array_arg0))
7995 if (array_arg0->valuetype && iface_arg0->valuetype && lower_valuetype_class_for_array_cast (array_arg0) == lower_valuetype_class_for_array_cast (iface_arg0))
8002 mono_array_class_implements_magic_interface_slow (MonoClass *iface, MonoClass *array_class)
8004 MonoClass *iface_arg0, *array_arg0;
8006 if (!array_class->rank)
8009 if (!mono_class_is_magical_array_interface (iface))
8012 iface_arg0 = mono_class_from_mono_type (iface->generic_class->context.class_inst->type_argv [0]);
8013 array_arg0 = array_class->element_class;
8014 /* Valuetypes are not compatible with sys.enum, sys.valuetype and sys.object, but mono_class_is_assignable_from will report so. */
8015 if (array_arg0->valuetype) {
8016 if (iface_arg0 == mono_defaults.enum_class || iface_arg0 == mono_defaults.enum_class->parent || iface_arg0 == mono_defaults.object_class)
8020 if (mono_class_is_assignable_from_slow (iface_arg0, array_arg0))
8023 if (array_arg0->valuetype && iface_arg0->valuetype && lower_valuetype_class_for_array_cast (array_arg0) == lower_valuetype_class_for_array_cast (iface_arg0))
8030 * mono_class_is_assignable_from:
8031 * @klass: the class to be assigned to
8032 * @oklass: the source class
8034 * Return: true if an instance of object oklass can be assigned to an
8035 * instance of object @klass
8038 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8040 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8042 mono_class_init (klass);
8044 if (!oklass->inited)
8045 mono_class_init (oklass);
8047 if (klass->exception_type || oklass->exception_type)
8050 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8051 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8053 return mono_gparam_is_assignable_from (klass, oklass);
8056 if (MONO_CLASS_IS_INTERFACE (klass)) {
8057 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8058 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8059 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8063 for (i = 0; constraints [i]; ++i) {
8064 if (mono_class_is_assignable_from (klass, constraints [i]))
8072 /* interface_offsets might not be set for dynamic classes */
8073 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8075 * oklass might be a generic type parameter but they have
8076 * interface_offsets set.
8078 return mono_reflection_call_is_assignable_to (oklass, klass);
8079 if (!oklass->interface_bitmap)
8080 /* Happens with generic instances of not-yet created dynamic types */
8082 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8085 if (mono_class_has_variant_generic_params (klass)) {
8088 mono_class_setup_interfaces (oklass, &error);
8089 if (!mono_error_ok (&error)) {
8090 mono_error_cleanup (&error);
8094 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8095 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8096 MonoClass *iface = oklass->interfaces_packed [i];
8098 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8103 if (mono_array_class_implements_magic_interface (klass, oklass))
8106 } else if (klass->delegate) {
8107 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8109 }else if (klass->rank) {
8110 MonoClass *eclass, *eoclass;
8112 if (oklass->rank != klass->rank)
8115 /* vectors vs. one dimensional arrays */
8116 if (oklass->byval_arg.type != klass->byval_arg.type)
8119 eclass = klass->cast_class;
8120 eoclass = oklass->cast_class;
8123 * a is b does not imply a[] is b[] when a is a valuetype, and
8124 * b is a reference type.
8127 if (eoclass->valuetype) {
8128 if ((eclass == mono_defaults.enum_class) ||
8129 (eclass == mono_defaults.enum_class->parent) ||
8130 (eclass == mono_defaults.object_class))
8134 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8135 } else if (mono_class_is_nullable (klass)) {
8136 if (mono_class_is_nullable (oklass))
8137 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8139 return mono_class_is_assignable_from (klass->cast_class, oklass);
8140 } else if (klass == mono_defaults.object_class)
8143 return mono_class_has_parent (oklass, klass);
8146 /*Check if @oklass is variant compatible with @klass.*/
8148 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8151 MonoType **klass_argv, **oklass_argv;
8152 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8153 MonoGenericContainer *container = klass_gtd->generic_container;
8155 /*Viable candidates are instances of the same generic interface*/
8156 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8159 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8160 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8162 for (j = 0; j < container->type_argc; ++j) {
8163 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8164 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8166 if (param1_class->valuetype != param2_class->valuetype)
8170 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8171 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8173 if (param1_class != param2_class) {
8174 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8175 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8177 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8178 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8186 /*Check if @candidate implements the interface @target*/
8188 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8192 gboolean is_variant = mono_class_has_variant_generic_params (target);
8194 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8195 if (mono_class_is_variant_compatible_slow (target, candidate))
8200 if (candidate == target)
8203 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8204 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8205 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8207 if (tb && tb->interfaces) {
8208 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8209 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8210 MonoClass *iface_class;
8212 /* we can't realize the type here since it can do pretty much anything. */
8215 iface_class = mono_class_from_mono_type (iface->type);
8216 if (iface_class == target)
8218 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8220 if (mono_class_implement_interface_slow (target, iface_class))
8225 /*setup_interfaces don't mono_class_init anything*/
8226 /*FIXME this doesn't handle primitive type arrays.
8227 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8228 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8230 mono_class_setup_interfaces (candidate, &error);
8231 if (!mono_error_ok (&error)) {
8232 mono_error_cleanup (&error);
8236 if (mono_array_class_implements_magic_interface_slow (target, candidate))
8239 for (i = 0; i < candidate->interface_count; ++i) {
8240 if (candidate->interfaces [i] == target)
8243 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8246 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8250 candidate = candidate->parent;
8251 } while (candidate);
8257 * Check if @oklass can be assigned to @klass.
8258 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8261 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8263 if (candidate == target)
8265 if (target == mono_defaults.object_class)
8268 if (mono_class_has_parent (candidate, target))
8271 /*If target is not an interface there is no need to check them.*/
8272 if (MONO_CLASS_IS_INTERFACE (target))
8273 return mono_class_implement_interface_slow (target, candidate);
8275 if (target->delegate && mono_class_has_variant_generic_params (target))
8276 return mono_class_is_variant_compatible (target, candidate, FALSE);
8279 MonoClass *eclass, *eoclass;
8281 if (target->rank != candidate->rank)
8284 /* vectors vs. one dimensional arrays */
8285 if (target->byval_arg.type != candidate->byval_arg.type)
8288 eclass = target->cast_class;
8289 eoclass = candidate->cast_class;
8292 * a is b does not imply a[] is b[] when a is a valuetype, and
8293 * b is a reference type.
8296 if (eoclass->valuetype) {
8297 if ((eclass == mono_defaults.enum_class) ||
8298 (eclass == mono_defaults.enum_class->parent) ||
8299 (eclass == mono_defaults.object_class))
8303 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8305 /*FIXME properly handle nullables */
8306 /*FIXME properly handle (M)VAR */
8311 * mono_class_get_cctor:
8312 * @klass: A MonoClass pointer
8314 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8317 mono_class_get_cctor (MonoClass *klass)
8319 MonoCachedClassInfo cached_info;
8321 if (image_is_dynamic (klass->image)) {
8323 * has_cctor is not set for these classes because mono_class_init () is
8326 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8329 if (!klass->has_cctor)
8332 if (mono_class_get_cached_class_info (klass, &cached_info))
8333 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8335 if (klass->generic_class && !klass->methods)
8336 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8338 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8342 * mono_class_get_finalizer:
8343 * @klass: The MonoClass pointer
8345 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8348 mono_class_get_finalizer (MonoClass *klass)
8350 MonoCachedClassInfo cached_info;
8353 mono_class_init (klass);
8354 if (!mono_class_has_finalizer (klass))
8357 if (mono_class_get_cached_class_info (klass, &cached_info))
8358 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8360 mono_class_setup_vtable (klass);
8361 return klass->vtable [finalize_slot];
8366 * mono_class_needs_cctor_run:
8367 * @klass: the MonoClass pointer
8368 * @caller: a MonoMethod describing the caller
8370 * Determines whenever the class has a static constructor and whenever it
8371 * needs to be called when executing CALLER.
8374 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8378 method = mono_class_get_cctor (klass);
8380 return (method == caller) ? FALSE : TRUE;
8386 * mono_class_array_element_size:
8389 * Returns: the number of bytes an element of type @klass
8390 * uses when stored into an array.
8393 mono_class_array_element_size (MonoClass *klass)
8395 MonoType *type = &klass->byval_arg;
8398 switch (type->type) {
8401 case MONO_TYPE_BOOLEAN:
8405 case MONO_TYPE_CHAR:
8414 case MONO_TYPE_CLASS:
8415 case MONO_TYPE_STRING:
8416 case MONO_TYPE_OBJECT:
8417 case MONO_TYPE_SZARRAY:
8418 case MONO_TYPE_ARRAY:
8420 case MONO_TYPE_MVAR:
8421 return sizeof (gpointer);
8426 case MONO_TYPE_VALUETYPE:
8427 if (type->data.klass->enumtype) {
8428 type = mono_class_enum_basetype (type->data.klass);
8429 klass = klass->element_class;
8432 return mono_class_instance_size (klass) - sizeof (MonoObject);
8433 case MONO_TYPE_GENERICINST:
8434 type = &type->data.generic_class->container_class->byval_arg;
8437 case MONO_TYPE_VOID:
8441 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8447 * mono_array_element_size:
8448 * @ac: pointer to a #MonoArrayClass
8450 * Returns: the size of single array element.
8453 mono_array_element_size (MonoClass *ac)
8455 g_assert (ac->rank);
8456 return ac->sizes.element_size;
8460 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8461 MonoGenericContext *context)
8463 if (image_is_dynamic (image)) {
8464 MonoClass *tmp_handle_class;
8465 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8467 g_assert (tmp_handle_class);
8469 *handle_class = tmp_handle_class;
8471 if (tmp_handle_class == mono_defaults.typehandle_class)
8472 return &((MonoClass*)obj)->byval_arg;
8477 switch (token & 0xff000000) {
8478 case MONO_TOKEN_TYPE_DEF:
8479 case MONO_TOKEN_TYPE_REF:
8480 case MONO_TOKEN_TYPE_SPEC: {
8484 *handle_class = mono_defaults.typehandle_class;
8485 type = mono_type_get_checked (image, token, context, &error);
8487 mono_loader_set_error_from_mono_error (&error);
8488 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8491 mono_class_init (mono_class_from_mono_type (type));
8492 /* We return a MonoType* as handle */
8495 case MONO_TOKEN_FIELD_DEF: {
8498 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8502 *handle_class = mono_defaults.fieldhandle_class;
8503 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8505 mono_loader_set_error_from_mono_error (&error);
8506 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8509 mono_class_init (class);
8510 return mono_class_get_field (class, token);
8512 case MONO_TOKEN_METHOD_DEF:
8513 case MONO_TOKEN_METHOD_SPEC: {
8515 meth = mono_get_method_full (image, token, NULL, context);
8517 *handle_class = mono_defaults.methodhandle_class;
8520 case MONO_TOKEN_MEMBER_REF: {
8521 guint32 cols [MONO_MEMBERREF_SIZE];
8523 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8524 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8525 mono_metadata_decode_blob_size (sig, &sig);
8526 if (*sig == 0x6) { /* it's a field */
8528 MonoClassField *field;
8529 field = mono_field_from_token (image, token, &klass, context);
8531 *handle_class = mono_defaults.fieldhandle_class;
8535 meth = mono_get_method_full (image, token, NULL, context);
8537 *handle_class = mono_defaults.methodhandle_class;
8542 g_warning ("Unknown token 0x%08x in ldtoken", token);
8549 * This function might need to call runtime functions so it can't be part
8550 * of the metadata library.
8552 static MonoLookupDynamicToken lookup_dynamic = NULL;
8555 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8557 lookup_dynamic = func;
8561 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8563 MonoClass *handle_class;
8565 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8569 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8571 return lookup_dynamic (image, token, valid_token, handle_class, context);
8574 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8577 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8579 get_cached_class_info = func;
8583 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8585 if (!get_cached_class_info)
8588 return get_cached_class_info (klass, res);
8592 mono_install_get_class_from_name (MonoGetClassFromName func)
8594 get_class_from_name = func;
8598 mono_class_get_image (MonoClass *klass)
8600 return klass->image;
8604 * mono_class_get_element_class:
8605 * @klass: the MonoClass to act on
8607 * Returns: the element class of an array or an enumeration.
8610 mono_class_get_element_class (MonoClass *klass)
8612 return klass->element_class;
8616 * mono_class_is_valuetype:
8617 * @klass: the MonoClass to act on
8619 * Returns: true if the MonoClass represents a ValueType.
8622 mono_class_is_valuetype (MonoClass *klass)
8624 return klass->valuetype;
8628 * mono_class_is_enum:
8629 * @klass: the MonoClass to act on
8631 * Returns: true if the MonoClass represents an enumeration.
8634 mono_class_is_enum (MonoClass *klass)
8636 return klass->enumtype;
8640 * mono_class_enum_basetype:
8641 * @klass: the MonoClass to act on
8643 * Returns: the underlying type representation for an enumeration.
8646 mono_class_enum_basetype (MonoClass *klass)
8648 if (klass->element_class == klass)
8649 /* SRE or broken types */
8652 return &klass->element_class->byval_arg;
8656 * mono_class_get_parent
8657 * @klass: the MonoClass to act on
8659 * Returns: the parent class for this class.
8662 mono_class_get_parent (MonoClass *klass)
8664 return klass->parent;
8668 * mono_class_get_nesting_type;
8669 * @klass: the MonoClass to act on
8671 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8674 mono_class_get_nesting_type (MonoClass *klass)
8676 return klass->nested_in;
8680 * mono_class_get_rank:
8681 * @klass: the MonoClass to act on
8683 * Returns: the rank for the array (the number of dimensions).
8686 mono_class_get_rank (MonoClass *klass)
8692 * mono_class_get_flags:
8693 * @klass: the MonoClass to act on
8695 * The type flags from the TypeDef table from the metadata.
8696 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8699 * Returns: the flags from the TypeDef table.
8702 mono_class_get_flags (MonoClass *klass)
8704 return klass->flags;
8708 * mono_class_get_name
8709 * @klass: the MonoClass to act on
8711 * Returns: the name of the class.
8714 mono_class_get_name (MonoClass *klass)
8720 * mono_class_get_namespace:
8721 * @klass: the MonoClass to act on
8723 * Returns: the namespace of the class.
8726 mono_class_get_namespace (MonoClass *klass)
8728 return klass->name_space;
8732 * mono_class_get_type:
8733 * @klass: the MonoClass to act on
8735 * This method returns the internal Type representation for the class.
8737 * Returns: the MonoType from the class.
8740 mono_class_get_type (MonoClass *klass)
8742 return &klass->byval_arg;
8746 * mono_class_get_type_token
8747 * @klass: the MonoClass to act on
8749 * This method returns type token for the class.
8751 * Returns: the type token for the class.
8754 mono_class_get_type_token (MonoClass *klass)
8756 return klass->type_token;
8760 * mono_class_get_byref_type:
8761 * @klass: the MonoClass to act on
8766 mono_class_get_byref_type (MonoClass *klass)
8768 return &klass->this_arg;
8772 * mono_class_num_fields:
8773 * @klass: the MonoClass to act on
8775 * Returns: the number of static and instance fields in the class.
8778 mono_class_num_fields (MonoClass *klass)
8780 return klass->field.count;
8784 * mono_class_num_methods:
8785 * @klass: the MonoClass to act on
8787 * Returns: the number of methods in the class.
8790 mono_class_num_methods (MonoClass *klass)
8792 return klass->method.count;
8796 * mono_class_num_properties
8797 * @klass: the MonoClass to act on
8799 * Returns: the number of properties in the class.
8802 mono_class_num_properties (MonoClass *klass)
8804 mono_class_setup_properties (klass);
8806 return klass->ext->property.count;
8810 * mono_class_num_events:
8811 * @klass: the MonoClass to act on
8813 * Returns: the number of events in the class.
8816 mono_class_num_events (MonoClass *klass)
8818 mono_class_setup_events (klass);
8820 return klass->ext->event.count;
8824 * mono_class_get_fields:
8825 * @klass: the MonoClass to act on
8827 * This routine is an iterator routine for retrieving the fields in a class.
8829 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8830 * iterate over all of the elements. When no more values are
8831 * available, the return value is NULL.
8833 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8836 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8838 MonoClassField* field;
8842 mono_class_setup_fields_locking (klass);
8843 if (klass->exception_type)
8845 /* start from the first */
8846 if (klass->field.count) {
8847 return *iter = &klass->fields [0];
8855 if (field < &klass->fields [klass->field.count]) {
8856 return *iter = field;
8862 * mono_class_get_methods
8863 * @klass: the MonoClass to act on
8865 * This routine is an iterator routine for retrieving the fields in a class.
8867 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8868 * iterate over all of the elements. When no more values are
8869 * available, the return value is NULL.
8871 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8874 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8876 MonoMethod** method;
8880 mono_class_setup_methods (klass);
8883 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8884 * FIXME we should better report this error to the caller
8886 if (!klass->methods)
8888 /* start from the first */
8889 if (klass->method.count) {
8890 *iter = &klass->methods [0];
8891 return klass->methods [0];
8899 if (method < &klass->methods [klass->method.count]) {
8907 * mono_class_get_virtual_methods:
8909 * Iterate over the virtual methods of KLASS.
8911 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8914 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8916 MonoMethod** method;
8919 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8921 mono_class_setup_methods (klass);
8923 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8924 * FIXME we should better report this error to the caller
8926 if (!klass->methods)
8928 /* start from the first */
8929 method = &klass->methods [0];
8934 while (method < &klass->methods [klass->method.count]) {
8935 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8939 if (method < &klass->methods [klass->method.count]) {
8946 /* Search directly in metadata to avoid calling setup_methods () */
8947 MonoMethod *res = NULL;
8953 start_index = GPOINTER_TO_UINT (*iter);
8956 for (i = start_index; i < klass->method.count; ++i) {
8959 /* class->method.first points into the methodptr table */
8960 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8962 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8966 if (i < klass->method.count) {
8967 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8968 /* Add 1 here so the if (*iter) check fails */
8969 *iter = GUINT_TO_POINTER (i + 1);
8978 * mono_class_get_properties:
8979 * @klass: the MonoClass to act on
8981 * This routine is an iterator routine for retrieving the properties in a class.
8983 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8984 * iterate over all of the elements. When no more values are
8985 * available, the return value is NULL.
8987 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8990 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8992 MonoProperty* property;
8996 mono_class_setup_properties (klass);
8997 /* start from the first */
8998 if (klass->ext->property.count) {
8999 return *iter = &klass->ext->properties [0];
9007 if (property < &klass->ext->properties [klass->ext->property.count]) {
9008 return *iter = property;
9014 * mono_class_get_events:
9015 * @klass: the MonoClass to act on
9017 * This routine is an iterator routine for retrieving the properties in a class.
9019 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9020 * iterate over all of the elements. When no more values are
9021 * available, the return value is NULL.
9023 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9026 mono_class_get_events (MonoClass* klass, gpointer *iter)
9032 mono_class_setup_events (klass);
9033 /* start from the first */
9034 if (klass->ext->event.count) {
9035 return *iter = &klass->ext->events [0];
9043 if (event < &klass->ext->events [klass->ext->event.count]) {
9044 return *iter = event;
9050 * mono_class_get_interfaces
9051 * @klass: the MonoClass to act on
9053 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9055 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9056 * iterate over all of the elements. When no more values are
9057 * available, the return value is NULL.
9059 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9062 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9070 mono_class_init (klass);
9071 if (!klass->interfaces_inited) {
9072 mono_class_setup_interfaces (klass, &error);
9073 if (!mono_error_ok (&error)) {
9074 mono_error_cleanup (&error);
9078 /* start from the first */
9079 if (klass->interface_count) {
9080 *iter = &klass->interfaces [0];
9081 return klass->interfaces [0];
9089 if (iface < &klass->interfaces [klass->interface_count]) {
9097 setup_nested_types (MonoClass *klass)
9100 GList *classes, *nested_classes, *l;
9103 if (klass->nested_classes_inited)
9106 if (!klass->type_token)
9107 klass->nested_classes_inited = TRUE;
9109 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9113 guint32 cols [MONO_NESTED_CLASS_SIZE];
9114 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9115 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9116 if (!mono_error_ok (&error)) {
9117 /*FIXME don't swallow the error message*/
9118 mono_error_cleanup (&error);
9120 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9124 classes = g_list_prepend (classes, nclass);
9126 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9129 mono_class_alloc_ext (klass);
9131 nested_classes = NULL;
9132 for (l = classes; l; l = l->next)
9133 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9134 g_list_free (classes);
9136 mono_image_lock (klass->image);
9138 mono_memory_barrier ();
9139 if (!klass->nested_classes_inited) {
9140 klass->ext->nested_classes = nested_classes;
9141 mono_memory_barrier ();
9142 klass->nested_classes_inited = TRUE;
9145 mono_image_unlock (klass->image);
9149 * mono_class_get_nested_types
9150 * @klass: the MonoClass to act on
9152 * This routine is an iterator routine for retrieving the nested types of a class.
9153 * This works only if @klass is non-generic, or a generic type definition.
9155 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9156 * iterate over all of the elements. When no more values are
9157 * available, the return value is NULL.
9159 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9162 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9168 if (!klass->nested_classes_inited)
9169 setup_nested_types (klass);
9172 /* start from the first */
9173 if (klass->ext && klass->ext->nested_classes) {
9174 *iter = klass->ext->nested_classes;
9175 return klass->ext->nested_classes->data;
9177 /* no nested types */
9192 * mono_class_is_delegate
9193 * @klass: the MonoClass to act on
9195 * Returns: true if the MonoClass represents a System.Delegate.
9198 mono_class_is_delegate (MonoClass *klass)
9200 return klass->delegate;
9204 * mono_class_implements_interface
9205 * @klass: The MonoClass to act on
9206 * @interface: The interface to check if @klass implements.
9208 * Returns: true if @klass implements @interface.
9211 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9213 return mono_class_is_assignable_from (iface, klass);
9217 * mono_field_get_name:
9218 * @field: the MonoClassField to act on
9220 * Returns: the name of the field.
9223 mono_field_get_name (MonoClassField *field)
9229 * mono_field_get_type:
9230 * @field: the MonoClassField to act on
9232 * Returns: MonoType of the field.
9235 mono_field_get_type (MonoClassField *field)
9238 MonoType *type = mono_field_get_type_checked (field, &error);
9239 if (!mono_error_ok (&error)) {
9240 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9241 mono_error_cleanup (&error);
9248 * mono_field_get_type_checked:
9249 * @field: the MonoClassField to act on
9250 * @error: used to return any erro found while retrieving @field type
9252 * Returns: MonoType of the field.
9255 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9257 mono_error_init (error);
9259 mono_field_resolve_type (field, error);
9264 * mono_field_get_parent:
9265 * @field: the MonoClassField to act on
9267 * Returns: MonoClass where the field was defined.
9270 mono_field_get_parent (MonoClassField *field)
9272 return field->parent;
9276 * mono_field_get_flags;
9277 * @field: the MonoClassField to act on
9279 * The metadata flags for a field are encoded using the
9280 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9282 * Returns: the flags for the field.
9285 mono_field_get_flags (MonoClassField *field)
9288 return mono_field_resolve_flags (field);
9289 return field->type->attrs;
9293 * mono_field_get_offset;
9294 * @field: the MonoClassField to act on
9296 * Returns: the field offset.
9299 mono_field_get_offset (MonoClassField *field)
9301 return field->offset;
9305 mono_field_get_rva (MonoClassField *field)
9309 MonoClass *klass = field->parent;
9310 MonoFieldDefaultValue *field_def_values;
9312 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9314 if (!klass->ext || !klass->ext->field_def_values) {
9315 mono_class_alloc_ext (klass);
9317 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9319 mono_image_lock (klass->image);
9320 if (!klass->ext->field_def_values)
9321 klass->ext->field_def_values = field_def_values;
9322 mono_image_unlock (klass->image);
9325 field_index = mono_field_get_index (field);
9327 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9328 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9330 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9331 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9334 return klass->ext->field_def_values [field_index].data;
9338 * mono_field_get_data;
9339 * @field: the MonoClassField to act on
9341 * Returns: pointer to the metadata constant value or to the field
9342 * data if it has an RVA flag.
9345 mono_field_get_data (MonoClassField *field)
9347 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9348 MonoTypeEnum def_type;
9350 return mono_class_get_field_default_value (field, &def_type);
9351 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9352 return mono_field_get_rva (field);
9359 * mono_property_get_name:
9360 * @prop: the MonoProperty to act on
9362 * Returns: the name of the property
9365 mono_property_get_name (MonoProperty *prop)
9371 * mono_property_get_set_method
9372 * @prop: the MonoProperty to act on.
9374 * Returns: the setter method of the property (A MonoMethod)
9377 mono_property_get_set_method (MonoProperty *prop)
9383 * mono_property_get_get_method
9384 * @prop: the MonoProperty to act on.
9386 * Returns: the setter method of the property (A MonoMethod)
9389 mono_property_get_get_method (MonoProperty *prop)
9395 * mono_property_get_parent:
9396 * @prop: the MonoProperty to act on.
9398 * Returns: the MonoClass where the property was defined.
9401 mono_property_get_parent (MonoProperty *prop)
9403 return prop->parent;
9407 * mono_property_get_flags:
9408 * @prop: the MonoProperty to act on.
9410 * The metadata flags for a property are encoded using the
9411 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9413 * Returns: the flags for the property.
9416 mono_property_get_flags (MonoProperty *prop)
9422 * mono_event_get_name:
9423 * @event: the MonoEvent to act on
9425 * Returns: the name of the event.
9428 mono_event_get_name (MonoEvent *event)
9434 * mono_event_get_add_method:
9435 * @event: The MonoEvent to act on.
9437 * Returns: the @add' method for the event (a MonoMethod).
9440 mono_event_get_add_method (MonoEvent *event)
9446 * mono_event_get_remove_method:
9447 * @event: The MonoEvent to act on.
9449 * Returns: the @remove method for the event (a MonoMethod).
9452 mono_event_get_remove_method (MonoEvent *event)
9454 return event->remove;
9458 * mono_event_get_raise_method:
9459 * @event: The MonoEvent to act on.
9461 * Returns: the @raise method for the event (a MonoMethod).
9464 mono_event_get_raise_method (MonoEvent *event)
9466 return event->raise;
9470 * mono_event_get_parent:
9471 * @event: the MonoEvent to act on.
9473 * Returns: the MonoClass where the event is defined.
9476 mono_event_get_parent (MonoEvent *event)
9478 return event->parent;
9482 * mono_event_get_flags
9483 * @event: the MonoEvent to act on.
9485 * The metadata flags for an event are encoded using the
9486 * EVENT_* constants. See the tabledefs.h file for details.
9488 * Returns: the flags for the event.
9491 mono_event_get_flags (MonoEvent *event)
9493 return event->attrs;
9497 * mono_class_get_method_from_name:
9498 * @klass: where to look for the method
9499 * @name: name of the method
9500 * @param_count: number of parameters. -1 for any number.
9502 * Obtains a MonoMethod with a given name and number of parameters.
9503 * It only works if there are no multiple signatures for any given method name.
9506 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9508 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9512 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9514 MonoMethod *res = NULL;
9517 /* Search directly in the metadata to avoid calling setup_methods () */
9518 for (i = 0; i < klass->method.count; ++i) {
9519 guint32 cols [MONO_METHOD_SIZE];
9521 MonoMethodSignature *sig;
9523 /* class->method.first points into the methodptr table */
9524 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9526 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9527 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9528 if (param_count == -1) {
9532 sig = mono_method_signature (method);
9533 if (sig && sig->param_count == param_count) {
9544 * mono_class_get_method_from_name_flags:
9545 * @klass: where to look for the method
9546 * @name_space: name of the method
9547 * @param_count: number of parameters. -1 for any number.
9548 * @flags: flags which must be set in the method
9550 * Obtains a MonoMethod with a given name and number of parameters.
9551 * It only works if there are no multiple signatures for any given method name.
9554 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9556 MonoMethod *res = NULL;
9559 mono_class_init (klass);
9561 if (klass->generic_class && !klass->methods) {
9562 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9564 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9568 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9569 mono_class_setup_methods (klass);
9571 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9572 See mono/tests/array_load_exception.il
9573 FIXME we should better report this error to the caller
9575 if (!klass->methods)
9577 for (i = 0; i < klass->method.count; ++i) {
9578 MonoMethod *method = klass->methods [i];
9580 if (method->name[0] == name [0] &&
9581 !strcmp (name, method->name) &&
9582 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9583 ((method->flags & flags) == flags)) {
9590 res = find_method_in_metadata (klass, name, param_count, flags);
9597 * mono_class_set_failure:
9598 * @klass: class in which the failure was detected
9599 * @ex_type: the kind of exception/error to be thrown (later)
9600 * @ex_data: exception data (specific to each type of exception/error)
9602 * Keep a detected failure informations in the class for later processing.
9603 * Note that only the first failure is kept.
9605 * LOCKING: Acquires the loader lock.
9608 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9610 if (klass->exception_type)
9613 mono_loader_lock ();
9614 klass->exception_type = ex_type;
9616 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9617 mono_loader_unlock ();
9623 * mono_class_get_exception_data:
9625 * Return the exception_data property of KLASS.
9627 * LOCKING: Acquires the loader lock.
9630 mono_class_get_exception_data (MonoClass *klass)
9632 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9636 * mono_classes_init:
9638 * Initialize the resources used by this module.
9641 mono_classes_init (void)
9643 mono_mutex_init (&classes_mutex);
9645 mono_counters_register ("Inflated methods size",
9646 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9647 mono_counters_register ("Inflated classes",
9648 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9649 mono_counters_register ("Inflated classes size",
9650 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9651 mono_counters_register ("MonoClass size",
9652 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9653 mono_counters_register ("MonoClassExt size",
9654 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9658 * mono_classes_cleanup:
9660 * Free the resources used by this module.
9663 mono_classes_cleanup (void)
9665 if (global_interface_bitset)
9666 mono_bitset_free (global_interface_bitset);
9667 global_interface_bitset = NULL;
9668 mono_mutex_destroy (&classes_mutex);
9672 * mono_class_get_exception_for_failure:
9673 * @klass: class in which the failure was detected
9675 * Return a constructed MonoException than the caller can then throw
9676 * using mono_raise_exception - or NULL if no failure is present (or
9677 * doesn't result in an exception).
9680 mono_class_get_exception_for_failure (MonoClass *klass)
9682 gpointer exception_data = mono_class_get_exception_data (klass);
9684 switch (klass->exception_type) {
9685 #ifndef DISABLE_SECURITY
9686 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9687 MonoDomain *domain = mono_domain_get ();
9688 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9689 MonoMethod *method = exception_data;
9690 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9691 MonoObject *exc = NULL;
9695 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9696 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9697 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9699 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9700 return (MonoException*) exc;
9703 case MONO_EXCEPTION_TYPE_LOAD: {
9706 char *str = mono_type_get_full_name (klass);
9707 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9708 name = mono_string_new (mono_domain_get (), str);
9710 ex = mono_get_exception_type_load (name, astr);
9714 case MONO_EXCEPTION_MISSING_METHOD: {
9715 char *class_name = exception_data;
9716 char *assembly_name = class_name + strlen (class_name) + 1;
9718 return mono_get_exception_missing_method (class_name, assembly_name);
9720 case MONO_EXCEPTION_MISSING_FIELD: {
9721 char *class_name = exception_data;
9722 char *member_name = class_name + strlen (class_name) + 1;
9724 return mono_get_exception_missing_field (class_name, member_name);
9726 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9727 char *msg_format = exception_data;
9728 char *assembly_name = msg_format + strlen (msg_format) + 1;
9729 char *msg = g_strdup_printf (msg_format, assembly_name);
9732 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9738 case MONO_EXCEPTION_BAD_IMAGE: {
9739 return mono_get_exception_bad_image_format (exception_data);
9742 MonoLoaderError *error;
9745 error = mono_loader_get_last_error ();
9747 ex = mono_loader_error_prepare_exception (error);
9751 /* TODO - handle other class related failures */
9758 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9760 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9761 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9763 if (outer_klass == inner_klass)
9765 inner_klass = inner_klass->nested_in;
9766 } while (inner_klass);
9771 mono_class_get_generic_type_definition (MonoClass *klass)
9773 return klass->generic_class ? klass->generic_class->container_class : klass;
9777 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9779 * Generic instantiations are ignored for all super types of @klass.
9781 * Visibility checks ignoring generic instantiations.
9784 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9787 klass = mono_class_get_generic_type_definition (klass);
9788 parent = mono_class_get_generic_type_definition (parent);
9789 mono_class_setup_supertypes (klass);
9791 for (i = 0; i < klass->idepth; ++i) {
9792 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9798 * Subtype can only access parent members with family protection if the site object
9799 * is subclass of Subtype. For example:
9800 * class A { protected int x; }
9802 * void valid_access () {
9806 * void invalid_access () {
9813 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9815 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9818 if (context_klass == NULL)
9820 /*if access_klass is not member_klass context_klass must be type compat*/
9821 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9827 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9830 if (accessing == accessed)
9832 if (!accessed || !accessing)
9835 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9836 * anywhere so untrusted friends are not safe to access platform's code internals */
9837 if (mono_security_core_clr_enabled ()) {
9838 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9842 mono_assembly_load_friends (accessed);
9843 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9844 MonoAssemblyName *friend = tmp->data;
9845 /* Be conservative with checks */
9848 if (strcmp (accessing->aname.name, friend->name))
9850 if (friend->public_key_token [0]) {
9851 if (!accessing->aname.public_key_token [0])
9853 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9862 * If klass is a generic type or if it is derived from a generic type, return the
9863 * MonoClass of the generic definition
9864 * Returns NULL if not found
9867 get_generic_definition_class (MonoClass *klass)
9870 if (klass->generic_class && klass->generic_class->container_class)
9871 return klass->generic_class->container_class;
9872 klass = klass->parent;
9878 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9881 for (i = 0; i < ginst->type_argc; ++i) {
9882 MonoType *type = ginst->type_argv[i];
9883 switch (type->type) {
9884 case MONO_TYPE_SZARRAY:
9885 if (!can_access_type (access_klass, type->data.klass))
9888 case MONO_TYPE_ARRAY:
9889 if (!can_access_type (access_klass, type->data.array->eklass))
9893 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9896 case MONO_TYPE_CLASS:
9897 case MONO_TYPE_VALUETYPE:
9898 case MONO_TYPE_GENERICINST:
9899 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9907 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9911 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9914 if (access_klass->element_class && !access_klass->enumtype)
9915 access_klass = access_klass->element_class;
9917 if (member_klass->element_class && !member_klass->enumtype)
9918 member_klass = member_klass->element_class;
9920 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9922 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9925 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9928 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9931 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9934 /*Non nested type with nested visibility. We just fail it.*/
9935 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9938 switch (access_level) {
9939 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9940 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9942 case TYPE_ATTRIBUTE_PUBLIC:
9945 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9948 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9949 return is_nesting_type (member_klass, access_klass);
9951 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9952 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9954 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9955 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9957 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9958 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9959 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9961 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9962 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9963 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9968 /* FIXME: check visibility of type, too */
9970 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9972 MonoClass *member_generic_def;
9973 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9976 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9977 access_klass->generic_container) &&
9978 (member_generic_def = get_generic_definition_class (member_klass))) {
9979 MonoClass *access_container;
9981 if (access_klass->generic_container)
9982 access_container = access_klass;
9984 access_container = access_klass->generic_class->container_class;
9986 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9990 /* Partition I 8.5.3.2 */
9991 /* the access level values are the same for fields and methods */
9992 switch (access_level) {
9993 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9994 /* same compilation unit */
9995 return access_klass->image == member_klass->image;
9996 case FIELD_ATTRIBUTE_PRIVATE:
9997 return access_klass == member_klass;
9998 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9999 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10000 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10003 case FIELD_ATTRIBUTE_ASSEMBLY:
10004 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10005 case FIELD_ATTRIBUTE_FAMILY:
10006 if (is_valid_family_access (access_klass, member_klass, context_klass))
10009 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10010 if (is_valid_family_access (access_klass, member_klass, context_klass))
10012 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10013 case FIELD_ATTRIBUTE_PUBLIC:
10020 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10022 /* FIXME: check all overlapping fields */
10023 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10025 MonoClass *nested = method->klass->nested_in;
10027 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10030 nested = nested->nested_in;
10037 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10039 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10041 MonoClass *nested = method->klass->nested_in;
10043 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10046 nested = nested->nested_in;
10051 * with generics calls to explicit interface implementations can be expressed
10052 * directly: the method is private, but we must allow it. This may be opening
10053 * a hole or the generics code should handle this differently.
10054 * Maybe just ensure the interface type is public.
10056 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10062 * mono_method_can_access_method_full:
10063 * @method: The caller method
10064 * @called: The called method
10065 * @context_klass: The static type on stack of the owner @called object used
10067 * This function must be used with instance calls, as they have more strict family accessibility.
10068 * It can be used with static methods, but context_klass should be NULL.
10070 * Returns: TRUE if caller have proper visibility and acessibility to @called
10073 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10075 MonoClass *access_class = method->klass;
10076 MonoClass *member_class = called->klass;
10077 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10079 MonoClass *nested = access_class->nested_in;
10081 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10084 nested = nested->nested_in;
10091 can = can_access_type (access_class, member_class);
10093 MonoClass *nested = access_class->nested_in;
10095 can = can_access_type (nested, member_class);
10098 nested = nested->nested_in;
10105 if (called->is_inflated) {
10106 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10107 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10116 * mono_method_can_access_field_full:
10117 * @method: The caller method
10118 * @field: The accessed field
10119 * @context_klass: The static type on stack of the owner @field object used
10121 * This function must be used with instance fields, as they have more strict family accessibility.
10122 * It can be used with static fields, but context_klass should be NULL.
10124 * Returns: TRUE if caller have proper visibility and acessibility to @field
10127 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10129 MonoClass *access_class = method->klass;
10130 MonoClass *member_class = field->parent;
10131 /* FIXME: check all overlapping fields */
10132 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10134 MonoClass *nested = access_class->nested_in;
10136 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10139 nested = nested->nested_in;
10146 can = can_access_type (access_class, member_class);
10148 MonoClass *nested = access_class->nested_in;
10150 can = can_access_type (nested, member_class);
10153 nested = nested->nested_in;
10163 * mono_class_can_access_class:
10164 * @source_class: The source class
10165 * @target_class: The accessed class
10167 * This function returns is @target_class is visible to @source_class
10169 * Returns: TRUE if source have proper visibility and acessibility to target
10172 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10174 return can_access_type (source_class, target_class);
10178 * mono_type_is_valid_enum_basetype:
10179 * @type: The MonoType to check
10181 * Returns: TRUE if the type can be used as the basetype of an enum
10183 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10184 switch (type->type) {
10187 case MONO_TYPE_BOOLEAN:
10190 case MONO_TYPE_CHAR:
10203 * mono_class_is_valid_enum:
10204 * @klass: An enum class to be validated
10206 * This method verify the required properties an enum should have.
10208 * Returns: TRUE if the informed enum class is valid
10210 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10211 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10212 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10214 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10215 MonoClassField * field;
10216 gpointer iter = NULL;
10217 gboolean found_base_field = FALSE;
10219 g_assert (klass->enumtype);
10220 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10221 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10225 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10228 while ((field = mono_class_get_fields (klass, &iter))) {
10229 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10230 if (found_base_field)
10232 found_base_field = TRUE;
10233 if (!mono_type_is_valid_enum_basetype (field->type))
10238 if (!found_base_field)
10241 if (klass->method.count > 0)
10248 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10250 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10254 * mono_class_setup_interface_id:
10256 * Initializes MonoClass::interface_id if required.
10258 * LOCKING: Acquires the loader lock.
10261 mono_class_setup_interface_id (MonoClass *class)
10263 mono_loader_lock ();
10264 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10265 class->interface_id = mono_get_unique_iid (class);
10266 mono_loader_unlock ();
10270 * mono_class_alloc_ext:
10272 * Allocate klass->ext if not already done.
10275 mono_class_alloc_ext (MonoClass *klass)
10282 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10283 mono_image_lock (klass->image);
10284 mono_memory_barrier ();
10287 class_ext_size += sizeof (MonoClassExt);
10288 mono_image_unlock (klass->image);
10292 * mono_class_setup_interfaces:
10294 * Initialize class->interfaces/interfaces_count.
10295 * LOCKING: Acquires the loader lock.
10296 * This function can fail the type.
10299 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10301 int i, interface_count;
10302 MonoClass **interfaces;
10304 mono_error_init (error);
10306 if (klass->interfaces_inited)
10309 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10310 MonoType *args [1];
10312 /* generic IList, ICollection, IEnumerable */
10313 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10314 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10316 args [0] = &klass->element_class->byval_arg;
10317 interfaces [0] = mono_class_bind_generic_parameters (
10318 mono_defaults.generic_ilist_class, 1, args, FALSE);
10319 if (interface_count > 1)
10320 interfaces [1] = mono_class_bind_generic_parameters (
10321 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10322 } else if (klass->generic_class) {
10323 MonoClass *gklass = klass->generic_class->container_class;
10325 mono_class_setup_interfaces (gklass, error);
10326 if (!mono_error_ok (error)) {
10327 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10331 interface_count = gklass->interface_count;
10332 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10333 for (i = 0; i < interface_count; i++) {
10334 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10335 if (!mono_error_ok (error)) {
10336 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10341 interface_count = 0;
10345 mono_image_lock (klass->image);
10347 if (!klass->interfaces_inited) {
10348 klass->interface_count = interface_count;
10349 klass->interfaces = interfaces;
10351 mono_memory_barrier ();
10353 klass->interfaces_inited = TRUE;
10356 mono_image_unlock (klass->image);
10360 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10362 MonoClass *class = field->parent;
10363 MonoImage *image = class->image;
10364 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10365 int field_idx = field - class->fields;
10367 mono_error_init (error);
10370 MonoClassField *gfield = >d->fields [field_idx];
10371 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10372 if (!mono_error_ok (error)) {
10373 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10374 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10378 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10379 if (!mono_error_ok (error)) {
10380 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10381 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10386 guint32 cols [MONO_FIELD_SIZE];
10387 MonoGenericContainer *container = NULL;
10388 int idx = class->field.first + field_idx;
10390 /*FIXME, in theory we do not lazy load SRE fields*/
10391 g_assert (!image_is_dynamic (image));
10393 if (class->generic_container) {
10394 container = class->generic_container;
10396 container = gtd->generic_container;
10397 g_assert (container);
10400 /* class->field.first and idx points into the fieldptr table */
10401 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10403 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10404 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10405 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10409 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10411 mono_metadata_decode_value (sig, &sig);
10412 /* FIELD signature == 0x06 */
10413 g_assert (*sig == 0x06);
10414 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10416 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10421 mono_field_resolve_flags (MonoClassField *field)
10423 MonoClass *class = field->parent;
10424 MonoImage *image = class->image;
10425 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10426 int field_idx = field - class->fields;
10430 MonoClassField *gfield = >d->fields [field_idx];
10431 return mono_field_get_flags (gfield);
10433 int idx = class->field.first + field_idx;
10435 /*FIXME, in theory we do not lazy load SRE fields*/
10436 g_assert (!image_is_dynamic (image));
10438 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10443 * mono_class_setup_basic_field_info:
10444 * @class: The class to initialize
10446 * Initializes the class->fields array of fields.
10447 * Aquires the loader lock.
10450 mono_class_setup_basic_field_info_locking (MonoClass *class)
10452 mono_loader_lock ();
10453 mono_class_setup_basic_field_info (class);
10454 mono_loader_unlock ();
10458 * mono_class_get_fields_lazy:
10459 * @klass: the MonoClass to act on
10461 * This routine is an iterator routine for retrieving the fields in a class.
10462 * Only minimal information about fields are loaded. Accessors must be used
10463 * for all MonoClassField returned.
10465 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10466 * iterate over all of the elements. When no more values are
10467 * available, the return value is NULL.
10469 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10472 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10474 MonoClassField* field;
10478 mono_class_setup_basic_field_info_locking (klass);
10479 if (!klass->fields)
10481 /* start from the first */
10482 if (klass->field.count) {
10483 return *iter = &klass->fields [0];
10491 if (field < &klass->fields [klass->field.count]) {
10492 return *iter = field;
10498 mono_class_full_name (MonoClass *klass)
10500 return mono_type_full_name (&klass->byval_arg);