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));
1645 if (class->generic_container) {
1646 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1652 /* Only do these checks if we still think this type is blittable */
1653 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1654 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1657 MonoClass *field_class = mono_class_from_mono_type (field->type);
1659 mono_class_setup_fields (field_class);
1660 if (field_class->exception_type) {
1661 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1665 if (!field_class || !field_class->blittable)
1670 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1671 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1672 blittable = class->element_class->blittable;
1675 if (mono_type_has_exceptions (field->type)) {
1676 char *class_name = mono_type_get_full_name (class);
1677 char *type_name = mono_type_full_name (field->type);
1679 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1680 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1681 g_free (class_name);
1685 /* The def_value of fields is compute lazily during vtable creation */
1688 if (class == mono_defaults.string_class)
1691 class->blittable = blittable;
1693 if (class->enumtype && !mono_class_enum_basetype (class)) {
1694 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1697 if (explicit_size && real_size) {
1698 class->instance_size = MAX (real_size, class->instance_size);
1701 if (class->exception_type)
1703 mono_class_layout_fields (class);
1705 /*valuetypes can't be neither bigger than 1Mb or empty. */
1706 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1707 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1709 mono_memory_barrier ();
1710 class->fields_inited = 1;
1714 * mono_class_setup_fields_locking:
1715 * @class: The class to initialize
1717 * Initializes the class->fields array of fields.
1718 * Aquires the loader lock.
1721 mono_class_setup_fields_locking (MonoClass *class)
1723 /* This can be checked without locks */
1724 if (class->fields_inited)
1726 mono_loader_lock ();
1727 mono_class_setup_fields (class);
1728 mono_loader_unlock ();
1732 * mono_class_has_references:
1734 * Returns whenever @klass->has_references is set, initializing it if needed.
1735 * Aquires the loader lock.
1738 mono_class_has_references (MonoClass *klass)
1740 if (klass->init_pending) {
1741 /* Be conservative */
1744 mono_class_init (klass);
1746 return klass->has_references;
1751 * mono_type_get_basic_type_from_generic:
1754 * Returns a closed type corresponding to the possibly open type
1758 mono_type_get_basic_type_from_generic (MonoType *type)
1760 /* When we do generic sharing we let type variables stand for reference types. */
1761 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1762 return &mono_defaults.object_class->byval_arg;
1767 * mono_class_layout_fields:
1770 * Compute the placement of fields inside an object or struct, according to
1771 * the layout rules and set the following fields in @class:
1772 * - has_references (if the class contains instance references firled or structs that contain references)
1773 * - has_static_refs (same, but for static fields)
1774 * - instance_size (size of the object in memory)
1775 * - class_size (size needed for the static fields)
1776 * - size_inited (flag set when the instance_size is set)
1778 * LOCKING: this is supposed to be called with the loader lock held.
1781 mono_class_layout_fields (MonoClass *class)
1784 const int top = class->field.count;
1785 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1786 guint32 pass, passes, real_size;
1787 gboolean gc_aware_layout = FALSE;
1788 gboolean has_static_fields = FALSE;
1789 MonoClassField *field;
1792 * When we do generic sharing we need to have layout
1793 * information for open generic classes (either with a generic
1794 * context containing type variables or with a generic
1795 * container), so we don't return in that case anymore.
1799 * Enable GC aware auto layout: in this mode, reference
1800 * fields are grouped together inside objects, increasing collector
1802 * Requires that all classes whose layout is known to native code be annotated
1803 * with [StructLayout (LayoutKind.Sequential)]
1804 * Value types have gc_aware_layout disabled by default, as per
1805 * what the default is for other runtimes.
1807 /* corlib is missing [StructLayout] directives in many places */
1808 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1809 if (!class->valuetype)
1810 gc_aware_layout = TRUE;
1813 /* Compute klass->has_references */
1815 * Process non-static fields first, since static fields might recursively
1816 * refer to the class itself.
1818 for (i = 0; i < top; i++) {
1821 field = &class->fields [i];
1823 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1824 ftype = mono_type_get_underlying_type (field->type);
1825 ftype = mono_type_get_basic_type_from_generic (ftype);
1826 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1827 class->has_references = TRUE;
1831 for (i = 0; i < top; i++) {
1834 field = &class->fields [i];
1836 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1837 ftype = mono_type_get_underlying_type (field->type);
1838 ftype = mono_type_get_basic_type_from_generic (ftype);
1839 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1840 class->has_static_refs = TRUE;
1844 for (i = 0; i < top; i++) {
1847 field = &class->fields [i];
1849 ftype = mono_type_get_underlying_type (field->type);
1850 ftype = mono_type_get_basic_type_from_generic (ftype);
1851 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1852 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1853 class->has_static_refs = TRUE;
1855 class->has_references = TRUE;
1860 * Compute field layout and total size (not considering static fields)
1864 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1865 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1867 if (gc_aware_layout)
1872 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1875 if (class->parent) {
1876 mono_class_setup_fields (class->parent);
1877 if (class->parent->exception_type) {
1878 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1881 real_size = class->parent->instance_size;
1883 real_size = sizeof (MonoObject);
1886 for (pass = 0; pass < passes; ++pass) {
1887 for (i = 0; i < top; i++){
1892 field = &class->fields [i];
1894 if (mono_field_is_deleted (field))
1896 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1899 ftype = mono_type_get_underlying_type (field->type);
1900 ftype = mono_type_get_basic_type_from_generic (ftype);
1901 if (gc_aware_layout) {
1902 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1911 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1912 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1913 /* This field is a hack inserted by MCS to empty structures */
1917 size = mono_type_size (field->type, &align);
1919 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1920 align = class->packing_size ? MIN (class->packing_size, align): align;
1921 /* if the field has managed references, we need to force-align it
1924 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1925 align = MAX (align, sizeof (gpointer));
1927 class->min_align = MAX (align, class->min_align);
1928 field->offset = real_size;
1930 field->offset += align - 1;
1931 field->offset &= ~(align - 1);
1933 /*TypeBuilders produce all sort of weird things*/
1934 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1935 real_size = field->offset + size;
1938 class->instance_size = MAX (real_size, class->instance_size);
1940 if (class->instance_size & (class->min_align - 1)) {
1941 class->instance_size += class->min_align - 1;
1942 class->instance_size &= ~(class->min_align - 1);
1946 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1950 for (i = 0; i < top; i++) {
1955 field = &class->fields [i];
1958 * There must be info about all the fields in a type if it
1959 * uses explicit layout.
1961 if (mono_field_is_deleted (field))
1963 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1966 size = mono_type_size (field->type, &align);
1967 align = class->packing_size ? MIN (class->packing_size, align): align;
1968 class->min_align = MAX (align, class->min_align);
1971 * When we get here, field->offset is already set by the
1972 * loader (for either runtime fields or fields loaded from metadata).
1973 * The offset is from the start of the object: this works for both
1974 * classes and valuetypes.
1976 field->offset += sizeof (MonoObject);
1977 ftype = mono_type_get_underlying_type (field->type);
1978 ftype = mono_type_get_basic_type_from_generic (ftype);
1979 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1980 if (field->offset % sizeof (gpointer)) {
1981 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1988 real_size = MAX (real_size, size + field->offset);
1991 if (class->has_references) {
1992 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
1994 /* Check for overlapping reference and non-reference fields */
1995 for (i = 0; i < top; i++) {
1998 field = &class->fields [i];
2000 if (mono_field_is_deleted (field))
2002 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2004 ftype = mono_type_get_underlying_type (field->type);
2005 if (MONO_TYPE_IS_REFERENCE (ftype))
2006 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2008 for (i = 0; i < top; i++) {
2009 field = &class->fields [i];
2011 if (mono_field_is_deleted (field))
2013 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2016 // FIXME: Too much code does this
2018 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2019 char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
2020 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2024 g_free (ref_bitmap);
2027 class->instance_size = MAX (real_size, class->instance_size);
2028 if (class->instance_size & (class->min_align - 1)) {
2029 class->instance_size += class->min_align - 1;
2030 class->instance_size &= ~(class->min_align - 1);
2036 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2038 * For small structs, set min_align to at least the struct size to improve
2039 * performance, and since the JIT memset/memcpy code assumes this and generates
2040 * unaligned accesses otherwise. See #78990 for a testcase.
2042 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2043 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2046 mono_memory_barrier ();
2047 class->size_inited = 1;
2050 * Compute static field layout and size
2052 for (i = 0; i < top; i++){
2056 field = &class->fields [i];
2058 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2060 if (mono_field_is_deleted (field))
2063 if (mono_type_has_exceptions (field->type)) {
2064 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2068 has_static_fields = TRUE;
2070 size = mono_type_size (field->type, &align);
2071 field->offset = class->sizes.class_size;
2072 /*align is always non-zero here*/
2073 field->offset += align - 1;
2074 field->offset &= ~(align - 1);
2075 class->sizes.class_size = field->offset + size;
2078 if (has_static_fields && class->sizes.class_size == 0)
2079 /* Simplify code which depends on class_size != 0 if the class has static fields */
2080 class->sizes.class_size = 8;
2084 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2088 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2089 method->klass = class;
2090 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2091 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2092 method->signature = sig;
2093 method->name = name;
2096 if (name [0] == '.') {
2097 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2099 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2105 * mono_class_setup_methods:
2108 * Initializes the 'methods' array in CLASS.
2109 * Calling this method should be avoided if possible since it allocates a lot
2110 * of long-living MonoMethod structures.
2111 * Methods belonging to an interface are assigned a sequential slot starting
2114 * On failure this function sets class->exception_type
2117 mono_class_setup_methods (MonoClass *class)
2120 MonoMethod **methods;
2125 if (class->generic_class) {
2127 MonoClass *gklass = class->generic_class->container_class;
2129 mono_class_init (gklass);
2130 if (!gklass->exception_type)
2131 mono_class_setup_methods (gklass);
2132 if (gklass->exception_type) {
2133 /* FIXME make exception_data less opaque so it's possible to dup it here */
2134 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2138 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2139 count = gklass->method.count;
2140 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2142 for (i = 0; i < count; i++) {
2143 methods [i] = mono_class_inflate_generic_method_full_checked (
2144 gklass->methods [i], class, mono_class_get_context (class), &error);
2145 if (!mono_error_ok (&error)) {
2146 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2147 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)));
2150 mono_error_cleanup (&error);
2154 } else if (class->rank) {
2156 MonoMethod *amethod;
2157 MonoMethodSignature *sig;
2158 int count_generic = 0, first_generic = 0;
2161 count = 3 + (class->rank > 1? 2: 1);
2163 mono_class_setup_interfaces (class, &error);
2164 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2166 if (class->interface_count) {
2167 count_generic = generic_array_methods (class);
2168 first_generic = count;
2169 count += class->interface_count * count_generic;
2172 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2174 sig = mono_metadata_signature_alloc (class->image, class->rank);
2175 sig->ret = &mono_defaults.void_class->byval_arg;
2176 sig->pinvoke = TRUE;
2177 sig->hasthis = TRUE;
2178 for (i = 0; i < class->rank; ++i)
2179 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2181 amethod = create_array_method (class, ".ctor", sig);
2182 methods [method_num++] = amethod;
2183 if (class->rank > 1) {
2184 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2185 sig->ret = &mono_defaults.void_class->byval_arg;
2186 sig->pinvoke = TRUE;
2187 sig->hasthis = TRUE;
2188 for (i = 0; i < class->rank * 2; ++i)
2189 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2191 amethod = create_array_method (class, ".ctor", sig);
2192 methods [method_num++] = amethod;
2194 /* element Get (idx11, [idx2, ...]) */
2195 sig = mono_metadata_signature_alloc (class->image, class->rank);
2196 sig->ret = &class->element_class->byval_arg;
2197 sig->pinvoke = TRUE;
2198 sig->hasthis = TRUE;
2199 for (i = 0; i < class->rank; ++i)
2200 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2201 amethod = create_array_method (class, "Get", sig);
2202 methods [method_num++] = amethod;
2203 /* element& Address (idx11, [idx2, ...]) */
2204 sig = mono_metadata_signature_alloc (class->image, class->rank);
2205 sig->ret = &class->element_class->this_arg;
2206 sig->pinvoke = TRUE;
2207 sig->hasthis = TRUE;
2208 for (i = 0; i < class->rank; ++i)
2209 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2210 amethod = create_array_method (class, "Address", sig);
2211 methods [method_num++] = amethod;
2212 /* void Set (idx11, [idx2, ...], element) */
2213 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2214 sig->ret = &mono_defaults.void_class->byval_arg;
2215 sig->pinvoke = TRUE;
2216 sig->hasthis = TRUE;
2217 for (i = 0; i < class->rank; ++i)
2218 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2219 sig->params [i] = &class->element_class->byval_arg;
2220 amethod = create_array_method (class, "Set", sig);
2221 methods [method_num++] = amethod;
2223 for (i = 0; i < class->interface_count; i++)
2224 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2226 count = class->method.count;
2227 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2228 for (i = 0; i < count; ++i) {
2229 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2230 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2234 if (MONO_CLASS_IS_INTERFACE (class)) {
2236 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2237 for (i = 0; i < count; ++i) {
2238 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2239 methods [i]->slot = slot++;
2243 mono_image_lock (class->image);
2245 if (!class->methods) {
2246 class->method.count = count;
2248 /* Needed because of the double-checking locking pattern */
2249 mono_memory_barrier ();
2251 class->methods = methods;
2254 mono_image_unlock (class->image);
2258 * mono_class_get_method_by_index:
2260 * Returns class->methods [index], initializing class->methods if neccesary.
2262 * LOCKING: Acquires the loader lock.
2265 mono_class_get_method_by_index (MonoClass *class, int index)
2267 /* Avoid calling setup_methods () if possible */
2268 if (class->generic_class && !class->methods) {
2269 MonoClass *gklass = class->generic_class->container_class;
2272 m = mono_class_inflate_generic_method_full (
2273 gklass->methods [index], class, mono_class_get_context (class));
2275 * If setup_methods () is called later for this class, no duplicates are created,
2276 * since inflate_generic_method guarantees that only one instance of a method
2277 * is created for each context.
2280 mono_class_setup_methods (class);
2281 g_assert (m == class->methods [index]);
2285 mono_class_setup_methods (class);
2286 if (class->exception_type) /*FIXME do proper error handling*/
2288 g_assert (index >= 0 && index < class->method.count);
2289 return class->methods [index];
2294 * mono_class_get_inflated_method:
2296 * Given an inflated class CLASS and a method METHOD which should be a method of
2297 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2300 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2302 MonoClass *gklass = class->generic_class->container_class;
2305 g_assert (method->klass == gklass);
2307 mono_class_setup_methods (gklass);
2308 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2310 for (i = 0; i < gklass->method.count; ++i) {
2311 if (gklass->methods [i] == method) {
2313 return class->methods [i];
2315 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2323 * mono_class_get_vtable_entry:
2325 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2326 * LOCKING: Acquires the loader lock.
2329 mono_class_get_vtable_entry (MonoClass *class, int offset)
2333 if (class->rank == 1) {
2335 * szarrays do not overwrite any methods of Array, so we can avoid
2336 * initializing their vtables in some cases.
2338 mono_class_setup_vtable (class->parent);
2339 if (offset < class->parent->vtable_size)
2340 return class->parent->vtable [offset];
2343 if (class->generic_class) {
2344 MonoClass *gklass = class->generic_class->container_class;
2345 mono_class_setup_vtable (gklass);
2346 m = gklass->vtable [offset];
2348 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2350 mono_class_setup_vtable (class);
2351 if (class->exception_type)
2353 m = class->vtable [offset];
2360 * mono_class_get_vtable_size:
2362 * Return the vtable size for KLASS.
2365 mono_class_get_vtable_size (MonoClass *klass)
2367 mono_class_setup_vtable (klass);
2369 return klass->vtable_size;
2373 * mono_class_setup_properties:
2375 * Initialize class->ext.property and class->ext.properties.
2377 * This method can fail the class.
2380 mono_class_setup_properties (MonoClass *class)
2382 guint startm, endm, i, j;
2383 guint32 cols [MONO_PROPERTY_SIZE];
2384 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2385 MonoProperty *properties;
2389 if (class->ext && class->ext->properties)
2392 if (class->generic_class) {
2393 MonoClass *gklass = class->generic_class->container_class;
2395 mono_class_init (gklass);
2396 mono_class_setup_properties (gklass);
2397 if (gklass->exception_type) {
2398 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2402 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2404 for (i = 0; i < gklass->ext->property.count; i++) {
2405 MonoProperty *prop = &properties [i];
2407 *prop = gklass->ext->properties [i];
2410 prop->get = mono_class_inflate_generic_method_full (
2411 prop->get, class, mono_class_get_context (class));
2413 prop->set = mono_class_inflate_generic_method_full (
2414 prop->set, class, mono_class_get_context (class));
2416 prop->parent = class;
2419 first = gklass->ext->property.first;
2420 count = gklass->ext->property.count;
2422 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2423 count = last - first;
2426 mono_class_setup_methods (class);
2427 if (class->exception_type)
2431 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2432 for (i = first; i < last; ++i) {
2433 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2434 properties [i - first].parent = class;
2435 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2436 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2438 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2439 for (j = startm; j < endm; ++j) {
2442 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2444 if (class->image->uncompressed_metadata)
2445 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2446 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2448 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2450 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2451 case METHOD_SEMANTIC_SETTER:
2452 properties [i - first].set = method;
2454 case METHOD_SEMANTIC_GETTER:
2455 properties [i - first].get = method;
2464 mono_class_alloc_ext (class);
2466 mono_image_lock (class->image);
2468 if (class->ext->properties) {
2469 /* We leak 'properties' which was allocated from the image mempool */
2470 mono_image_unlock (class->image);
2474 class->ext->property.first = first;
2475 class->ext->property.count = count;
2477 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2478 mono_memory_barrier ();
2480 /* Leave this assignment as the last op in the function */
2481 class->ext->properties = properties;
2483 mono_image_unlock (class->image);
2487 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2489 MonoMethod **om, **retval;
2492 for (om = methods, count = 0; *om; ++om, ++count)
2495 retval = g_new0 (MonoMethod*, count + 1);
2497 for (om = methods, count = 0; *om; ++om, ++count)
2498 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2503 /*This method can fail the class.*/
2505 mono_class_setup_events (MonoClass *class)
2508 guint startm, endm, i, j;
2509 guint32 cols [MONO_EVENT_SIZE];
2510 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2514 if (class->ext && class->ext->events)
2517 if (class->generic_class) {
2518 MonoClass *gklass = class->generic_class->container_class;
2519 MonoGenericContext *context = NULL;
2521 mono_class_setup_events (gklass);
2522 if (gklass->exception_type) {
2523 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2527 first = gklass->ext->event.first;
2528 count = gklass->ext->event.count;
2530 events = mono_class_new0 (class, MonoEvent, count);
2533 context = mono_class_get_context (class);
2535 for (i = 0; i < count; i++) {
2536 MonoEvent *event = &events [i];
2537 MonoEvent *gevent = &gklass->ext->events [i];
2539 event->parent = class;
2540 event->name = gevent->name;
2541 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2542 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2543 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2544 #ifndef MONO_SMALL_CONFIG
2545 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2547 event->attrs = gevent->attrs;
2550 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2551 count = last - first;
2554 mono_class_setup_methods (class);
2555 if (class->exception_type) {
2556 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2561 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2562 for (i = first; i < last; ++i) {
2563 MonoEvent *event = &events [i - first];
2565 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2566 event->parent = class;
2567 event->attrs = cols [MONO_EVENT_FLAGS];
2568 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2570 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2571 for (j = startm; j < endm; ++j) {
2574 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2576 if (class->image->uncompressed_metadata)
2577 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2578 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2580 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2582 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2583 case METHOD_SEMANTIC_ADD_ON:
2584 event->add = method;
2586 case METHOD_SEMANTIC_REMOVE_ON:
2587 event->remove = method;
2589 case METHOD_SEMANTIC_FIRE:
2590 event->raise = method;
2592 case METHOD_SEMANTIC_OTHER: {
2593 #ifndef MONO_SMALL_CONFIG
2596 if (event->other == NULL) {
2597 event->other = g_new0 (MonoMethod*, 2);
2599 while (event->other [n])
2601 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2603 event->other [n] = method;
2604 /* NULL terminated */
2605 event->other [n + 1] = NULL;
2616 mono_class_alloc_ext (class);
2618 mono_image_lock (class->image);
2620 if (class->ext->events) {
2621 mono_image_unlock (class->image);
2625 class->ext->event.first = first;
2626 class->ext->event.count = count;
2628 /* Flush any pending writes as we do double checked locking on class->ext.events */
2629 mono_memory_barrier ();
2631 /* Leave this assignment as the last op in the function */
2632 class->ext->events = events;
2634 mono_image_unlock (class->image);
2638 * Global pool of interface IDs, represented as a bitset.
2639 * LOCKING: Protected by the classes lock.
2641 static MonoBitSet *global_interface_bitset = NULL;
2644 * mono_unload_interface_ids:
2645 * @bitset: bit set of interface IDs
2647 * When an image is unloaded, the interface IDs associated with
2648 * the image are put back in the global pool of IDs so the numbers
2652 mono_unload_interface_ids (MonoBitSet *bitset)
2655 mono_bitset_sub (global_interface_bitset, bitset);
2660 mono_unload_interface_id (MonoClass *class)
2662 if (global_interface_bitset && class->interface_id) {
2664 mono_bitset_clear (global_interface_bitset, class->interface_id);
2670 * mono_get_unique_iid:
2673 * Assign a unique integer ID to the interface represented by @class.
2674 * The ID will positive and as small as possible.
2675 * LOCKING: Acquires the classes lock.
2676 * Returns: the new ID.
2679 mono_get_unique_iid (MonoClass *class)
2683 g_assert (MONO_CLASS_IS_INTERFACE (class));
2687 if (!global_interface_bitset) {
2688 global_interface_bitset = mono_bitset_new (128, 0);
2691 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2693 int old_size = mono_bitset_size (global_interface_bitset);
2694 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2695 mono_bitset_free (global_interface_bitset);
2696 global_interface_bitset = new_set;
2699 mono_bitset_set (global_interface_bitset, iid);
2700 /* set the bit also in the per-image set */
2701 if (!class->generic_class) {
2702 if (class->image->interface_bitset) {
2703 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2704 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2705 mono_bitset_free (class->image->interface_bitset);
2706 class->image->interface_bitset = new_set;
2709 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2711 mono_bitset_set (class->image->interface_bitset, iid);
2716 #ifndef MONO_SMALL_CONFIG
2717 if (mono_print_vtable) {
2719 char *type_name = mono_type_full_name (&class->byval_arg);
2720 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2721 generic_id = class->generic_class->context.class_inst->id;
2722 g_assert (generic_id != 0);
2726 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2731 g_assert (iid <= 65535);
2736 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2741 mono_class_setup_interfaces (klass, error);
2742 if (!mono_error_ok (error))
2745 for (i = 0; i < klass->interface_count; i++) {
2746 ic = klass->interfaces [i];
2749 *res = g_ptr_array_new ();
2750 g_ptr_array_add (*res, ic);
2751 mono_class_init (ic);
2752 if (ic->exception_type) {
2753 mono_error_set_type_load_class (error, ic, "Error Loading class");
2757 collect_implemented_interfaces_aux (ic, res, error);
2758 if (!mono_error_ok (error))
2764 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2766 GPtrArray *res = NULL;
2768 collect_implemented_interfaces_aux (klass, &res, error);
2769 if (!mono_error_ok (error)) {
2771 g_ptr_array_free (res, TRUE);
2778 compare_interface_ids (const void *p_key, const void *p_element) {
2779 const MonoClass *key = p_key;
2780 const MonoClass *element = *(MonoClass**) p_element;
2782 return (key->interface_id - element->interface_id);
2785 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2787 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2788 MonoClass **result = mono_binary_search (
2790 klass->interfaces_packed,
2791 klass->interface_offsets_count,
2792 sizeof (MonoClass *),
2793 compare_interface_ids);
2795 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2802 * mono_class_interface_offset_with_variance:
2804 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2805 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2807 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2809 * FIXME figure out MS disambiguation rules and fix this function.
2812 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2813 int i = mono_class_interface_offset (klass, itf);
2814 *non_exact_match = FALSE;
2818 if (!mono_class_has_variant_generic_params (itf))
2821 for (i = 0; i < klass->interface_offsets_count; i++) {
2822 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2823 *non_exact_match = TRUE;
2824 return klass->interface_offsets_packed [i];
2832 print_implemented_interfaces (MonoClass *klass) {
2835 GPtrArray *ifaces = NULL;
2837 int ancestor_level = 0;
2839 name = mono_type_get_full_name (klass);
2840 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2843 for (i = 0; i < klass->interface_offsets_count; i++)
2844 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2845 klass->interfaces_packed [i]->interface_id,
2846 klass->interface_offsets_packed [i],
2847 klass->interfaces_packed [i]->method.count,
2848 klass->interfaces_packed [i]->name_space,
2849 klass->interfaces_packed [i]->name );
2850 printf ("Interface flags: ");
2851 for (i = 0; i <= klass->max_interface_id; i++)
2852 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2853 printf ("(%d,T)", i);
2855 printf ("(%d,F)", i);
2857 printf ("Dump interface flags:");
2858 #ifdef COMPRESSED_INTERFACE_BITMAP
2860 const uint8_t* p = klass->interface_bitmap;
2861 i = klass->max_interface_id;
2863 printf (" %d x 00 %02X", p [0], p [1]);
2869 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2870 printf (" %02X", klass->interface_bitmap [i]);
2873 while (klass != NULL) {
2874 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2875 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2876 if (!mono_error_ok (&error)) {
2877 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2878 mono_error_cleanup (&error);
2879 } else if (ifaces) {
2880 for (i = 0; i < ifaces->len; i++) {
2881 MonoClass *ic = g_ptr_array_index (ifaces, i);
2882 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2883 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2885 mono_class_interface_offset (klass, ic),
2890 g_ptr_array_free (ifaces, TRUE);
2893 klass = klass->parent;
2898 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2901 args [0] = &arg0->byval_arg;
2903 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2907 array_class_get_if_rank (MonoClass *class, guint rank)
2909 return rank ? mono_array_class_get (class, rank) : class;
2913 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2915 valuetype_types [0] = eclass;
2916 if (eclass == mono_defaults.int16_class)
2917 valuetype_types [1] = mono_defaults.uint16_class;
2918 else if (eclass == mono_defaults.uint16_class)
2919 valuetype_types [1] = mono_defaults.int16_class;
2920 else if (eclass == mono_defaults.int32_class)
2921 valuetype_types [1] = mono_defaults.uint32_class;
2922 else if (eclass == mono_defaults.uint32_class)
2923 valuetype_types [1] = mono_defaults.int32_class;
2924 else if (eclass == mono_defaults.int64_class)
2925 valuetype_types [1] = mono_defaults.uint64_class;
2926 else if (eclass == mono_defaults.uint64_class)
2927 valuetype_types [1] = mono_defaults.int64_class;
2928 else if (eclass == mono_defaults.byte_class)
2929 valuetype_types [1] = mono_defaults.sbyte_class;
2930 else if (eclass == mono_defaults.sbyte_class)
2931 valuetype_types [1] = mono_defaults.byte_class;
2932 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2933 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2936 /* this won't be needed once bug #325495 is completely fixed
2937 * though we'll need something similar to know which interfaces to allow
2938 * in arrays when they'll be lazyly created
2940 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2941 * MS returns diferrent types based on which instance is called. For example:
2942 * object obj = new byte[10][];
2943 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2944 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2947 * Fixing this should kill quite some code, save some bits and improve compatibility.
2950 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2952 MonoClass *eclass = class->element_class;
2953 static MonoClass* generic_icollection_class = NULL;
2954 static MonoClass* generic_ienumerable_class = NULL;
2955 static MonoClass* generic_ienumerator_class = NULL;
2956 static MonoClass* generic_ireadonlylist_class = NULL;
2957 static MonoClass* generic_ireadonlycollection_class = NULL;
2958 MonoClass *valuetype_types[2] = { NULL, NULL };
2959 MonoClass **interfaces = NULL;
2960 int i, nifaces, interface_count, real_count, original_rank;
2962 gboolean internal_enumerator;
2963 gboolean eclass_is_valuetype;
2965 if (!mono_defaults.generic_ilist_class) {
2969 internal_enumerator = FALSE;
2970 eclass_is_valuetype = FALSE;
2971 original_rank = eclass->rank;
2972 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2973 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2975 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2977 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2978 original_rank = eclass->rank;
2980 eclass = eclass->element_class;
2981 internal_enumerator = TRUE;
2982 *is_enumerator = TRUE;
2990 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2991 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2993 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2995 if (!generic_icollection_class) {
2996 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2997 "System.Collections.Generic", "ICollection`1");
2998 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2999 "System.Collections.Generic", "IEnumerable`1");
3000 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3001 "System.Collections.Generic", "IEnumerator`1");
3002 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3003 "System.Collections.Generic", "IReadOnlyList`1");
3004 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3005 "System.Collections.Generic", "IReadOnlyCollection`1");
3008 mono_class_init (eclass);
3011 * Arrays in 2.0 need to implement a number of generic interfaces
3012 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3013 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3014 * We collect the types needed to build the
3015 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3016 * the generic interfaces needed to implement.
3018 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3019 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3021 if (eclass->valuetype) {
3022 nifaces = generic_ireadonlylist_class ? 5 : 3;
3023 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3025 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3026 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3027 if (internal_enumerator) {
3029 if (valuetype_types [1])
3033 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3034 interfaces [0] = valuetype_types [0];
3035 if (valuetype_types [1])
3036 interfaces [nifaces] = valuetype_types [1];
3038 eclass_is_valuetype = TRUE;
3041 int idepth = eclass->idepth;
3042 if (!internal_enumerator)
3044 nifaces = generic_ireadonlylist_class ? 2 : 3;
3046 // FIXME: This doesn't seem to work/required for generic params
3047 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3048 mono_class_setup_interface_offsets (eclass);
3050 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3051 /* we add object for interfaces and the supertypes for the other
3052 * types. The last of the supertypes is the element class itself which we
3053 * already created the explicit interfaces for (so we include it for IEnumerator
3054 * and exclude it for arrays).
3056 if (MONO_CLASS_IS_INTERFACE (eclass))
3059 interface_count += idepth;
3060 if (eclass->rank && eclass->element_class->valuetype) {
3061 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3062 if (valuetype_types [1])
3065 /* IList, ICollection, IEnumerable, IReadOnlyList */
3066 interface_count *= nifaces;
3067 real_count = interface_count;
3068 if (internal_enumerator) {
3069 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3070 if (valuetype_types [1])
3073 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3074 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3075 interfaces [0] = mono_defaults.object_class;
3079 for (i = 0; i < idepth; i++) {
3080 mono_class_init (eclass->supertypes [i]);
3081 interfaces [j] = eclass->supertypes [i];
3085 if (all_interfaces) {
3086 for (i = 0; i < eclass->interface_offsets_count; i++) {
3087 interfaces [j] = eclass->interfaces_packed [i];
3091 for (i = 0; i < eclass->interface_count; i++) {
3092 interfaces [j] = eclass->interfaces [i];
3096 if (valuetype_types [1]) {
3097 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3102 /* instantiate the generic interfaces */
3103 for (i = 0; i < interface_count; i += nifaces) {
3104 MonoClass *iface = interfaces [i];
3106 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3107 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3109 if (eclass->valuetype) {
3110 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3111 if (generic_ireadonlylist_class) {
3112 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3113 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3116 if (!generic_ireadonlylist_class)
3117 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3120 if (internal_enumerator) {
3122 /* instantiate IEnumerator<iface> */
3123 for (i = 0; i < interface_count; i++) {
3124 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3126 j = interface_count;
3127 if (!eclass_is_valuetype) {
3128 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3129 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3132 for (i = 0; i < eclass->idepth; i++) {
3133 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3137 for (i = 0; i < eclass->interface_offsets_count; i++) {
3138 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3142 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3144 if (valuetype_types [1])
3145 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3149 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3150 for (i = 0; i < real_count; ++i) {
3151 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3152 g_print ("%s implements %s\n", type_name, name);
3163 find_array_interface (MonoClass *klass, const char *name)
3166 for (i = 0; i < klass->interface_count; ++i) {
3167 if (strcmp (klass->interfaces [i]->name, name) == 0)
3174 * Return the number of virtual methods.
3175 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3176 * Return -1 on failure.
3177 * FIXME It would be nice if this information could be cached somewhere.
3180 count_virtual_methods (MonoClass *class)
3184 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3186 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3187 mono_class_setup_methods (class);
3188 if (class->exception_type)
3191 for (i = 0; i < class->method.count; ++i) {
3192 flags = class->methods [i]->flags;
3193 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3197 for (i = 0; i < class->method.count; ++i) {
3198 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3200 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3208 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3216 m = (l + num_ifaces) / 2;
3217 if (interfaces_full [m] == ic)
3219 if (l == num_ifaces)
3221 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3230 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3232 int i = find_interface (num_ifaces, interfaces_full, ic);
3234 return interface_offsets_full [i];
3239 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3241 int i = find_interface (num_ifaces, interfaces_full, ic);
3245 interface_offsets_full [i] = offset;
3248 for (i = 0; i < num_ifaces; ++i) {
3249 if (interfaces_full [i]) {
3251 if (interfaces_full [i]->interface_id < ic->interface_id)
3254 while (end < num_ifaces && interfaces_full [end]) end++;
3255 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3256 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3258 interfaces_full [i] = ic;
3259 interface_offsets_full [i] = offset;
3265 #ifdef COMPRESSED_INTERFACE_BITMAP
3268 * Compressed interface bitmap design.
3270 * Interface bitmaps take a large amount of memory, because their size is
3271 * linear with the maximum interface id assigned in the process (each interface
3272 * is assigned a unique id as it is loaded). The number of interface classes
3273 * is high because of the many implicit interfaces implemented by arrays (we'll
3274 * need to lazy-load them in the future).
3275 * Most classes implement a very small number of interfaces, so the bitmap is
3276 * sparse. This bitmap needs to be checked by interface casts, so access to the
3277 * needed bit must be fast and doable with few jit instructions.
3279 * The current compression format is as follows:
3280 * *) it is a sequence of one or more two-byte elements
3281 * *) the first byte in the element is the count of empty bitmap bytes
3282 * at the current bitmap position
3283 * *) the second byte in the element is an actual bitmap byte at the current
3286 * As an example, the following compressed bitmap bytes:
3287 * 0x07 0x01 0x00 0x7
3288 * correspond to the following bitmap:
3289 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3291 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3292 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3293 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3297 * mono_compress_bitmap:
3298 * @dest: destination buffer
3299 * @bitmap: bitmap buffer
3300 * @size: size of @bitmap in bytes
3302 * This is a mono internal function.
3303 * The @bitmap data is compressed into a format that is small but
3304 * still searchable in few instructions by the JIT and runtime.
3305 * The compressed data is stored in the buffer pointed to by the
3306 * @dest array. Passing a #NULL value for @dest allows to just compute
3307 * the size of the buffer.
3308 * This compression algorithm assumes the bits set in the bitmap are
3309 * few and far between, like in interface bitmaps.
3310 * Returns: the size of the compressed bitmap in bytes.
3313 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3317 const uint8_t *end = bitmap + size;
3318 while (bitmap < end) {
3319 if (*bitmap || numz == 255) {
3343 * mono_class_interface_match:
3344 * @bitmap: a compressed bitmap buffer
3345 * @id: the index to check in the bitmap
3347 * This is a mono internal function.
3348 * Checks if a bit is set in a compressed interface bitmap. @id must
3349 * be already checked for being smaller than the maximum id encoded in the
3352 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3356 mono_class_interface_match (const uint8_t *bitmap, int id)
3359 id -= bitmap [0] * 8;
3363 return bitmap [1] & (1 << id);
3372 * LOCKING: this is supposed to be called with the loader lock held.
3373 * Return -1 on failure and set exception_type
3376 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3380 int i, j, max_iid, num_ifaces;
3381 MonoClass **interfaces_full = NULL;
3382 int *interface_offsets_full = NULL;
3384 GPtrArray **ifaces_array = NULL;
3385 int interface_offsets_count;
3386 MonoClass **array_interfaces = NULL;
3387 int num_array_interfaces;
3388 int is_enumerator = FALSE;
3390 mono_class_setup_supertypes (class);
3392 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3393 * implicit interfaces have the property that they are assigned the same slot in the
3394 * vtables for compatible interfaces
3396 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3398 /* compute maximum number of slots and maximum interface id */
3400 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3401 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3402 for (j = 0; j < class->idepth; j++) {
3403 k = class->supertypes [j];
3404 num_ifaces += k->interface_count;
3405 for (i = 0; i < k->interface_count; i++) {
3406 ic = k->interfaces [i];
3409 mono_class_init (ic);
3411 if (max_iid < ic->interface_id)
3412 max_iid = ic->interface_id;
3414 ifaces = mono_class_get_implemented_interfaces (k, &error);
3415 if (!mono_error_ok (&error)) {
3416 char *name = mono_type_get_full_name (k);
3417 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)));
3419 mono_error_cleanup (&error);
3424 num_ifaces += ifaces->len;
3425 for (i = 0; i < ifaces->len; ++i) {
3426 ic = g_ptr_array_index (ifaces, i);
3427 if (max_iid < ic->interface_id)
3428 max_iid = ic->interface_id;
3430 ifaces_array [j] = ifaces;
3434 for (i = 0; i < num_array_interfaces; ++i) {
3435 ic = array_interfaces [i];
3436 mono_class_init (ic);
3437 if (max_iid < ic->interface_id)
3438 max_iid = ic->interface_id;
3441 if (MONO_CLASS_IS_INTERFACE (class)) {
3443 if (max_iid < class->interface_id)
3444 max_iid = class->interface_id;
3446 class->max_interface_id = max_iid;
3447 /* compute vtable offset for interfaces */
3448 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3449 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3451 for (i = 0; i < num_ifaces; i++) {
3452 interface_offsets_full [i] = -1;
3455 /* skip the current class */
3456 for (j = 0; j < class->idepth - 1; j++) {
3457 k = class->supertypes [j];
3458 ifaces = ifaces_array [j];
3461 for (i = 0; i < ifaces->len; ++i) {
3463 ic = g_ptr_array_index (ifaces, i);
3465 /*Force the sharing of interface offsets between parent and subtypes.*/
3466 io = mono_class_interface_offset (k, ic);
3468 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3473 g_assert (class == class->supertypes [class->idepth - 1]);
3474 ifaces = ifaces_array [class->idepth - 1];
3476 for (i = 0; i < ifaces->len; ++i) {
3478 ic = g_ptr_array_index (ifaces, i);
3479 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3481 count = count_virtual_methods (ic);
3483 char *name = mono_type_get_full_name (ic);
3484 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3493 if (MONO_CLASS_IS_INTERFACE (class))
3494 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3496 if (num_array_interfaces) {
3497 if (is_enumerator) {
3498 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3499 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3500 g_assert (ienumerator_offset >= 0);
3501 for (i = 0; i < num_array_interfaces; ++i) {
3502 ic = array_interfaces [i];
3503 if (strcmp (ic->name, "IEnumerator`1") == 0)
3504 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3506 g_assert_not_reached ();
3507 /*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);*/
3510 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3511 int ilist_iface_idx = find_array_interface (class, "IList`1");
3512 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3513 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3514 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3515 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3516 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3517 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3518 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3519 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3520 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3521 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3522 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3523 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3524 for (i = 0; i < num_array_interfaces; ++i) {
3526 ic = array_interfaces [i];
3527 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3528 offset = ilist_offset;
3529 else if (strcmp (ic->name, "ICollection`1") == 0)
3530 offset = icollection_offset;
3531 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3532 offset = ienumerable_offset;
3533 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3534 offset = ireadonlylist_offset;
3535 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3536 offset = ireadonlycollection_offset;
3538 g_assert_not_reached ();
3539 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3540 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3545 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3546 if (interface_offsets_full [i] != -1) {
3547 interface_offsets_count ++;
3552 * We might get called multiple times:
3553 * - mono_class_init ()
3554 * - mono_class_setup_vtable ().
3555 * - mono_class_setup_interface_offsets ().
3556 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3557 * means we have to overwrite those when called from other places (#4440).
3559 if (class->interfaces_packed && !overwrite) {
3560 g_assert (class->interface_offsets_count == interface_offsets_count);
3564 class->interface_offsets_count = interface_offsets_count;
3565 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3566 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3567 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3568 #ifdef COMPRESSED_INTERFACE_BITMAP
3569 bitmap = g_malloc0 (bsize);
3571 bitmap = mono_class_alloc0 (class, bsize);
3573 for (i = 0; i < interface_offsets_count; i++) {
3574 int id = interfaces_full [i]->interface_id;
3575 bitmap [id >> 3] |= (1 << (id & 7));
3576 class->interfaces_packed [i] = interfaces_full [i];
3577 class->interface_offsets_packed [i] = interface_offsets_full [i];
3578 /*if (num_array_interfaces)
3579 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]);*/
3581 #ifdef COMPRESSED_INTERFACE_BITMAP
3582 i = mono_compress_bitmap (NULL, bitmap, bsize);
3583 class->interface_bitmap = mono_class_alloc0 (class, i);
3584 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3587 class->interface_bitmap = bitmap;
3592 g_free (interfaces_full);
3593 g_free (interface_offsets_full);
3594 g_free (array_interfaces);
3595 for (i = 0; i < class->idepth; i++) {
3596 ifaces = ifaces_array [i];
3598 g_ptr_array_free (ifaces, TRUE);
3600 g_free (ifaces_array);
3602 //printf ("JUST DONE: ");
3603 //print_implemented_interfaces (class);
3609 * Setup interface offsets for interfaces.
3611 * - class->max_interface_id
3612 * - class->interface_offsets_count
3613 * - class->interfaces_packed
3614 * - class->interface_offsets_packed
3615 * - class->interface_bitmap
3617 * This function can fail @class.
3620 mono_class_setup_interface_offsets (MonoClass *class)
3622 mono_loader_lock ();
3624 setup_interface_offsets (class, 0, FALSE);
3626 mono_loader_unlock ();
3629 /*Checks if @klass has @parent as one of it's parents type gtd
3633 * Bar<T> : Foo<Bar<Bar<T>>>
3637 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3639 klass = mono_class_get_generic_type_definition (klass);
3640 parent = mono_class_get_generic_type_definition (parent);
3641 mono_class_setup_supertypes (klass);
3642 mono_class_setup_supertypes (parent);
3644 return klass->idepth >= parent->idepth &&
3645 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3649 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3651 MonoGenericInst *ginst;
3653 if (!class->generic_class) {
3654 mono_class_setup_vtable_full (class, in_setup);
3655 return class->exception_type == 0;
3658 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3659 if (class->generic_class->container_class->exception_type) {
3660 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3664 ginst = class->generic_class->context.class_inst;
3665 for (i = 0; i < ginst->type_argc; ++i) {
3667 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3669 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3670 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3671 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3673 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3674 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3682 * mono_class_setup_vtable:
3684 * Creates the generic vtable of CLASS.
3685 * Initializes the following fields in MonoClass:
3688 * Plus all the fields initialized by setup_interface_offsets ().
3689 * If there is an error during vtable construction, class->exception_type is set.
3691 * LOCKING: Acquires the loader lock.
3694 mono_class_setup_vtable (MonoClass *class)
3696 mono_class_setup_vtable_full (class, NULL);
3700 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3702 MonoMethod **overrides;
3703 MonoGenericContext *context;
3711 if (MONO_CLASS_IS_INTERFACE (class)) {
3712 /* This sets method->slot for all methods if this is an interface */
3713 mono_class_setup_methods (class);
3717 if (class->exception_type)
3720 if (g_list_find (in_setup, class))
3723 mono_loader_lock ();
3725 if (class->vtable) {
3726 mono_loader_unlock ();
3730 mono_stats.generic_vtable_count ++;
3731 in_setup = g_list_prepend (in_setup, class);
3733 if (class->generic_class) {
3734 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3735 mono_loader_unlock ();
3736 g_list_remove (in_setup, class);
3740 context = mono_class_get_context (class);
3741 type_token = class->generic_class->container_class->type_token;
3743 context = (MonoGenericContext *) class->generic_container;
3744 type_token = class->type_token;
3747 if (image_is_dynamic (class->image)) {
3748 /* Generic instances can have zero method overrides without causing any harm.
3749 * This is true since we don't do layout all over again for them, we simply inflate
3750 * the layout of the parent.
3752 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3754 /* The following call fails if there are missing methods in the type */
3755 /* FIXME it's probably a good idea to avoid this for generic instances. */
3756 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3760 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3762 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3766 mono_loader_unlock ();
3767 g_list_remove (in_setup, class);
3772 #define DEBUG_INTERFACE_VTABLE_CODE 0
3773 #define TRACE_INTERFACE_VTABLE_CODE 0
3774 #define VERIFY_INTERFACE_VTABLE_CODE 0
3775 #define VTABLE_SELECTOR (1)
3777 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3778 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3779 if (!(VTABLE_SELECTOR)) break; \
3783 #define DEBUG_INTERFACE_VTABLE(stmt)
3786 #if TRACE_INTERFACE_VTABLE_CODE
3787 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3788 if (!(VTABLE_SELECTOR)) break; \
3792 #define TRACE_INTERFACE_VTABLE(stmt)
3795 #if VERIFY_INTERFACE_VTABLE_CODE
3796 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3797 if (!(VTABLE_SELECTOR)) break; \
3801 #define VERIFY_INTERFACE_VTABLE(stmt)
3805 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3807 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3811 GString *res = g_string_new ("");
3813 g_string_append_c (res, '(');
3814 for (i = 0; i < sig->param_count; ++i) {
3816 g_string_append_c (res, ',');
3817 mono_type_get_desc (res, sig->params [i], include_namespace);
3819 g_string_append (res, ")=>");
3820 if (sig->ret != NULL) {
3821 mono_type_get_desc (res, sig->ret, include_namespace);
3823 g_string_append (res, "NULL");
3826 g_string_free (res, FALSE);
3830 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3831 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3832 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3833 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3841 is_wcf_hack_disabled (void)
3843 static gboolean disabled;
3844 static gboolean inited = FALSE;
3846 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3853 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) {
3854 MonoMethodSignature *cmsig, *imsig;
3855 if (strcmp (im->name, cm->name) == 0) {
3856 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3857 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3860 if (! slot_is_empty) {
3861 if (require_newslot) {
3862 if (! interface_is_explicitly_implemented_by_class) {
3863 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3866 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3867 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3871 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3874 cmsig = mono_method_signature (cm);
3875 imsig = mono_method_signature (im);
3876 if (!cmsig || !imsig) {
3877 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3881 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3882 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3883 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3884 TRACE_INTERFACE_VTABLE (printf ("]"));
3887 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3888 /* CAS - SecurityAction.InheritanceDemand on interface */
3889 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3890 mono_secman_inheritancedemand_method (cm, im);
3893 if (mono_security_core_clr_enabled ())
3894 mono_security_core_clr_check_override (class, cm, im);
3896 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3897 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3898 char *body_name = mono_method_full_name (cm, TRUE);
3899 char *decl_name = mono_method_full_name (im, TRUE);
3900 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));
3908 MonoClass *ic = im->klass;
3909 const char *ic_name_space = ic->name_space;
3910 const char *ic_name = ic->name;
3913 if (! require_newslot) {
3914 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3917 if (cm->klass->rank == 0) {
3918 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3921 cmsig = mono_method_signature (cm);
3922 imsig = mono_method_signature (im);
3923 if (!cmsig || !imsig) {
3924 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3928 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3929 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3930 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3931 TRACE_INTERFACE_VTABLE (printf ("]"));
3934 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3935 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3938 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3939 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3942 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))) {
3943 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3947 subname = strstr (cm->name, ic_name_space);
3948 if (subname != cm->name) {
3949 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3952 subname += strlen (ic_name_space);
3953 if (subname [0] != '.') {
3954 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3958 if (strstr (subname, ic_name) != subname) {
3959 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3962 subname += strlen (ic_name);
3963 if (subname [0] != '.') {
3964 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3968 if (strcmp (subname, im->name) != 0) {
3969 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3973 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3974 /* CAS - SecurityAction.InheritanceDemand on interface */
3975 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3976 mono_secman_inheritancedemand_method (cm, im);
3979 if (mono_security_core_clr_enabled ())
3980 mono_security_core_clr_check_override (class, cm, im);
3982 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3983 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3984 char *body_name = mono_method_full_name (cm, TRUE);
3985 char *decl_name = mono_method_full_name (im, TRUE);
3986 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));
3996 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3998 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3999 MonoMethod *method = key;
4000 MonoMethod *override = value;
4001 MonoClass *method_class = mono_method_get_class (method);
4002 MonoClass *override_class = mono_method_get_class (override);
4004 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4005 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4006 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4009 print_overrides (GHashTable *override_map, const char *message) {
4011 printf ("Override map \"%s\" START:\n", message);
4012 g_hash_table_foreach (override_map, foreach_override, NULL);
4013 printf ("Override map \"%s\" END.\n", message);
4015 printf ("Override map \"%s\" EMPTY.\n", message);
4019 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4020 char *full_name = mono_type_full_name (&class->byval_arg);
4024 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4026 if (print_interfaces) {
4027 print_implemented_interfaces (class);
4028 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4031 if (class->parent) {
4032 parent_size = class->parent->vtable_size;
4036 for (i = 0; i < size; ++i) {
4037 MonoMethod *cm = vtable [i];
4038 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4039 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4041 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4049 #if VERIFY_INTERFACE_VTABLE_CODE
4051 mono_method_try_get_vtable_index (MonoMethod *method)
4053 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4054 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4055 if (imethod->declaring->is_generic)
4056 return imethod->declaring->slot;
4058 return method->slot;
4062 mono_class_verify_vtable (MonoClass *class)
4065 char *full_name = mono_type_full_name (&class->byval_arg);
4067 printf ("*** Verifying VTable of class '%s' \n", full_name);
4071 if (!class->methods)
4074 for (i = 0; i < class->method.count; ++i) {
4075 MonoMethod *cm = class->methods [i];
4078 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4082 full_name = mono_method_full_name (cm, TRUE);
4084 slot = mono_method_try_get_vtable_index (cm);
4086 if (slot >= class->vtable_size) {
4087 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4091 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4092 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4093 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4094 g_free (other_name);
4097 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4104 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4106 char *method_signature;
4109 for (index = 0; index < onum; ++index) {
4110 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4111 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4113 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4114 type_name = mono_type_full_name (&class->byval_arg);
4115 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4116 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4117 g_free (method_signature);
4119 mono_class_setup_methods (class);
4120 if (class->exception_type) {
4121 char *name = mono_type_get_full_name (class);
4122 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4126 for (index = 0; index < class->method.count; ++index) {
4127 MonoMethod *cm = class->methods [index];
4128 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4130 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4131 g_free (method_signature);
4136 mono_method_get_method_definition (MonoMethod *method)
4138 while (method->is_inflated)
4139 method = ((MonoMethodInflated*)method)->declaring;
4144 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4148 for (i = 0; i < onum; ++i) {
4149 MonoMethod *decl = overrides [i * 2];
4150 MonoMethod *body = overrides [i * 2 + 1];
4152 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4153 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4157 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4158 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4159 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4161 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4165 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4166 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4167 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4169 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4173 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4174 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4178 body = mono_method_get_method_definition (body);
4179 decl = mono_method_get_method_definition (decl);
4181 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4182 char *body_name = mono_method_full_name (body, TRUE);
4183 char *decl_name = mono_method_full_name (decl, TRUE);
4184 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));
4194 mono_class_need_stelemref_method (MonoClass *class)
4196 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4200 * LOCKING: this is supposed to be called with the loader lock held.
4203 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4207 MonoMethod **vtable;
4208 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4209 GPtrArray *ifaces = NULL;
4210 GHashTable *override_map = NULL;
4211 gboolean security_enabled = mono_security_enabled ();
4213 gpointer class_iter;
4214 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4215 int first_non_interface_slot;
4217 GSList *virt_methods = NULL, *l;
4218 int stelemref_slot = 0;
4223 if (overrides && !verify_class_overrides (class, overrides, onum))
4226 ifaces = mono_class_get_implemented_interfaces (class, &error);
4227 if (!mono_error_ok (&error)) {
4228 char *name = mono_type_get_full_name (class);
4229 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)));
4231 mono_error_cleanup (&error);
4233 } else if (ifaces) {
4234 for (i = 0; i < ifaces->len; i++) {
4235 MonoClass *ic = g_ptr_array_index (ifaces, i);
4236 max_vtsize += ic->method.count;
4238 g_ptr_array_free (ifaces, TRUE);
4242 if (class->parent) {
4243 mono_class_init (class->parent);
4244 mono_class_setup_vtable_full (class->parent, in_setup);
4246 if (class->parent->exception_type) {
4247 char *name = mono_type_get_full_name (class->parent);
4248 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4253 max_vtsize += class->parent->vtable_size;
4254 cur_slot = class->parent->vtable_size;
4257 max_vtsize += class->method.count;
4259 /*Array have a slot for stelemref*/
4260 if (mono_class_need_stelemref_method (class)) {
4261 stelemref_slot = cur_slot;
4266 vtable = alloca (sizeof (gpointer) * max_vtsize);
4267 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4269 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4271 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4272 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4275 max_iid = class->max_interface_id;
4276 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4278 /* Optimized version for generic instances */
4279 if (class->generic_class) {
4281 MonoClass *gklass = class->generic_class->container_class;
4284 mono_class_setup_vtable_full (gklass, in_setup);
4285 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4286 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4290 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4291 class->vtable_size = gklass->vtable_size;
4292 for (i = 0; i < gklass->vtable_size; ++i)
4293 if (gklass->vtable [i]) {
4294 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4295 if (!mono_error_ok (&error)) {
4296 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4297 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4299 mono_error_cleanup (&error);
4303 tmp [i]->slot = gklass->vtable [i]->slot;
4305 mono_memory_barrier ();
4306 class->vtable = tmp;
4308 /* Have to set method->slot for abstract virtual methods */
4309 if (class->methods && gklass->methods) {
4310 for (i = 0; i < class->method.count; ++i)
4311 if (class->methods [i]->slot == -1)
4312 class->methods [i]->slot = gklass->methods [i]->slot;
4318 if (class->parent && class->parent->vtable_size) {
4319 MonoClass *parent = class->parent;
4322 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4324 // Also inherit parent interface vtables, just as a starting point.
4325 // This is needed otherwise bug-77127.exe fails when the property methods
4326 // have different names in the iterface and the class, because for child
4327 // classes the ".override" information is not used anymore.
4328 for (i = 0; i < parent->interface_offsets_count; i++) {
4329 MonoClass *parent_interface = parent->interfaces_packed [i];
4330 int interface_offset = mono_class_interface_offset (class, parent_interface);
4331 /*FIXME this is now dead code as this condition will never hold true.
4332 Since interface offsets are inherited then the offset of an interface implemented
4333 by a parent will never be the out of it's vtable boundary.
4335 if (interface_offset >= parent->vtable_size) {
4336 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4339 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4340 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4341 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4342 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4343 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4344 parent_interface_offset + j, parent_interface_offset, j,
4345 interface_offset + j, interface_offset, j));
4352 /*Array have a slot for stelemref*/
4353 if (mono_class_need_stelemref_method (class)) {
4354 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4356 method->slot = stelemref_slot;
4358 g_assert (method->slot == stelemref_slot);
4360 vtable [stelemref_slot] = method;
4363 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4364 /* override interface methods */
4365 for (i = 0; i < onum; i++) {
4366 MonoMethod *decl = overrides [i*2];
4367 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4369 dslot = mono_method_get_vtable_slot (decl);
4371 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4375 dslot += mono_class_interface_offset (class, decl->klass);
4376 vtable [dslot] = overrides [i*2 + 1];
4377 vtable [dslot]->slot = dslot;
4379 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4381 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4383 if (mono_security_core_clr_enabled ())
4384 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4387 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4388 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4391 * Create a list of virtual methods to avoid calling
4392 * mono_class_get_virtual_methods () which is slow because of the metadata
4396 gpointer iter = NULL;
4399 virt_methods = NULL;
4400 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4401 virt_methods = g_slist_prepend (virt_methods, cm);
4403 if (class->exception_type)
4407 // Loop on all implemented interfaces...
4408 for (i = 0; i < class->interface_offsets_count; i++) {
4409 MonoClass *parent = class->parent;
4411 gboolean interface_is_explicitly_implemented_by_class;
4414 ic = class->interfaces_packed [i];
4415 ic_offset = mono_class_interface_offset (class, ic);
4417 mono_class_setup_methods (ic);
4418 if (ic->exception_type)
4421 // Check if this interface is explicitly implemented (instead of just inherited)
4422 if (parent != NULL) {
4423 int implemented_interfaces_index;
4424 interface_is_explicitly_implemented_by_class = FALSE;
4425 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4426 if (ic == class->interfaces [implemented_interfaces_index]) {
4427 interface_is_explicitly_implemented_by_class = TRUE;
4432 interface_is_explicitly_implemented_by_class = TRUE;
4435 // Loop on all interface methods...
4436 for (im_index = 0; im_index < ic->method.count; im_index++) {
4437 MonoMethod *im = ic->methods [im_index];
4438 int im_slot = ic_offset + im->slot;
4439 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4441 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4444 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4446 // If there is an explicit implementation, just use it right away,
4447 // otherwise look for a matching method
4448 if (override_im == NULL) {
4453 // First look for a suitable method among the class methods
4455 for (l = virt_methods; l; l = l->next) {
4457 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)));
4458 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4459 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4460 vtable [im_slot] = cm;
4461 /* Why do we need this? */
4466 TRACE_INTERFACE_VTABLE (printf ("\n"));
4467 if (class->exception_type) /*Might be set by check_interface_method_override*/
4471 // If the slot is still empty, look in all the inherited virtual methods...
4472 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4473 MonoClass *parent = class->parent;
4474 // Reverse order, so that last added methods are preferred
4475 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4476 MonoMethod *cm = parent->vtable [cm_index];
4478 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));
4479 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4480 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4481 vtable [im_slot] = cm;
4482 /* Why do we need this? */
4488 if (class->exception_type) /*Might be set by check_interface_method_override*/
4490 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4494 g_assert (vtable [im_slot] == override_im);
4499 // If the class is not abstract, check that all its interface slots are full.
4500 // The check is done here and not directly at the end of the loop above because
4501 // it can happen (for injected generic array interfaces) that the same slot is
4502 // processed multiple times (those interfaces have overlapping slots), and it
4503 // will not always be the first pass the one that fills the slot.
4504 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4505 for (i = 0; i < class->interface_offsets_count; i++) {
4509 ic = class->interfaces_packed [i];
4510 ic_offset = mono_class_interface_offset (class, ic);
4512 for (im_index = 0; im_index < ic->method.count; im_index++) {
4513 MonoMethod *im = ic->methods [im_index];
4514 int im_slot = ic_offset + im->slot;
4516 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4519 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4520 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4521 if (vtable [im_slot] == NULL) {
4522 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4529 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4531 for (l = virt_methods; l; l = l->next) {
4534 * If the method is REUSE_SLOT, we must check in the
4535 * base class for a method to override.
4537 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4539 for (k = class->parent; k ; k = k->parent) {
4544 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4545 MonoMethodSignature *cmsig, *m1sig;
4547 cmsig = mono_method_signature (cm);
4548 m1sig = mono_method_signature (m1);
4550 if (!cmsig || !m1sig) {
4551 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4555 if (!strcmp(cm->name, m1->name) &&
4556 mono_metadata_signature_equal (cmsig, m1sig)) {
4558 /* CAS - SecurityAction.InheritanceDemand */
4559 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4560 mono_secman_inheritancedemand_method (cm, m1);
4563 if (mono_security_core_clr_enabled ())
4564 mono_security_core_clr_check_override (class, cm, m1);
4566 slot = mono_method_get_vtable_slot (m1);
4570 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4571 char *body_name = mono_method_full_name (cm, TRUE);
4572 char *decl_name = mono_method_full_name (m1, TRUE);
4573 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));
4579 g_assert (cm->slot < max_vtsize);
4581 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4582 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4583 mono_method_full_name (m1, 1), m1,
4584 mono_method_full_name (cm, 1), cm));
4585 g_hash_table_insert (override_map, m1, cm);
4589 if (k->exception_type)
4599 /*Non final newslot methods must be given a non-interface vtable slot*/
4600 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4604 cm->slot = cur_slot++;
4606 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4607 vtable [cm->slot] = cm;
4610 /* override non interface methods */
4611 for (i = 0; i < onum; i++) {
4612 MonoMethod *decl = overrides [i*2];
4613 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4614 g_assert (decl->slot != -1);
4615 vtable [decl->slot] = overrides [i*2 + 1];
4616 overrides [i * 2 + 1]->slot = decl->slot;
4618 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4619 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4620 mono_method_full_name (decl, 1), decl,
4621 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4622 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4624 if (mono_security_core_clr_enabled ())
4625 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4630 * If a method occupies more than one place in the vtable, and it is
4631 * overriden, then change the other occurances too.
4636 for (i = 0; i < max_vtsize; ++i)
4638 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4640 cm = g_hash_table_lookup (override_map, vtable [i]);
4645 g_hash_table_destroy (override_map);
4646 override_map = NULL;
4649 g_slist_free (virt_methods);
4650 virt_methods = NULL;
4652 /* Ensure that all vtable slots are filled with concrete instance methods */
4653 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4654 for (i = 0; i < cur_slot; ++i) {
4655 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4656 char *type_name = mono_type_get_full_name (class);
4657 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4658 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));
4660 g_free (method_name);
4666 if (class->generic_class) {
4667 MonoClass *gklass = class->generic_class->container_class;
4669 mono_class_init (gklass);
4671 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4673 /* Check that the vtable_size value computed in mono_class_init () is correct */
4674 if (class->vtable_size)
4675 g_assert (cur_slot == class->vtable_size);
4676 class->vtable_size = cur_slot;
4679 /* Try to share the vtable with our parent. */
4680 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4681 mono_memory_barrier ();
4682 class->vtable = class->parent->vtable;
4684 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4685 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4686 mono_memory_barrier ();
4687 class->vtable = tmp;
4690 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4691 if (mono_print_vtable) {
4694 print_implemented_interfaces (class);
4696 for (i = 0; i <= max_iid; i++)
4697 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4700 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4701 class->vtable_size, icount);
4703 for (i = 0; i < cur_slot; ++i) {
4708 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4709 mono_method_full_name (cm, TRUE));
4715 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4716 class->name, max_iid);
4718 for (i = 0; i < class->interface_count; i++) {
4719 ic = class->interfaces [i];
4720 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4721 mono_class_interface_offset (class, ic),
4722 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4725 for (k = class->parent; k ; k = k->parent) {
4726 for (i = 0; i < k->interface_count; i++) {
4727 ic = k->interfaces [i];
4728 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4729 mono_class_interface_offset (class, ic),
4730 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4736 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4741 char *name = mono_type_get_full_name (class);
4742 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4745 g_hash_table_destroy (override_map);
4747 g_slist_free (virt_methods);
4752 * mono_method_get_vtable_slot:
4754 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4755 * LOCKING: Acquires the loader lock.
4757 * FIXME Use proper MonoError machinery here.
4760 mono_method_get_vtable_slot (MonoMethod *method)
4762 if (method->slot == -1) {
4763 mono_class_setup_vtable (method->klass);
4764 if (method->klass->exception_type)
4766 if (method->slot == -1) {
4770 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4771 g_assert (method->klass->generic_class);
4772 gklass = method->klass->generic_class->container_class;
4773 mono_class_setup_methods (method->klass);
4774 g_assert (method->klass->methods);
4775 for (i = 0; i < method->klass->method.count; ++i) {
4776 if (method->klass->methods [i] == method)
4779 g_assert (i < method->klass->method.count);
4780 g_assert (gklass->methods);
4781 method->slot = gklass->methods [i]->slot;
4783 g_assert (method->slot != -1);
4785 return method->slot;
4789 * mono_method_get_vtable_index:
4792 * Returns the index into the runtime vtable to access the method or,
4793 * in the case of a virtual generic method, the virtual generic method
4794 * thunk. Returns -1 on failure.
4796 * FIXME Use proper MonoError machinery here.
4799 mono_method_get_vtable_index (MonoMethod *method)
4801 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4802 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4803 if (imethod->declaring->is_generic)
4804 return mono_method_get_vtable_slot (imethod->declaring);
4806 return mono_method_get_vtable_slot (method);
4809 static MonoMethod *default_ghc = NULL;
4810 static MonoMethod *default_finalize = NULL;
4811 static int finalize_slot = -1;
4812 static int ghc_slot = -1;
4815 initialize_object_slots (MonoClass *class)
4820 if (class == mono_defaults.object_class) {
4821 mono_class_setup_vtable (class);
4822 for (i = 0; i < class->vtable_size; ++i) {
4823 MonoMethod *cm = class->vtable [i];
4825 if (!strcmp (cm->name, "GetHashCode"))
4827 else if (!strcmp (cm->name, "Finalize"))
4831 g_assert (ghc_slot > 0);
4832 default_ghc = class->vtable [ghc_slot];
4834 g_assert (finalize_slot > 0);
4835 default_finalize = class->vtable [finalize_slot];
4840 MonoMethod *array_method;
4842 } GenericArrayMethodInfo;
4844 static int generic_array_method_num = 0;
4845 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4848 generic_array_methods (MonoClass *class)
4850 int i, count_generic = 0;
4851 GList *list = NULL, *tmp;
4852 if (generic_array_method_num)
4853 return generic_array_method_num;
4854 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4855 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4856 for (i = 0; i < class->parent->method.count; i++) {
4857 MonoMethod *m = class->parent->methods [i];
4858 if (!strncmp (m->name, "InternalArray__", 15)) {
4860 list = g_list_prepend (list, m);
4863 list = g_list_reverse (list);
4864 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4866 for (tmp = list; tmp; tmp = tmp->next) {
4867 const char *mname, *iname;
4869 MonoMethod *m = tmp->data;
4870 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4871 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4873 generic_array_method_info [i].array_method = m;
4874 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4875 iname = "System.Collections.Generic.ICollection`1.";
4876 mname = m->name + 27;
4877 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4878 iname = "System.Collections.Generic.IEnumerable`1.";
4879 mname = m->name + 27;
4880 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4881 iname = "System.Collections.Generic.IReadOnlyList`1.";
4882 mname = m->name + strlen (ireadonlylist_prefix);
4883 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4884 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4885 mname = m->name + strlen (ireadonlycollection_prefix);
4886 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4887 iname = "System.Collections.Generic.IList`1.";
4888 mname = m->name + 15;
4890 g_assert_not_reached ();
4893 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4894 strcpy (name, iname);
4895 strcpy (name + strlen (iname), mname);
4896 generic_array_method_info [i].name = name;
4899 /*g_print ("array generic methods: %d\n", count_generic);*/
4901 generic_array_method_num = count_generic;
4903 return generic_array_method_num;
4907 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4909 MonoGenericContext tmp_context;
4912 tmp_context.class_inst = NULL;
4913 tmp_context.method_inst = iface->generic_class->context.class_inst;
4914 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4916 for (i = 0; i < generic_array_method_num; i++) {
4917 MonoMethod *m = generic_array_method_info [i].array_method;
4918 MonoMethod *inflated;
4920 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4921 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4926 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4928 int null_length = strlen ("(null)");
4929 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4930 char *s = mono_image_alloc (image, len);
4933 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4934 g_assert (result == len - 1);
4940 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4942 gpointer exception_data = NULL;
4944 switch (error->exception_type) {
4945 case MONO_EXCEPTION_TYPE_LOAD:
4946 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4949 case MONO_EXCEPTION_MISSING_METHOD:
4950 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4953 case MONO_EXCEPTION_MISSING_FIELD: {
4954 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4955 const char *class_name;
4958 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4960 class_name = error->klass->name;
4962 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4965 g_free ((void*)class_name);
4969 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4972 if (error->ref_only)
4973 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.";
4975 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4977 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4981 case MONO_EXCEPTION_BAD_IMAGE:
4982 exception_data = error->msg;
4986 g_assert_not_reached ();
4989 mono_class_set_failure (class, error->exception_type, exception_data);
4994 * @class: the class to initialize
4996 * Compute the instance_size, class_size and other infos that cannot be
4997 * computed at mono_class_get() time. Also compute vtable_size if possible.
4998 * Returns TRUE on success or FALSE if there was a problem in loading
4999 * the type (incorrect assemblies, missing assemblies, methods, etc).
5001 * LOCKING: Acquires the loader lock.
5004 mono_class_init (MonoClass *class)
5007 MonoCachedClassInfo cached_info;
5008 gboolean has_cached_info;
5012 /* Double-checking locking pattern */
5013 if (class->inited || class->exception_type)
5014 return class->exception_type == MONO_EXCEPTION_NONE;
5016 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5018 /* We do everything inside the lock to prevent races */
5019 mono_loader_lock ();
5021 if (class->inited || class->exception_type) {
5022 mono_loader_unlock ();
5023 /* Somebody might have gotten in before us */
5024 return class->exception_type == MONO_EXCEPTION_NONE;
5027 if (class->init_pending) {
5028 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5032 class->init_pending = 1;
5034 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5035 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5040 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5041 MonoClass *element_class = class->element_class;
5042 if (!element_class->inited)
5043 mono_class_init (element_class);
5044 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5045 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5050 /* CAS - SecurityAction.InheritanceDemand */
5051 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5052 mono_secman_inheritancedemand_class (class, class->parent);
5055 mono_stats.initialized_class_count++;
5057 if (class->generic_class && !class->generic_class->is_dynamic) {
5058 MonoClass *gklass = class->generic_class->container_class;
5060 mono_stats.generic_class_count++;
5062 class->method = gklass->method;
5063 class->field = gklass->field;
5065 mono_class_init (gklass);
5066 // FIXME: Why is this needed ?
5067 if (!gklass->exception_type)
5068 mono_class_setup_methods (gklass);
5069 if (gklass->exception_type) {
5070 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5074 if (MONO_CLASS_IS_INTERFACE (class))
5075 class->interface_id = mono_get_unique_iid (class);
5078 if (class->parent && !class->parent->inited)
5079 mono_class_init (class->parent);
5081 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5083 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5084 class->nested_classes_inited = TRUE;
5087 * Computes the size used by the fields, and their locations
5089 if (has_cached_info) {
5090 class->instance_size = cached_info.instance_size;
5091 class->sizes.class_size = cached_info.class_size;
5092 class->packing_size = cached_info.packing_size;
5093 class->min_align = cached_info.min_align;
5094 class->blittable = cached_info.blittable;
5095 class->has_references = cached_info.has_references;
5096 class->has_static_refs = cached_info.has_static_refs;
5097 class->no_special_static_fields = cached_info.no_special_static_fields;
5100 if (!class->size_inited){
5101 mono_class_setup_fields (class);
5102 if (class->exception_type || mono_loader_get_last_error ())
5106 /* Initialize arrays */
5108 class->method.count = 3 + (class->rank > 1? 2: 1);
5110 if (class->interface_count) {
5111 int count_generic = generic_array_methods (class);
5112 class->method.count += class->interface_count * count_generic;
5116 mono_class_setup_supertypes (class);
5119 initialize_object_slots (class);
5122 * Initialize the rest of the data without creating a generic vtable if possible.
5123 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5124 * also avoid computing a generic vtable.
5126 if (has_cached_info) {
5128 class->vtable_size = cached_info.vtable_size;
5129 class->has_finalize = cached_info.has_finalize;
5130 class->has_finalize_inited = TRUE;
5131 class->ghcimpl = cached_info.ghcimpl;
5132 class->has_cctor = cached_info.has_cctor;
5133 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5134 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5135 * The first slot if for array with.
5137 static int szarray_vtable_size[2] = { 0 };
5139 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5142 if (!szarray_vtable_size [slot]) {
5143 mono_class_setup_vtable (class);
5144 szarray_vtable_size [slot] = class->vtable_size;
5146 class->vtable_size = szarray_vtable_size[slot];
5148 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5149 MonoClass *gklass = class->generic_class->container_class;
5151 /* Generic instance case */
5152 class->ghcimpl = gklass->ghcimpl;
5153 class->has_cctor = gklass->has_cctor;
5155 mono_class_setup_vtable (gklass);
5156 if (gklass->exception_type) {
5157 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5161 class->vtable_size = gklass->vtable_size;
5165 /* ghcimpl is not currently used
5167 if (class->parent) {
5168 MonoMethod *cmethod = class->vtable [ghc_slot];
5169 if (cmethod->is_inflated)
5170 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5171 if (cmethod == default_ghc) {
5177 /* C# doesn't allow interfaces to have cctors */
5178 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5179 MonoMethod *cmethod = NULL;
5181 if (class->type_token) {
5182 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5183 /* The find_method function ignores the 'flags' argument */
5184 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5185 class->has_cctor = 1;
5187 mono_class_setup_methods (class);
5188 if (class->exception_type)
5191 for (i = 0; i < class->method.count; ++i) {
5192 MonoMethod *method = class->methods [i];
5193 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5194 (strcmp (".cctor", method->name) == 0)) {
5195 class->has_cctor = 1;
5203 if (class->parent) {
5204 int first_iface_slot;
5205 /* This will compute class->parent->vtable_size for some classes */
5206 mono_class_init (class->parent);
5207 if (class->parent->exception_type) {
5208 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5211 if (mono_loader_get_last_error ())
5213 if (!class->parent->vtable_size) {
5214 /* FIXME: Get rid of this somehow */
5215 mono_class_setup_vtable (class->parent);
5216 if (class->parent->exception_type) {
5217 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5220 if (mono_loader_get_last_error ())
5223 first_iface_slot = class->parent->vtable_size;
5224 if (mono_class_need_stelemref_method (class))
5226 setup_interface_offsets (class, first_iface_slot, TRUE);
5228 setup_interface_offsets (class, 0, TRUE);
5231 if (mono_security_core_clr_enabled ())
5232 mono_security_core_clr_check_inheritance (class);
5234 if (mono_loader_get_last_error ()) {
5235 if (class->exception_type == MONO_EXCEPTION_NONE) {
5236 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5238 mono_loader_clear_error ();
5241 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5242 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5247 /* Because of the double-checking locking pattern */
5248 mono_memory_barrier ();
5250 class->init_pending = 0;
5252 mono_loader_unlock ();
5254 if (mono_debugger_class_init_func)
5255 mono_debugger_class_init_func (class);
5257 return class->exception_type == MONO_EXCEPTION_NONE;
5261 * mono_class_has_finalizer:
5263 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5267 mono_class_has_finalizer (MonoClass *klass)
5269 MonoClass *class = klass;
5270 gboolean has_finalize = FALSE;
5272 if (klass->has_finalize_inited)
5273 return klass->has_finalize;
5275 /* Interfaces and valuetypes are not supposed to have finalizers */
5276 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5277 MonoMethod *cmethod = NULL;
5279 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5280 } else if (class->generic_class) {
5281 MonoClass *gklass = class->generic_class->container_class;
5283 has_finalize = mono_class_has_finalizer (gklass);
5284 } else if (class->parent && class->parent->has_finalize) {
5285 has_finalize = TRUE;
5287 if (class->parent) {
5289 * Can't search in metadata for a method named Finalize, because that
5290 * ignores overrides.
5292 mono_class_setup_vtable (class);
5293 if (class->exception_type || mono_loader_get_last_error ())
5296 cmethod = class->vtable [finalize_slot];
5300 g_assert (class->vtable_size > finalize_slot);
5302 if (class->parent) {
5303 if (cmethod->is_inflated)
5304 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5305 if (cmethod != default_finalize)
5306 has_finalize = TRUE;
5312 mono_image_lock (klass->image);
5314 if (!klass->has_finalize_inited) {
5315 klass->has_finalize = has_finalize ? 1 : 0;
5317 mono_memory_barrier ();
5318 klass->has_finalize_inited = TRUE;
5321 mono_image_unlock (klass->image);
5323 return klass->has_finalize;
5327 mono_is_corlib_image (MonoImage *image)
5329 /* FIXME: allow the dynamic case for our compilers and with full trust */
5330 if (image_is_dynamic (image))
5331 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5333 return image == mono_defaults.corlib;
5337 * LOCKING: this assumes the loader lock is held
5340 mono_class_setup_mono_type (MonoClass *class)
5342 const char *name = class->name;
5343 const char *nspace = class->name_space;
5344 gboolean is_corlib = mono_is_corlib_image (class->image);
5346 class->this_arg.byref = 1;
5347 class->this_arg.data.klass = class;
5348 class->this_arg.type = MONO_TYPE_CLASS;
5349 class->byval_arg.data.klass = class;
5350 class->byval_arg.type = MONO_TYPE_CLASS;
5352 if (is_corlib && !strcmp (nspace, "System")) {
5353 if (!strcmp (name, "ValueType")) {
5355 * do not set the valuetype bit for System.ValueType.
5356 * class->valuetype = 1;
5358 class->blittable = TRUE;
5359 } else if (!strcmp (name, "Enum")) {
5361 * do not set the valuetype bit for System.Enum.
5362 * class->valuetype = 1;
5364 class->valuetype = 0;
5365 class->enumtype = 0;
5366 } else if (!strcmp (name, "Object")) {
5367 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5368 } else if (!strcmp (name, "String")) {
5369 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5370 } else if (!strcmp (name, "TypedReference")) {
5371 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5375 if (class->valuetype) {
5376 int t = MONO_TYPE_VALUETYPE;
5378 if (is_corlib && !strcmp (nspace, "System")) {
5381 if (!strcmp (name, "Boolean")) {
5382 t = MONO_TYPE_BOOLEAN;
5383 } else if (!strcmp(name, "Byte")) {
5385 class->blittable = TRUE;
5389 if (!strcmp (name, "Char")) {
5394 if (!strcmp (name, "Double")) {
5396 class->blittable = TRUE;
5400 if (!strcmp (name, "Int32")) {
5402 class->blittable = TRUE;
5403 } else if (!strcmp(name, "Int16")) {
5405 class->blittable = TRUE;
5406 } else if (!strcmp(name, "Int64")) {
5408 class->blittable = TRUE;
5409 } else if (!strcmp(name, "IntPtr")) {
5411 class->blittable = TRUE;
5415 if (!strcmp (name, "Single")) {
5417 class->blittable = TRUE;
5418 } else if (!strcmp(name, "SByte")) {
5420 class->blittable = TRUE;
5424 if (!strcmp (name, "UInt32")) {
5426 class->blittable = TRUE;
5427 } else if (!strcmp(name, "UInt16")) {
5429 class->blittable = TRUE;
5430 } else if (!strcmp(name, "UInt64")) {
5432 class->blittable = TRUE;
5433 } else if (!strcmp(name, "UIntPtr")) {
5435 class->blittable = TRUE;
5439 if (!strcmp (name, "TypedReference")) {
5440 t = MONO_TYPE_TYPEDBYREF;
5441 class->blittable = TRUE;
5445 if (!strcmp (name, "Void")) {
5453 class->this_arg.type = class->byval_arg.type = t;
5456 if (MONO_CLASS_IS_INTERFACE (class))
5457 class->interface_id = mono_get_unique_iid (class);
5463 * COM initialization is delayed until needed.
5464 * However when a [ComImport] attribute is present on a type it will trigger
5465 * the initialization. This is not a problem unless the BCL being executed
5466 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5469 init_com_from_comimport (MonoClass *class)
5471 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5472 if (mono_security_core_clr_enabled ()) {
5473 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5474 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5475 /* but it can not be made available for application (i.e. user code) since all COM calls
5476 * are considered native calls. In this case we fail with a TypeLoadException (just like
5477 * Silverlight 2 does */
5478 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5483 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5485 #endif /*DISABLE_COM*/
5488 * LOCKING: this assumes the loader lock is held
5491 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5493 gboolean system_namespace;
5494 gboolean is_corlib = mono_is_corlib_image (class->image);
5496 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5498 /* if root of the hierarchy */
5499 if (system_namespace && !strcmp (class->name, "Object")) {
5500 class->parent = NULL;
5501 class->instance_size = sizeof (MonoObject);
5504 if (!strcmp (class->name, "<Module>")) {
5505 class->parent = NULL;
5506 class->instance_size = 0;
5510 if (!MONO_CLASS_IS_INTERFACE (class)) {
5511 /* Imported COM Objects always derive from __ComObject. */
5513 if (MONO_CLASS_IS_IMPORT (class)) {
5514 init_com_from_comimport (class);
5515 if (parent == mono_defaults.object_class)
5516 parent = mono_class_get_com_object_class ();
5520 /* set the parent to something useful and safe, but mark the type as broken */
5521 parent = mono_defaults.object_class;
5522 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5525 class->parent = parent;
5527 if (parent->generic_class && !parent->name) {
5529 * If the parent is a generic instance, we may get
5530 * called before it is fully initialized, especially
5531 * before it has its name.
5536 #ifndef DISABLE_REMOTING
5537 class->marshalbyref = parent->marshalbyref;
5538 class->contextbound = parent->contextbound;
5541 class->delegate = parent->delegate;
5543 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5544 mono_class_set_is_com_object (class);
5546 if (system_namespace) {
5547 #ifndef DISABLE_REMOTING
5548 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5549 class->marshalbyref = 1;
5551 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5552 class->contextbound = 1;
5554 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5555 class->delegate = 1;
5558 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5559 (strcmp (class->parent->name_space, "System") == 0)))
5560 class->valuetype = 1;
5561 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5562 class->valuetype = class->enumtype = 1;
5564 /*class->enumtype = class->parent->enumtype; */
5566 /* initialize com types if COM interfaces are present */
5568 if (MONO_CLASS_IS_IMPORT (class))
5569 init_com_from_comimport (class);
5571 class->parent = NULL;
5577 * mono_class_setup_supertypes:
5580 * Build the data structure needed to make fast type checks work.
5581 * This currently sets two fields in @class:
5582 * - idepth: distance between @class and System.Object in the type
5584 * - supertypes: array of classes: each element has a class in the hierarchy
5585 * starting from @class up to System.Object
5587 * LOCKING: This function is atomic, in case of contention we waste memory.
5590 mono_class_setup_supertypes (MonoClass *class)
5593 MonoClass **supertypes;
5595 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5599 if (class->parent && !class->parent->supertypes)
5600 mono_class_setup_supertypes (class->parent);
5602 class->idepth = class->parent->idepth + 1;
5606 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5607 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5609 if (class->parent) {
5610 supertypes [class->idepth - 1] = class;
5611 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5613 supertypes [0] = class;
5616 mono_atomic_store_release (&class->supertypes, supertypes);
5620 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5622 MonoClass *gtd = (MonoClass*)user_data;
5623 /* Only try to fix generic instances of @gtd */
5624 if (gclass->generic_class->container_class != gtd)
5627 /* Check if the generic instance has no parent. */
5628 if (gtd->parent && !gclass->parent)
5629 mono_generic_class_setup_parent (gclass, gtd);
5635 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5637 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5638 mono_error_set_type_load_class (error, class, msg);
5642 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5644 MonoLoaderError *lerror = mono_loader_get_last_error ();
5647 set_failure_from_loader_error (class, lerror);
5648 mono_error_set_from_loader_error (error);
5652 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5653 mono_error_set_type_load_class (error, class, msg);
5658 * mono_class_create_from_typedef:
5659 * @image: image where the token is valid
5660 * @type_token: typedef token
5661 * @error: used to return any error found while creating the type
5663 * Create the MonoClass* representing the specified type token.
5664 * @type_token must be a TypeDef token.
5666 * FIXME: don't return NULL on failure, just the the caller figure it out.
5669 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5671 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5672 MonoClass *class, *parent = NULL;
5673 guint32 cols [MONO_TYPEDEF_SIZE];
5674 guint32 cols_next [MONO_TYPEDEF_SIZE];
5675 guint tidx = mono_metadata_token_index (type_token);
5676 MonoGenericContext *context = NULL;
5677 const char *name, *nspace;
5679 MonoClass **interfaces;
5680 guint32 field_last, method_last;
5681 guint32 nesting_tokeen;
5683 mono_error_init (error);
5685 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5686 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5687 g_assert (!mono_loader_get_last_error ());
5691 mono_loader_lock ();
5693 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5694 mono_loader_unlock ();
5695 g_assert (!mono_loader_get_last_error ());
5699 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5701 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5702 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5704 class = mono_image_alloc0 (image, sizeof (MonoClass));
5707 class->name_space = nspace;
5709 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5711 class->image = image;
5712 class->type_token = type_token;
5713 class->flags = cols [MONO_TYPEDEF_FLAGS];
5715 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5717 classes_size += sizeof (MonoClass);
5720 * Check whether we're a generic type definition.
5722 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5723 if (class->generic_container) {
5724 class->is_generic = 1;
5725 class->generic_container->owner.klass = class;
5726 context = &class->generic_container->context;
5729 if (class->generic_container)
5730 enable_gclass_recording ();
5732 if (cols [MONO_TYPEDEF_EXTENDS]) {
5734 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5736 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5737 /*WARNING: this must satisfy mono_metadata_type_hash*/
5738 class->this_arg.byref = 1;
5739 class->this_arg.data.klass = class;
5740 class->this_arg.type = MONO_TYPE_CLASS;
5741 class->byval_arg.data.klass = class;
5742 class->byval_arg.type = MONO_TYPE_CLASS;
5744 parent = mono_class_get_checked (image, parent_token, error);
5745 if (parent && context) /* Always inflate */
5746 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5748 if (parent == NULL) {
5749 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5750 goto parent_failure;
5753 for (tmp = parent; tmp; tmp = tmp->parent) {
5755 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5756 goto parent_failure;
5758 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5759 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5760 goto parent_failure;
5765 mono_class_setup_parent (class, parent);
5767 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5768 mono_class_setup_mono_type (class);
5770 if (class->generic_container)
5771 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5774 * This might access class->byval_arg for recursion generated by generic constraints,
5775 * so it has to come after setup_mono_type ().
5777 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5778 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5779 if (!mono_error_ok (error)) {
5780 /*FIXME implement a mono_class_set_failure_from_mono_error */
5781 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5782 mono_loader_unlock ();
5783 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5784 g_assert (!mono_loader_get_last_error ());
5789 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5793 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5797 class->cast_class = class->element_class = class;
5799 if (!class->enumtype) {
5800 if (!mono_metadata_interfaces_from_typedef_full (
5801 image, type_token, &interfaces, &icount, FALSE, context)){
5802 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5803 mono_loader_unlock ();
5804 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5808 class->interfaces = interfaces;
5809 class->interface_count = icount;
5810 class->interfaces_inited = 1;
5813 /*g_print ("Load class %s\n", name);*/
5816 * Compute the field and method lists
5818 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5819 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5821 if (tt->rows > tidx){
5822 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5823 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5824 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5826 field_last = image->tables [MONO_TABLE_FIELD].rows;
5827 method_last = image->tables [MONO_TABLE_METHOD].rows;
5830 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5831 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5832 class->field.count = field_last - class->field.first;
5834 class->field.count = 0;
5836 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5837 class->method.count = method_last - class->method.first;
5839 class->method.count = 0;
5841 /* reserve space to store vector pointer in arrays */
5842 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5843 class->instance_size += 2 * sizeof (gpointer);
5844 g_assert (class->field.count == 0);
5847 if (class->enumtype) {
5848 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5849 if (!enum_basetype) {
5850 /*set it to a default value as the whole runtime can't handle this to be null*/
5851 class->cast_class = class->element_class = mono_defaults.int32_class;
5852 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5853 mono_loader_unlock ();
5854 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5855 g_assert (!mono_loader_get_last_error ());
5858 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5862 * If we're a generic type definition, load the constraints.
5863 * We must do this after the class has been constructed to make certain recursive scenarios
5866 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5867 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)));
5868 mono_loader_unlock ();
5869 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5870 g_assert (!mono_loader_get_last_error ());
5874 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5875 if (!strncmp (name, "Vector", 6))
5876 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");
5879 mono_loader_unlock ();
5881 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5882 g_assert (!mono_loader_get_last_error ());
5887 mono_class_setup_mono_type (class);
5888 mono_loader_unlock ();
5889 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5890 g_assert (!mono_loader_get_last_error ());
5894 /** is klass Nullable<T>? */
5896 mono_class_is_nullable (MonoClass *klass)
5898 return klass->generic_class != NULL &&
5899 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5903 /** if klass is T? return T */
5905 mono_class_get_nullable_param (MonoClass *klass)
5907 g_assert (mono_class_is_nullable (klass));
5908 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5912 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5916 MonoGenericClass *gclass = klass->generic_class;
5918 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5919 if (!mono_error_ok (&error)) {
5920 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5921 klass->parent = mono_defaults.object_class;
5922 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5923 mono_error_cleanup (&error);
5927 mono_class_setup_parent (klass, klass->parent);
5929 if (klass->enumtype) {
5930 klass->cast_class = gtd->cast_class;
5931 klass->element_class = gtd->element_class;
5937 * Create the `MonoClass' for an instantiation of a generic type.
5938 * We only do this if we actually need it.
5941 mono_generic_class_get_class (MonoGenericClass *gclass)
5943 MonoClass *klass, *gklass;
5945 if (gclass->cached_class)
5946 return gclass->cached_class;
5948 mono_loader_lock ();
5949 if (gclass->cached_class) {
5950 mono_loader_unlock ();
5951 return gclass->cached_class;
5954 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5956 gklass = gclass->container_class;
5958 if (record_gclass_instantiation > 0)
5959 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5961 if (gklass->nested_in) {
5962 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5963 klass->nested_in = gklass->nested_in;
5966 klass->name = gklass->name;
5967 klass->name_space = gklass->name_space;
5969 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5971 klass->image = gklass->image;
5972 klass->flags = gklass->flags;
5973 klass->type_token = gklass->type_token;
5974 klass->field.count = gklass->field.count;
5976 klass->is_inflated = 1;
5977 klass->generic_class = gclass;
5979 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5980 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5981 klass->this_arg.byref = TRUE;
5982 klass->enumtype = gklass->enumtype;
5983 klass->valuetype = gklass->valuetype;
5985 klass->cast_class = klass->element_class = klass;
5987 if (mono_class_is_nullable (klass))
5988 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5991 * We're not interested in the nested classes of a generic instance.
5992 * We use the generic type definition to look for nested classes.
5995 mono_generic_class_setup_parent (klass, gklass);
5997 if (gclass->is_dynamic) {
6000 mono_class_setup_supertypes (klass);
6002 if (klass->enumtype) {
6004 * For enums, gklass->fields might not been set, but instance_size etc. is
6005 * already set in mono_reflection_create_internal_class (). For non-enums,
6006 * these will be computed normally in mono_class_layout_fields ().
6008 klass->instance_size = gklass->instance_size;
6009 klass->sizes.class_size = gklass->sizes.class_size;
6010 mono_memory_barrier ();
6011 klass->size_inited = 1;
6015 mono_memory_barrier ();
6016 gclass->cached_class = klass;
6018 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6020 inflated_classes ++;
6021 inflated_classes_size += sizeof (MonoClass);
6023 mono_loader_unlock ();
6029 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6031 MonoClass *klass, **ptr;
6033 MonoGenericContainer *container = mono_generic_param_owner (param);
6037 image = mono_defaults.corlib;
6039 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6040 classes_size += sizeof (MonoClass);
6043 klass->name = pinfo->name;
6045 int n = mono_generic_param_num (param);
6046 klass->name = mono_image_alloc0 (image, 16);
6047 sprintf ((char*)klass->name, "%d", n);
6052 MonoMethod *omethod = container->owner.method;
6053 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6055 MonoClass *oklass = container->owner.klass;
6056 klass->name_space = oklass ? oklass->name_space : "";
6059 klass->name_space = "";
6062 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6066 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6070 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6071 klass->parent = pinfo->constraints [0];
6073 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6074 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6076 klass->parent = mono_defaults.object_class;
6079 if (count - pos > 0) {
6080 klass->interface_count = count - pos;
6081 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6082 klass->interfaces_inited = TRUE;
6083 for (i = pos; i < count; i++)
6084 klass->interfaces [i - pos] = pinfo->constraints [i];
6087 klass->image = image;
6089 klass->inited = TRUE;
6090 klass->cast_class = klass->element_class = klass;
6091 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6093 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6094 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6095 klass->this_arg.byref = TRUE;
6097 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6098 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6100 /*Init these fields to sane values*/
6101 klass->min_align = 1;
6102 klass->instance_size = sizeof (gpointer);
6103 mono_memory_barrier ();
6104 klass->size_inited = 1;
6106 mono_class_setup_supertypes (klass);
6108 if (count - pos > 0) {
6109 mono_class_setup_vtable (klass->parent);
6110 if (klass->parent->exception_type)
6111 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6113 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6119 #define FAST_CACHE_SIZE 16
6122 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6124 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6125 MonoImage *image = param->image;
6130 if (n < FAST_CACHE_SIZE) {
6132 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6134 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6136 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6137 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6142 * LOCKING: Acquires the loader lock.
6145 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6147 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6148 MonoImage *image = param->image;
6153 if (n < FAST_CACHE_SIZE) {
6155 /* No locking needed */
6156 if (!image->mvar_cache_fast)
6157 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6158 image->mvar_cache_fast [n] = klass;
6160 if (!image->var_cache_fast)
6161 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6162 image->var_cache_fast [n] = klass;
6166 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6168 mono_image_lock (image);
6169 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6171 ht = g_hash_table_new (NULL, NULL);
6172 mono_memory_barrier ();
6174 image->mvar_cache_slow = ht;
6176 image->var_cache_slow = ht;
6178 mono_image_unlock (image);
6181 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6185 * LOCKING: Acquires the loader lock.
6188 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6190 MonoGenericContainer *container = mono_generic_param_owner (param);
6191 MonoGenericParamInfo *pinfo;
6194 mono_loader_lock ();
6197 pinfo = mono_generic_param_info (param);
6198 if (pinfo->pklass) {
6199 mono_loader_unlock ();
6200 return pinfo->pklass;
6206 klass = get_anon_gparam_class (param, is_mvar);
6208 mono_loader_unlock ();
6213 if (!image && container) {
6215 MonoMethod *method = container->owner.method;
6216 image = (method && method->klass) ? method->klass->image : NULL;
6218 MonoClass *klass = container->owner.klass;
6219 // FIXME: 'klass' should not be null
6220 // But, monodis creates GenericContainers without associating a owner to it
6221 image = klass ? klass->image : NULL;
6225 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6227 mono_memory_barrier ();
6230 pinfo->pklass = klass;
6232 set_anon_gparam_class (param, is_mvar, klass);
6234 mono_loader_unlock ();
6236 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6237 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6243 mono_ptr_class_get (MonoType *type)
6246 MonoClass *el_class;
6250 el_class = mono_class_from_mono_type (type);
6251 image = el_class->image;
6253 mono_loader_lock ();
6255 if (!image->ptr_cache)
6256 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6258 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6259 mono_loader_unlock ();
6262 result = mono_image_alloc0 (image, sizeof (MonoClass));
6264 classes_size += sizeof (MonoClass);
6266 result->parent = NULL; /* no parent for PTR types */
6267 result->name_space = el_class->name_space;
6268 name = g_strdup_printf ("%s*", el_class->name);
6269 result->name = mono_image_strdup (image, name);
6272 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6274 result->image = el_class->image;
6275 result->inited = TRUE;
6276 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6277 /* Can pointers get boxed? */
6278 result->instance_size = sizeof (gpointer);
6279 result->cast_class = result->element_class = el_class;
6280 result->blittable = TRUE;
6282 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6283 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6284 result->this_arg.byref = TRUE;
6286 mono_class_setup_supertypes (result);
6288 g_hash_table_insert (image->ptr_cache, el_class, result);
6290 mono_loader_unlock ();
6292 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6298 mono_fnptr_class_get (MonoMethodSignature *sig)
6301 static GHashTable *ptr_hash = NULL;
6303 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6305 mono_loader_lock ();
6308 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6310 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6311 mono_loader_unlock ();
6314 result = g_new0 (MonoClass, 1);
6316 result->parent = NULL; /* no parent for PTR types */
6317 result->name_space = "System";
6318 result->name = "MonoFNPtrFakeClass";
6320 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6322 result->image = mono_defaults.corlib; /* need to fix... */
6323 result->inited = TRUE;
6324 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6325 /* Can pointers get boxed? */
6326 result->instance_size = sizeof (gpointer);
6327 result->cast_class = result->element_class = result;
6328 result->blittable = TRUE;
6330 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6331 result->this_arg.data.method = result->byval_arg.data.method = sig;
6332 result->this_arg.byref = TRUE;
6333 result->blittable = TRUE;
6335 mono_class_setup_supertypes (result);
6337 g_hash_table_insert (ptr_hash, sig, result);
6339 mono_loader_unlock ();
6341 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6347 mono_class_from_mono_type (MonoType *type)
6349 switch (type->type) {
6350 case MONO_TYPE_OBJECT:
6351 return type->data.klass? type->data.klass: mono_defaults.object_class;
6352 case MONO_TYPE_VOID:
6353 return type->data.klass? type->data.klass: mono_defaults.void_class;
6354 case MONO_TYPE_BOOLEAN:
6355 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6356 case MONO_TYPE_CHAR:
6357 return type->data.klass? type->data.klass: mono_defaults.char_class;
6359 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6361 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6363 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6365 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6367 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6369 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6371 return type->data.klass? type->data.klass: mono_defaults.int_class;
6373 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6375 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6377 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6379 return type->data.klass? type->data.klass: mono_defaults.single_class;
6381 return type->data.klass? type->data.klass: mono_defaults.double_class;
6382 case MONO_TYPE_STRING:
6383 return type->data.klass? type->data.klass: mono_defaults.string_class;
6384 case MONO_TYPE_TYPEDBYREF:
6385 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6386 case MONO_TYPE_ARRAY:
6387 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6389 return mono_ptr_class_get (type->data.type);
6390 case MONO_TYPE_FNPTR:
6391 return mono_fnptr_class_get (type->data.method);
6392 case MONO_TYPE_SZARRAY:
6393 return mono_array_class_get (type->data.klass, 1);
6394 case MONO_TYPE_CLASS:
6395 case MONO_TYPE_VALUETYPE:
6396 return type->data.klass;
6397 case MONO_TYPE_GENERICINST:
6398 return mono_generic_class_get_class (type->data.generic_class);
6400 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6401 case MONO_TYPE_MVAR:
6402 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6404 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6405 g_assert_not_reached ();
6412 * mono_type_retrieve_from_typespec
6413 * @image: context where the image is created
6414 * @type_spec: typespec token
6415 * @context: the generic context used to evaluate generic instantiations in
6418 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6420 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6422 *did_inflate = FALSE;
6427 if (context && (context->class_inst || context->method_inst)) {
6428 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6430 if (!mono_error_ok (error)) {
6431 g_assert (!mono_loader_get_last_error ());
6437 *did_inflate = TRUE;
6444 * mono_class_create_from_typespec
6445 * @image: context where the image is created
6446 * @type_spec: typespec token
6447 * @context: the generic context used to evaluate generic instantiations in
6450 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6453 gboolean inflated = FALSE;
6454 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6455 if (!mono_error_ok (error))
6457 ret = mono_class_from_mono_type (t);
6459 mono_metadata_free_type (t);
6464 * mono_bounded_array_class_get:
6465 * @element_class: element class
6466 * @rank: the dimension of the array class
6467 * @bounded: whenever the array has non-zero bounds
6469 * Returns: a class object describing the array with element type @element_type and
6473 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6477 MonoClass *parent = NULL;
6478 GSList *list, *rootlist = NULL;
6481 gboolean corlib_type = FALSE;
6483 g_assert (rank <= 255);
6486 /* bounded only matters for one-dimensional arrays */
6489 image = eclass->image;
6491 if (rank == 1 && !bounded) {
6493 * This case is very frequent not just during compilation because of calls
6494 * from mono_class_from_mono_type (), mono_array_new (),
6495 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6497 mono_mutex_lock (&image->szarray_cache_lock);
6498 if (!image->szarray_cache)
6499 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6500 class = g_hash_table_lookup (image->szarray_cache, eclass);
6501 mono_mutex_unlock (&image->szarray_cache_lock);
6505 mono_loader_lock ();
6507 mono_loader_lock ();
6509 if (!image->array_cache)
6510 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6512 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6513 for (; list; list = list->next) {
6515 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6516 mono_loader_unlock ();
6523 /* for the building corlib use System.Array from it */
6524 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6525 parent = mono_class_from_name (image, "System", "Array");
6528 parent = mono_defaults.array_class;
6529 if (!parent->inited)
6530 mono_class_init (parent);
6533 class = mono_image_alloc0 (image, sizeof (MonoClass));
6535 class->image = image;
6536 class->name_space = eclass->name_space;
6537 nsize = strlen (eclass->name);
6538 name = g_malloc (nsize + 2 + rank + 1);
6539 memcpy (name, eclass->name, nsize);
6542 memset (name + nsize + 1, ',', rank - 1);
6544 name [nsize + rank] = '*';
6545 name [nsize + rank + bounded] = ']';
6546 name [nsize + rank + bounded + 1] = 0;
6547 class->name = mono_image_strdup (image, name);
6550 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6552 classes_size += sizeof (MonoClass);
6554 class->type_token = 0;
6555 /* all arrays are marked serializable and sealed, bug #42779 */
6556 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6557 class->parent = parent;
6558 class->instance_size = mono_class_instance_size (class->parent);
6560 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6561 /*Arrays of those two types are invalid.*/
6562 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6563 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6564 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6565 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6566 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6568 /* element_size -1 is ok as this is not an instantitable type*/
6569 class->sizes.element_size = -1;
6571 class->sizes.element_size = mono_class_array_element_size (eclass);
6573 mono_class_setup_supertypes (class);
6575 if (eclass->generic_class)
6576 mono_class_init (eclass);
6577 if (!eclass->size_inited)
6578 mono_class_setup_fields (eclass);
6579 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6580 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6582 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6586 if (eclass->enumtype)
6587 class->cast_class = eclass->element_class;
6589 class->cast_class = eclass;
6591 switch (class->cast_class->byval_arg.type) {
6593 class->cast_class = mono_defaults.byte_class;
6596 class->cast_class = mono_defaults.int16_class;
6599 #if SIZEOF_VOID_P == 4
6603 class->cast_class = mono_defaults.int32_class;
6606 #if SIZEOF_VOID_P == 8
6610 class->cast_class = mono_defaults.int64_class;
6614 class->element_class = eclass;
6616 if ((rank > 1) || bounded) {
6617 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6618 class->byval_arg.type = MONO_TYPE_ARRAY;
6619 class->byval_arg.data.array = at;
6620 at->eklass = eclass;
6622 /* FIXME: complete.... */
6624 class->byval_arg.type = MONO_TYPE_SZARRAY;
6625 class->byval_arg.data.klass = eclass;
6627 class->this_arg = class->byval_arg;
6628 class->this_arg.byref = 1;
6633 class->generic_container = eclass->generic_container;
6635 if (rank == 1 && !bounded) {
6636 MonoClass *prev_class;
6638 mono_mutex_lock (&image->szarray_cache_lock);
6639 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6641 /* Someone got in before us */
6644 g_hash_table_insert (image->szarray_cache, eclass, class);
6645 mono_mutex_unlock (&image->szarray_cache_lock);
6647 list = g_slist_append (rootlist, class);
6648 g_hash_table_insert (image->array_cache, eclass, list);
6651 mono_loader_unlock ();
6653 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6659 * mono_array_class_get:
6660 * @element_class: element class
6661 * @rank: the dimension of the array class
6663 * Returns: a class object describing the array with element type @element_type and
6667 mono_array_class_get (MonoClass *eclass, guint32 rank)
6669 return mono_bounded_array_class_get (eclass, rank, FALSE);
6673 * mono_class_instance_size:
6676 * Returns: the size of an object instance
6679 mono_class_instance_size (MonoClass *klass)
6681 if (!klass->size_inited)
6682 mono_class_init (klass);
6684 return klass->instance_size;
6688 * mono_class_min_align:
6691 * Returns: minimm alignment requirements
6694 mono_class_min_align (MonoClass *klass)
6696 if (!klass->size_inited)
6697 mono_class_init (klass);
6699 return klass->min_align;
6703 * mono_class_value_size:
6706 * This function is used for value types, and return the
6707 * space and the alignment to store that kind of value object.
6709 * Returns: the size of a value of kind @klass
6712 mono_class_value_size (MonoClass *klass, guint32 *align)
6716 /* fixme: check disable, because we still have external revereces to
6717 * mscorlib and Dummy Objects
6719 /*g_assert (klass->valuetype);*/
6721 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6724 *align = klass->min_align;
6730 * mono_class_data_size:
6733 * Returns: the size of the static class data
6736 mono_class_data_size (MonoClass *klass)
6739 mono_class_init (klass);
6740 /* This can happen with dynamically created types */
6741 if (!klass->fields_inited)
6742 mono_class_setup_fields_locking (klass);
6744 /* in arrays, sizes.class_size is unioned with element_size
6745 * and arrays have no static fields
6749 return klass->sizes.class_size;
6753 * Auxiliary routine to mono_class_get_field
6755 * Takes a field index instead of a field token.
6757 static MonoClassField *
6758 mono_class_get_field_idx (MonoClass *class, int idx)
6760 mono_class_setup_fields_locking (class);
6761 if (class->exception_type)
6765 if (class->image->uncompressed_metadata) {
6767 * class->field.first points to the FieldPtr table, while idx points into the
6768 * Field table, so we have to do a search.
6770 /*FIXME this is broken for types with multiple fields with the same name.*/
6771 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6774 for (i = 0; i < class->field.count; ++i)
6775 if (mono_field_get_name (&class->fields [i]) == name)
6776 return &class->fields [i];
6777 g_assert_not_reached ();
6779 if (class->field.count) {
6780 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6781 return &class->fields [idx - class->field.first];
6785 class = class->parent;
6791 * mono_class_get_field:
6792 * @class: the class to lookup the field.
6793 * @field_token: the field token
6795 * Returns: A MonoClassField representing the type and offset of
6796 * the field, or a NULL value if the field does not belong to this
6800 mono_class_get_field (MonoClass *class, guint32 field_token)
6802 int idx = mono_metadata_token_index (field_token);
6804 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6806 return mono_class_get_field_idx (class, idx - 1);
6810 * mono_class_get_field_from_name:
6811 * @klass: the class to lookup the field.
6812 * @name: the field name
6814 * Search the class @klass and it's parents for a field with the name @name.
6816 * Returns: the MonoClassField pointer of the named field or NULL
6819 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6821 return mono_class_get_field_from_name_full (klass, name, NULL);
6825 * mono_class_get_field_from_name_full:
6826 * @klass: the class to lookup the field.
6827 * @name: the field name
6828 * @type: the type of the fields. This optional.
6830 * Search the class @klass and it's parents for a field with the name @name and type @type.
6832 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6833 * of its generic type definition.
6835 * Returns: the MonoClassField pointer of the named field or NULL
6838 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6842 mono_class_setup_fields_locking (klass);
6843 if (klass->exception_type)
6847 for (i = 0; i < klass->field.count; ++i) {
6848 MonoClassField *field = &klass->fields [i];
6850 if (strcmp (name, mono_field_get_name (field)) != 0)
6854 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6855 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6860 klass = klass->parent;
6866 * mono_class_get_field_token:
6867 * @field: the field we need the token of
6869 * Get the token of a field. Note that the tokesn is only valid for the image
6870 * the field was loaded from. Don't use this function for fields in dynamic types.
6872 * Returns: the token representing the field in the image it was loaded from.
6875 mono_class_get_field_token (MonoClassField *field)
6877 MonoClass *klass = field->parent;
6880 mono_class_setup_fields_locking (klass);
6885 for (i = 0; i < klass->field.count; ++i) {
6886 if (&klass->fields [i] == field) {
6887 int idx = klass->field.first + i + 1;
6889 if (klass->image->uncompressed_metadata)
6890 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6891 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6894 klass = klass->parent;
6897 g_assert_not_reached ();
6902 mono_field_get_index (MonoClassField *field)
6904 int index = field - field->parent->fields;
6906 g_assert (index >= 0 && index < field->parent->field.count);
6912 * mono_class_get_field_default_value:
6914 * Return the default value of the field as a pointer into the metadata blob.
6917 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6920 guint32 constant_cols [MONO_CONSTANT_SIZE];
6922 MonoClass *klass = field->parent;
6924 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6926 if (!klass->ext || !klass->ext->field_def_values) {
6927 MonoFieldDefaultValue *def_values;
6929 mono_class_alloc_ext (klass);
6931 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6933 mono_image_lock (klass->image);
6934 mono_memory_barrier ();
6935 if (!klass->ext->field_def_values)
6936 klass->ext->field_def_values = def_values;
6937 mono_image_unlock (klass->image);
6940 field_index = mono_field_get_index (field);
6942 if (!klass->ext->field_def_values [field_index].data) {
6943 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6947 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6949 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6950 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6951 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6954 *def_type = klass->ext->field_def_values [field_index].def_type;
6955 return klass->ext->field_def_values [field_index].data;
6959 mono_property_get_index (MonoProperty *prop)
6961 int index = prop - prop->parent->ext->properties;
6963 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6969 * mono_class_get_property_default_value:
6971 * Return the default value of the field as a pointer into the metadata blob.
6974 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6977 guint32 constant_cols [MONO_CONSTANT_SIZE];
6978 MonoClass *klass = property->parent;
6980 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6982 * We don't cache here because it is not used by C# so it's quite rare, but
6983 * we still do the lookup in klass->ext because that is where the data
6984 * is stored for dynamic assemblies.
6987 if (image_is_dynamic (klass->image)) {
6988 int prop_index = mono_property_get_index (property);
6989 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6990 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6991 return klass->ext->prop_def_values [prop_index].data;
6995 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6999 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7000 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7001 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7005 mono_class_get_event_token (MonoEvent *event)
7007 MonoClass *klass = event->parent;
7012 for (i = 0; i < klass->ext->event.count; ++i) {
7013 if (&klass->ext->events [i] == event)
7014 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7017 klass = klass->parent;
7020 g_assert_not_reached ();
7025 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7029 gpointer iter = NULL;
7030 while ((p = mono_class_get_properties (klass, &iter))) {
7031 if (! strcmp (name, p->name))
7034 klass = klass->parent;
7040 mono_class_get_property_token (MonoProperty *prop)
7042 MonoClass *klass = prop->parent;
7046 gpointer iter = NULL;
7047 while ((p = mono_class_get_properties (klass, &iter))) {
7048 if (&klass->ext->properties [i] == prop)
7049 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7053 klass = klass->parent;
7056 g_assert_not_reached ();
7061 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7063 const char *name, *nspace;
7064 if (image_is_dynamic (image))
7065 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7067 switch (type_token & 0xff000000){
7068 case MONO_TOKEN_TYPE_DEF: {
7069 guint32 cols [MONO_TYPEDEF_SIZE];
7070 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7071 guint tidx = mono_metadata_token_index (type_token);
7073 if (tidx > tt->rows)
7074 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7076 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7077 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7078 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7079 if (strlen (nspace) == 0)
7080 return g_strdup_printf ("%s", name);
7082 return g_strdup_printf ("%s.%s", nspace, name);
7085 case MONO_TOKEN_TYPE_REF: {
7087 guint32 cols [MONO_TYPEREF_SIZE];
7088 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7089 guint tidx = mono_metadata_token_index (type_token);
7092 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7094 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7095 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7096 mono_error_cleanup (&error);
7100 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7101 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7102 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7103 if (strlen (nspace) == 0)
7104 return g_strdup_printf ("%s", name);
7106 return g_strdup_printf ("%s.%s", nspace, name);
7109 case MONO_TOKEN_TYPE_SPEC:
7110 return g_strdup_printf ("Typespec 0x%08x", type_token);
7112 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7117 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7119 if (image_is_dynamic (image))
7120 return g_strdup_printf ("DynamicAssembly %s", image->name);
7122 switch (type_token & 0xff000000){
7123 case MONO_TOKEN_TYPE_DEF:
7124 if (image->assembly)
7125 return mono_stringify_assembly_name (&image->assembly->aname);
7126 else if (image->assembly_name)
7127 return g_strdup (image->assembly_name);
7128 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7129 case MONO_TOKEN_TYPE_REF: {
7131 MonoAssemblyName aname;
7132 guint32 cols [MONO_TYPEREF_SIZE];
7133 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7134 guint32 idx = mono_metadata_token_index (type_token);
7137 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7139 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7140 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7141 mono_error_cleanup (&error);
7144 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7146 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7147 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7148 case MONO_RESOLUTION_SCOPE_MODULE:
7150 return g_strdup ("");
7151 case MONO_RESOLUTION_SCOPE_MODULEREF:
7153 return g_strdup ("");
7154 case MONO_RESOLUTION_SCOPE_TYPEREF:
7156 return g_strdup ("");
7157 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7158 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7159 return mono_stringify_assembly_name (&aname);
7161 g_assert_not_reached ();
7165 case MONO_TOKEN_TYPE_SPEC:
7167 return g_strdup ("");
7169 g_assert_not_reached ();
7176 * mono_class_get_full:
7177 * @image: the image where the class resides
7178 * @type_token: the token for the class
7179 * @context: the generic context used to evaluate generic instantiations in
7180 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7182 * Returns: the MonoClass that represents @type_token in @image
7185 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7189 class = mono_class_get_checked (image, type_token, &error);
7191 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7192 class = mono_class_inflate_generic_class_checked (class, context, &error);
7195 mono_loader_set_error_from_mono_error (&error);
7196 mono_error_cleanup (&error); /*FIXME don't swallow this error */
7203 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7207 mono_error_init (error);
7208 class = mono_class_get_checked (image, type_token, error);
7210 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7211 class = mono_class_inflate_generic_class_checked (class, context, error);
7216 * mono_class_get_checked:
7217 * @image: the image where the class resides
7218 * @type_token: the token for the class
7219 * @error: error object to return any error
7221 * Returns: the MonoClass that represents @type_token in @image
7224 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7226 MonoClass *class = NULL;
7228 mono_error_init (error);
7230 if (image_is_dynamic (image)) {
7231 int table = mono_metadata_token_table (type_token);
7233 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7234 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7237 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7241 switch (type_token & 0xff000000){
7242 case MONO_TOKEN_TYPE_DEF:
7243 class = mono_class_create_from_typedef (image, type_token, error);
7245 case MONO_TOKEN_TYPE_REF:
7246 class = mono_class_from_typeref_checked (image, type_token, error);
7248 case MONO_TOKEN_TYPE_SPEC:
7249 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7252 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7256 /* Generic case, should be avoided for when a better error is possible. */
7257 if (!class && mono_error_ok (error)) {
7258 char *name = mono_class_name_from_token (image, type_token);
7259 char *assembly = mono_assembly_name_from_token (image, type_token);
7260 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7268 * mono_type_get_checked:
7269 * @image: the image where the type resides
7270 * @type_token: the token for the type
7271 * @context: the generic context used to evaluate generic instantiations in
7272 * @error: Error handling context
7274 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7276 * Returns: the MonoType that represents @type_token in @image
7279 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7281 MonoType *type = NULL;
7282 gboolean inflated = FALSE;
7284 mono_error_init (error);
7286 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7287 if (image_is_dynamic (image))
7288 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7290 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7291 MonoClass *class = mono_class_get_checked (image, type_token, error);
7294 g_assert (!mono_loader_get_last_error ());
7299 return mono_class_get_type (class);
7302 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7305 g_assert (!mono_loader_get_last_error ());
7310 MonoType *tmp = type;
7311 type = mono_class_get_type (mono_class_from_mono_type (type));
7312 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7313 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7314 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7316 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7318 if (type->type != tmp->type)
7321 mono_metadata_free_type (tmp);
7328 mono_class_get (MonoImage *image, guint32 type_token)
7330 return mono_class_get_full (image, type_token, NULL);
7334 * mono_image_init_name_cache:
7336 * Initializes the class name cache stored in image->name_cache.
7338 * LOCKING: Acquires the corresponding image lock.
7341 mono_image_init_name_cache (MonoImage *image)
7343 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7344 guint32 cols [MONO_TYPEDEF_SIZE];
7347 guint32 i, visib, nspace_index;
7348 GHashTable *name_cache2, *nspace_table;
7350 mono_image_lock (image);
7352 if (image->name_cache) {
7353 mono_image_unlock (image);
7357 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7359 if (image_is_dynamic (image)) {
7360 mono_image_unlock (image);
7364 /* Temporary hash table to avoid lookups in the nspace_table */
7365 name_cache2 = g_hash_table_new (NULL, NULL);
7367 for (i = 1; i <= t->rows; ++i) {
7368 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7369 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7371 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7372 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7374 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7376 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7377 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7379 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7380 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7381 if (!nspace_table) {
7382 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7383 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7384 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7387 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7390 /* Load type names from EXPORTEDTYPES table */
7392 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7393 guint32 cols [MONO_EXP_TYPE_SIZE];
7396 for (i = 0; i < t->rows; ++i) {
7397 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7398 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7399 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7401 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7402 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7403 if (!nspace_table) {
7404 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7405 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7406 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7409 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7413 g_hash_table_destroy (name_cache2);
7414 mono_image_unlock (image);
7417 /*FIXME Only dynamic assemblies should allow this operation.*/
7419 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7420 const char *name, guint32 index)
7422 GHashTable *nspace_table;
7423 GHashTable *name_cache;
7426 mono_image_lock (image);
7428 if (!image->name_cache)
7429 mono_image_init_name_cache (image);
7431 name_cache = image->name_cache;
7432 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7433 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7434 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7437 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7438 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7440 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7442 mono_image_unlock (image);
7451 find_nocase (gpointer key, gpointer value, gpointer user_data)
7453 char *name = (char*)key;
7454 FindUserData *data = (FindUserData*)user_data;
7456 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7457 data->value = value;
7461 * mono_class_from_name_case:
7462 * @image: The MonoImage where the type is looked up in
7463 * @name_space: the type namespace
7464 * @name: the type short name.
7465 * @deprecated: use the _checked variant
7467 * Obtains a MonoClass with a given namespace and a given name which
7468 * is located in the given MonoImage. The namespace and name
7469 * lookups are case insensitive.
7472 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7475 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7476 g_assert (!mono_error_ok (&error));
7481 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7483 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7484 guint32 cols [MONO_TYPEDEF_SIZE];
7489 mono_error_init (error);
7491 if (image_is_dynamic (image)) {
7493 FindUserData user_data;
7495 mono_image_lock (image);
7497 if (!image->name_cache)
7498 mono_image_init_name_cache (image);
7500 user_data.key = name_space;
7501 user_data.value = NULL;
7502 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7504 if (user_data.value) {
7505 GHashTable *nspace_table = (GHashTable*)user_data.value;
7507 user_data.key = name;
7508 user_data.value = NULL;
7510 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7512 if (user_data.value)
7513 token = GPOINTER_TO_UINT (user_data.value);
7516 mono_image_unlock (image);
7519 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7525 /* add a cache if needed */
7526 for (i = 1; i <= t->rows; ++i) {
7527 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7528 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7530 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7531 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7533 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7535 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7536 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7537 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7538 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7544 return_nested_in (MonoClass *class, char *nested)
7547 char *s = strchr (nested, '/');
7548 gpointer iter = NULL;
7555 while ((found = mono_class_get_nested_types (class, &iter))) {
7556 if (strcmp (found->name, nested) == 0) {
7558 return return_nested_in (found, s);
7566 search_modules (MonoImage *image, const char *name_space, const char *name)
7568 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7569 MonoImage *file_image;
7574 * The EXPORTEDTYPES table only contains public types, so have to search the
7576 * Note: image->modules contains the contents of the MODULEREF table, while
7577 * the real module list is in the FILE table.
7579 for (i = 0; i < file_table->rows; i++) {
7580 guint32 cols [MONO_FILE_SIZE];
7581 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7582 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7585 file_image = mono_image_load_file_for_image (image, i + 1);
7587 class = mono_class_from_name (file_image, name_space, name);
7597 * mono_class_from_name:
7598 * @image: The MonoImage where the type is looked up in
7599 * @name_space: the type namespace
7600 * @name: the type short name.
7602 * Obtains a MonoClass with a given namespace and a given name which
7603 * is located in the given MonoImage.
7605 * To reference nested classes, use the "/" character as a separator.
7606 * For example use "Foo/Bar" to reference the class Bar that is nested
7607 * inside Foo, like this: "class Foo { class Bar {} }".
7610 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7612 GHashTable *nspace_table;
7613 MonoImage *loaded_image;
7620 if ((nested = strchr (name, '/'))) {
7621 int pos = nested - name;
7622 int len = strlen (name);
7625 memcpy (buf, name, len + 1);
7627 nested = buf + pos + 1;
7631 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7632 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7633 gboolean res = get_class_from_name (image, name_space, name, &class);
7636 class = search_modules (image, name_space, name);
7638 return class ? return_nested_in (class, nested) : NULL;
7644 mono_image_lock (image);
7646 if (!image->name_cache)
7647 mono_image_init_name_cache (image);
7649 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7652 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7654 mono_image_unlock (image);
7656 if (!token && image_is_dynamic (image) && image->modules) {
7657 /* Search modules as well */
7658 for (i = 0; i < image->module_count; ++i) {
7659 MonoImage *module = image->modules [i];
7661 class = mono_class_from_name (module, name_space, name);
7668 class = search_modules (image, name_space, name);
7676 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7677 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7678 guint32 cols [MONO_EXP_TYPE_SIZE];
7681 idx = mono_metadata_token_index (token);
7683 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7685 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7686 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7687 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7690 class = mono_class_from_name (loaded_image, name_space, name);
7692 return return_nested_in (class, nested);
7694 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7695 guint32 assembly_idx;
7697 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7699 mono_assembly_load_reference (image, assembly_idx - 1);
7700 g_assert (image->references [assembly_idx - 1]);
7701 if (image->references [assembly_idx - 1] == (gpointer)-1)
7704 /* FIXME: Cycle detection */
7705 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7707 g_error ("not yet implemented");
7711 token = MONO_TOKEN_TYPE_DEF | token;
7713 class = mono_class_get (image, token);
7715 return return_nested_in (class, nested);
7720 * mono_class_is_subclass_of:
7721 * @klass: class to probe if it is a subclass of another one
7722 * @klassc: the class we suspect is the base class
7723 * @check_interfaces: whether we should perform interface checks
7725 * This method determines whether @klass is a subclass of @klassc.
7727 * If the @check_interfaces flag is set, then if @klassc is an interface
7728 * this method return true if the @klass implements the interface or
7729 * if @klass is an interface, if one of its base classes is @klass.
7731 * If @check_interfaces is false then, then if @klass is not an interface
7732 * then it returns true if the @klass is a subclass of @klassc.
7734 * if @klass is an interface and @klassc is System.Object, then this function
7739 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7740 gboolean check_interfaces)
7742 /*FIXME test for interfaces with variant generic arguments*/
7744 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7745 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7747 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7750 for (i = 0; i < klass->interface_count; i ++) {
7751 MonoClass *ic = klass->interfaces [i];
7756 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7761 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7764 if (klassc == mono_defaults.object_class)
7771 mono_type_is_generic_argument (MonoType *type)
7773 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7777 mono_class_has_variant_generic_params (MonoClass *klass)
7780 MonoGenericContainer *container;
7782 if (!klass->generic_class)
7785 container = klass->generic_class->container_class->generic_container;
7787 for (i = 0; i < container->type_argc; ++i)
7788 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7795 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7797 if (target == candidate)
7800 if (check_for_reference_conv &&
7801 mono_type_is_generic_argument (&target->byval_arg) &&
7802 mono_type_is_generic_argument (&candidate->byval_arg)) {
7803 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7804 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7806 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7809 if (!mono_class_is_assignable_from (target, candidate))
7815 * @container the generic container from the GTD
7816 * @klass: the class to be assigned to
7817 * @oklass: the source class
7819 * Both klass and oklass must be instances of the same generic interface.
7820 * Return true if @klass can be assigned to a @klass variable
7823 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7826 MonoType **klass_argv, **oklass_argv;
7827 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7828 MonoGenericContainer *container = klass_gtd->generic_container;
7830 if (klass == oklass)
7833 /*Viable candidates are instances of the same generic interface*/
7834 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7837 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7838 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7840 for (j = 0; j < container->type_argc; ++j) {
7841 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7842 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7844 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7848 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7849 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7851 if (param1_class != param2_class) {
7852 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7853 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7855 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7856 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7866 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7868 MonoGenericParam *gparam, *ogparam;
7869 MonoGenericParamInfo *tinfo, *cinfo;
7870 MonoClass **candidate_class;
7871 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7874 if (target == candidate)
7876 if (target->byval_arg.type != candidate->byval_arg.type)
7879 gparam = target->byval_arg.data.generic_param;
7880 ogparam = candidate->byval_arg.data.generic_param;
7881 tinfo = mono_generic_param_info (gparam);
7882 cinfo = mono_generic_param_info (ogparam);
7884 class_constraint_satisfied = FALSE;
7885 valuetype_constraint_satisfied = FALSE;
7887 /*candidate must have a super set of target's special constraints*/
7888 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7889 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7891 if (cinfo->constraints) {
7892 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7893 MonoClass *cc = *candidate_class;
7895 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7896 class_constraint_satisfied = TRUE;
7897 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7898 valuetype_constraint_satisfied = TRUE;
7901 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7902 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7904 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7906 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7908 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7909 valuetype_constraint_satisfied)) {
7914 /*candidate type constraints must be a superset of target's*/
7915 if (tinfo->constraints) {
7916 MonoClass **target_class;
7917 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7918 MonoClass *tc = *target_class;
7921 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7922 * check it's constraints since it satisfy the constraint by itself.
7924 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7927 if (!cinfo->constraints)
7930 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7931 MonoClass *cc = *candidate_class;
7933 if (mono_class_is_assignable_from (tc, cc))
7937 * This happens when we have the following:
7939 * Bar<K> where K : IFace
7940 * Foo<T, U> where T : U where U : IFace
7942 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7945 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7946 if (mono_gparam_is_assignable_from (target, cc))
7950 if (!*candidate_class)
7955 /*candidate itself must have a constraint that satisfy target*/
7956 if (cinfo->constraints) {
7957 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7958 MonoClass *cc = *candidate_class;
7959 if (mono_class_is_assignable_from (target, cc))
7967 * mono_class_is_assignable_from:
7968 * @klass: the class to be assigned to
7969 * @oklass: the source class
7971 * Return: true if an instance of object oklass can be assigned to an
7972 * instance of object @klass
7975 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7977 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7979 mono_class_init (klass);
7981 if (!oklass->inited)
7982 mono_class_init (oklass);
7984 if (klass->exception_type || oklass->exception_type)
7987 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7988 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7990 return mono_gparam_is_assignable_from (klass, oklass);
7993 if (MONO_CLASS_IS_INTERFACE (klass)) {
7994 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7995 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7996 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8000 for (i = 0; constraints [i]; ++i) {
8001 if (mono_class_is_assignable_from (klass, constraints [i]))
8009 /* interface_offsets might not be set for dynamic classes */
8010 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8012 * oklass might be a generic type parameter but they have
8013 * interface_offsets set.
8015 return mono_reflection_call_is_assignable_to (oklass, klass);
8016 if (!oklass->interface_bitmap)
8017 /* Happens with generic instances of not-yet created dynamic types */
8019 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8022 if (mono_class_has_variant_generic_params (klass)) {
8025 mono_class_setup_interfaces (oklass, &error);
8026 if (!mono_error_ok (&error)) {
8027 mono_error_cleanup (&error);
8031 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8032 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8033 MonoClass *iface = oklass->interfaces_packed [i];
8035 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8040 } else if (klass->delegate) {
8041 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8043 }else if (klass->rank) {
8044 MonoClass *eclass, *eoclass;
8046 if (oklass->rank != klass->rank)
8049 /* vectors vs. one dimensional arrays */
8050 if (oklass->byval_arg.type != klass->byval_arg.type)
8053 eclass = klass->cast_class;
8054 eoclass = oklass->cast_class;
8057 * a is b does not imply a[] is b[] when a is a valuetype, and
8058 * b is a reference type.
8061 if (eoclass->valuetype) {
8062 if ((eclass == mono_defaults.enum_class) ||
8063 (eclass == mono_defaults.enum_class->parent) ||
8064 (eclass == mono_defaults.object_class))
8068 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8069 } else if (mono_class_is_nullable (klass)) {
8070 if (mono_class_is_nullable (oklass))
8071 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8073 return mono_class_is_assignable_from (klass->cast_class, oklass);
8074 } else if (klass == mono_defaults.object_class)
8077 return mono_class_has_parent (oklass, klass);
8080 /*Check if @oklass is variant compatible with @klass.*/
8082 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8085 MonoType **klass_argv, **oklass_argv;
8086 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8087 MonoGenericContainer *container = klass_gtd->generic_container;
8089 /*Viable candidates are instances of the same generic interface*/
8090 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8093 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8094 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8096 for (j = 0; j < container->type_argc; ++j) {
8097 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8098 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8100 if (param1_class->valuetype != param2_class->valuetype)
8104 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8105 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8107 if (param1_class != param2_class) {
8108 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8109 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8111 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8112 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8120 /*Check if @candidate implements the interface @target*/
8122 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8126 gboolean is_variant = mono_class_has_variant_generic_params (target);
8128 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8129 if (mono_class_is_variant_compatible_slow (target, candidate))
8134 if (candidate == target)
8137 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8138 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8139 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8141 if (tb && tb->interfaces) {
8142 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8143 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8144 MonoClass *iface_class;
8146 /* we can't realize the type here since it can do pretty much anything. */
8149 iface_class = mono_class_from_mono_type (iface->type);
8150 if (iface_class == target)
8152 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8154 if (mono_class_implement_interface_slow (target, iface_class))
8159 /*setup_interfaces don't mono_class_init anything*/
8160 /*FIXME this doesn't handle primitive type arrays.
8161 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8162 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8164 mono_class_setup_interfaces (candidate, &error);
8165 if (!mono_error_ok (&error)) {
8166 mono_error_cleanup (&error);
8170 for (i = 0; i < candidate->interface_count; ++i) {
8171 if (candidate->interfaces [i] == target)
8174 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8177 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8181 candidate = candidate->parent;
8182 } while (candidate);
8188 * Check if @oklass can be assigned to @klass.
8189 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8192 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8194 if (candidate == target)
8196 if (target == mono_defaults.object_class)
8199 if (mono_class_has_parent (candidate, target))
8202 /*If target is not an interface there is no need to check them.*/
8203 if (MONO_CLASS_IS_INTERFACE (target))
8204 return mono_class_implement_interface_slow (target, candidate);
8206 if (target->delegate && mono_class_has_variant_generic_params (target))
8207 return mono_class_is_variant_compatible (target, candidate, FALSE);
8210 MonoClass *eclass, *eoclass;
8212 if (target->rank != candidate->rank)
8215 /* vectors vs. one dimensional arrays */
8216 if (target->byval_arg.type != candidate->byval_arg.type)
8219 eclass = target->cast_class;
8220 eoclass = candidate->cast_class;
8223 * a is b does not imply a[] is b[] when a is a valuetype, and
8224 * b is a reference type.
8227 if (eoclass->valuetype) {
8228 if ((eclass == mono_defaults.enum_class) ||
8229 (eclass == mono_defaults.enum_class->parent) ||
8230 (eclass == mono_defaults.object_class))
8234 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8236 /*FIXME properly handle nullables */
8237 /*FIXME properly handle (M)VAR */
8242 * mono_class_get_cctor:
8243 * @klass: A MonoClass pointer
8245 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8248 mono_class_get_cctor (MonoClass *klass)
8250 MonoCachedClassInfo cached_info;
8252 if (image_is_dynamic (klass->image)) {
8254 * has_cctor is not set for these classes because mono_class_init () is
8257 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8260 if (!klass->has_cctor)
8263 if (mono_class_get_cached_class_info (klass, &cached_info))
8264 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8266 if (klass->generic_class && !klass->methods)
8267 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8269 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8273 * mono_class_get_finalizer:
8274 * @klass: The MonoClass pointer
8276 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8279 mono_class_get_finalizer (MonoClass *klass)
8281 MonoCachedClassInfo cached_info;
8284 mono_class_init (klass);
8285 if (!mono_class_has_finalizer (klass))
8288 if (mono_class_get_cached_class_info (klass, &cached_info))
8289 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8291 mono_class_setup_vtable (klass);
8292 return klass->vtable [finalize_slot];
8297 * mono_class_needs_cctor_run:
8298 * @klass: the MonoClass pointer
8299 * @caller: a MonoMethod describing the caller
8301 * Determines whenever the class has a static constructor and whenever it
8302 * needs to be called when executing CALLER.
8305 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8309 method = mono_class_get_cctor (klass);
8311 return (method == caller) ? FALSE : TRUE;
8317 * mono_class_array_element_size:
8320 * Returns: the number of bytes an element of type @klass
8321 * uses when stored into an array.
8324 mono_class_array_element_size (MonoClass *klass)
8326 MonoType *type = &klass->byval_arg;
8329 switch (type->type) {
8332 case MONO_TYPE_BOOLEAN:
8336 case MONO_TYPE_CHAR:
8345 case MONO_TYPE_CLASS:
8346 case MONO_TYPE_STRING:
8347 case MONO_TYPE_OBJECT:
8348 case MONO_TYPE_SZARRAY:
8349 case MONO_TYPE_ARRAY:
8351 case MONO_TYPE_MVAR:
8352 return sizeof (gpointer);
8357 case MONO_TYPE_VALUETYPE:
8358 if (type->data.klass->enumtype) {
8359 type = mono_class_enum_basetype (type->data.klass);
8360 klass = klass->element_class;
8363 return mono_class_instance_size (klass) - sizeof (MonoObject);
8364 case MONO_TYPE_GENERICINST:
8365 type = &type->data.generic_class->container_class->byval_arg;
8368 case MONO_TYPE_VOID:
8372 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8378 * mono_array_element_size:
8379 * @ac: pointer to a #MonoArrayClass
8381 * Returns: the size of single array element.
8384 mono_array_element_size (MonoClass *ac)
8386 g_assert (ac->rank);
8387 return ac->sizes.element_size;
8391 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8392 MonoGenericContext *context)
8394 if (image_is_dynamic (image)) {
8395 MonoClass *tmp_handle_class;
8396 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8398 g_assert (tmp_handle_class);
8400 *handle_class = tmp_handle_class;
8402 if (tmp_handle_class == mono_defaults.typehandle_class)
8403 return &((MonoClass*)obj)->byval_arg;
8408 switch (token & 0xff000000) {
8409 case MONO_TOKEN_TYPE_DEF:
8410 case MONO_TOKEN_TYPE_REF:
8411 case MONO_TOKEN_TYPE_SPEC: {
8415 *handle_class = mono_defaults.typehandle_class;
8416 type = mono_type_get_checked (image, token, context, &error);
8418 mono_loader_set_error_from_mono_error (&error);
8419 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8422 mono_class_init (mono_class_from_mono_type (type));
8423 /* We return a MonoType* as handle */
8426 case MONO_TOKEN_FIELD_DEF: {
8429 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8433 *handle_class = mono_defaults.fieldhandle_class;
8434 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8436 mono_loader_set_error_from_mono_error (&error);
8437 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8440 mono_class_init (class);
8441 return mono_class_get_field (class, token);
8443 case MONO_TOKEN_METHOD_DEF:
8444 case MONO_TOKEN_METHOD_SPEC: {
8446 meth = mono_get_method_full (image, token, NULL, context);
8448 *handle_class = mono_defaults.methodhandle_class;
8451 case MONO_TOKEN_MEMBER_REF: {
8452 guint32 cols [MONO_MEMBERREF_SIZE];
8454 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8455 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8456 mono_metadata_decode_blob_size (sig, &sig);
8457 if (*sig == 0x6) { /* it's a field */
8459 MonoClassField *field;
8460 field = mono_field_from_token (image, token, &klass, context);
8462 *handle_class = mono_defaults.fieldhandle_class;
8466 meth = mono_get_method_full (image, token, NULL, context);
8468 *handle_class = mono_defaults.methodhandle_class;
8473 g_warning ("Unknown token 0x%08x in ldtoken", token);
8480 * This function might need to call runtime functions so it can't be part
8481 * of the metadata library.
8483 static MonoLookupDynamicToken lookup_dynamic = NULL;
8486 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8488 lookup_dynamic = func;
8492 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8494 MonoClass *handle_class;
8496 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8500 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8502 return lookup_dynamic (image, token, valid_token, handle_class, context);
8505 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8508 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8510 get_cached_class_info = func;
8514 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8516 if (!get_cached_class_info)
8519 return get_cached_class_info (klass, res);
8523 mono_install_get_class_from_name (MonoGetClassFromName func)
8525 get_class_from_name = func;
8529 mono_class_get_image (MonoClass *klass)
8531 return klass->image;
8535 * mono_class_get_element_class:
8536 * @klass: the MonoClass to act on
8538 * Returns: the element class of an array or an enumeration.
8541 mono_class_get_element_class (MonoClass *klass)
8543 return klass->element_class;
8547 * mono_class_is_valuetype:
8548 * @klass: the MonoClass to act on
8550 * Returns: true if the MonoClass represents a ValueType.
8553 mono_class_is_valuetype (MonoClass *klass)
8555 return klass->valuetype;
8559 * mono_class_is_enum:
8560 * @klass: the MonoClass to act on
8562 * Returns: true if the MonoClass represents an enumeration.
8565 mono_class_is_enum (MonoClass *klass)
8567 return klass->enumtype;
8571 * mono_class_enum_basetype:
8572 * @klass: the MonoClass to act on
8574 * Returns: the underlying type representation for an enumeration.
8577 mono_class_enum_basetype (MonoClass *klass)
8579 if (klass->element_class == klass)
8580 /* SRE or broken types */
8583 return &klass->element_class->byval_arg;
8587 * mono_class_get_parent
8588 * @klass: the MonoClass to act on
8590 * Returns: the parent class for this class.
8593 mono_class_get_parent (MonoClass *klass)
8595 return klass->parent;
8599 * mono_class_get_nesting_type;
8600 * @klass: the MonoClass to act on
8602 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8605 mono_class_get_nesting_type (MonoClass *klass)
8607 return klass->nested_in;
8611 * mono_class_get_rank:
8612 * @klass: the MonoClass to act on
8614 * Returns: the rank for the array (the number of dimensions).
8617 mono_class_get_rank (MonoClass *klass)
8623 * mono_class_get_flags:
8624 * @klass: the MonoClass to act on
8626 * The type flags from the TypeDef table from the metadata.
8627 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8630 * Returns: the flags from the TypeDef table.
8633 mono_class_get_flags (MonoClass *klass)
8635 return klass->flags;
8639 * mono_class_get_name
8640 * @klass: the MonoClass to act on
8642 * Returns: the name of the class.
8645 mono_class_get_name (MonoClass *klass)
8651 * mono_class_get_namespace:
8652 * @klass: the MonoClass to act on
8654 * Returns: the namespace of the class.
8657 mono_class_get_namespace (MonoClass *klass)
8659 return klass->name_space;
8663 * mono_class_get_type:
8664 * @klass: the MonoClass to act on
8666 * This method returns the internal Type representation for the class.
8668 * Returns: the MonoType from the class.
8671 mono_class_get_type (MonoClass *klass)
8673 return &klass->byval_arg;
8677 * mono_class_get_type_token
8678 * @klass: the MonoClass to act on
8680 * This method returns type token for the class.
8682 * Returns: the type token for the class.
8685 mono_class_get_type_token (MonoClass *klass)
8687 return klass->type_token;
8691 * mono_class_get_byref_type:
8692 * @klass: the MonoClass to act on
8697 mono_class_get_byref_type (MonoClass *klass)
8699 return &klass->this_arg;
8703 * mono_class_num_fields:
8704 * @klass: the MonoClass to act on
8706 * Returns: the number of static and instance fields in the class.
8709 mono_class_num_fields (MonoClass *klass)
8711 return klass->field.count;
8715 * mono_class_num_methods:
8716 * @klass: the MonoClass to act on
8718 * Returns: the number of methods in the class.
8721 mono_class_num_methods (MonoClass *klass)
8723 return klass->method.count;
8727 * mono_class_num_properties
8728 * @klass: the MonoClass to act on
8730 * Returns: the number of properties in the class.
8733 mono_class_num_properties (MonoClass *klass)
8735 mono_class_setup_properties (klass);
8737 return klass->ext->property.count;
8741 * mono_class_num_events:
8742 * @klass: the MonoClass to act on
8744 * Returns: the number of events in the class.
8747 mono_class_num_events (MonoClass *klass)
8749 mono_class_setup_events (klass);
8751 return klass->ext->event.count;
8755 * mono_class_get_fields:
8756 * @klass: the MonoClass to act on
8758 * This routine is an iterator routine for retrieving the fields in a class.
8760 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8761 * iterate over all of the elements. When no more values are
8762 * available, the return value is NULL.
8764 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8767 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8769 MonoClassField* field;
8773 mono_class_setup_fields_locking (klass);
8774 if (klass->exception_type)
8776 /* start from the first */
8777 if (klass->field.count) {
8778 return *iter = &klass->fields [0];
8786 if (field < &klass->fields [klass->field.count]) {
8787 return *iter = field;
8793 * mono_class_get_methods
8794 * @klass: the MonoClass to act on
8796 * This routine is an iterator routine for retrieving the fields in a class.
8798 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8799 * iterate over all of the elements. When no more values are
8800 * available, the return value is NULL.
8802 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8805 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8807 MonoMethod** method;
8811 mono_class_setup_methods (klass);
8814 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8815 * FIXME we should better report this error to the caller
8817 if (!klass->methods)
8819 /* start from the first */
8820 if (klass->method.count) {
8821 *iter = &klass->methods [0];
8822 return klass->methods [0];
8830 if (method < &klass->methods [klass->method.count]) {
8838 * mono_class_get_virtual_methods:
8840 * Iterate over the virtual methods of KLASS.
8842 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8845 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8847 MonoMethod** method;
8850 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8852 mono_class_setup_methods (klass);
8854 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8855 * FIXME we should better report this error to the caller
8857 if (!klass->methods)
8859 /* start from the first */
8860 method = &klass->methods [0];
8865 while (method < &klass->methods [klass->method.count]) {
8866 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8870 if (method < &klass->methods [klass->method.count]) {
8877 /* Search directly in metadata to avoid calling setup_methods () */
8878 MonoMethod *res = NULL;
8884 start_index = GPOINTER_TO_UINT (*iter);
8887 for (i = start_index; i < klass->method.count; ++i) {
8890 /* class->method.first points into the methodptr table */
8891 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8893 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8897 if (i < klass->method.count) {
8898 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8899 /* Add 1 here so the if (*iter) check fails */
8900 *iter = GUINT_TO_POINTER (i + 1);
8909 * mono_class_get_properties:
8910 * @klass: the MonoClass to act on
8912 * This routine is an iterator routine for retrieving the properties in a class.
8914 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8915 * iterate over all of the elements. When no more values are
8916 * available, the return value is NULL.
8918 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8921 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8923 MonoProperty* property;
8927 mono_class_setup_properties (klass);
8928 /* start from the first */
8929 if (klass->ext->property.count) {
8930 return *iter = &klass->ext->properties [0];
8938 if (property < &klass->ext->properties [klass->ext->property.count]) {
8939 return *iter = property;
8945 * mono_class_get_events:
8946 * @klass: the MonoClass to act on
8948 * This routine is an iterator routine for retrieving the properties in a class.
8950 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8951 * iterate over all of the elements. When no more values are
8952 * available, the return value is NULL.
8954 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8957 mono_class_get_events (MonoClass* klass, gpointer *iter)
8963 mono_class_setup_events (klass);
8964 /* start from the first */
8965 if (klass->ext->event.count) {
8966 return *iter = &klass->ext->events [0];
8974 if (event < &klass->ext->events [klass->ext->event.count]) {
8975 return *iter = event;
8981 * mono_class_get_interfaces
8982 * @klass: the MonoClass to act on
8984 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8986 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8987 * iterate over all of the elements. When no more values are
8988 * available, the return value is NULL.
8990 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8993 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9001 mono_class_init (klass);
9002 if (!klass->interfaces_inited) {
9003 mono_class_setup_interfaces (klass, &error);
9004 if (!mono_error_ok (&error)) {
9005 mono_error_cleanup (&error);
9009 /* start from the first */
9010 if (klass->interface_count) {
9011 *iter = &klass->interfaces [0];
9012 return klass->interfaces [0];
9020 if (iface < &klass->interfaces [klass->interface_count]) {
9028 setup_nested_types (MonoClass *klass)
9031 GList *classes, *nested_classes, *l;
9034 if (klass->nested_classes_inited)
9037 if (!klass->type_token)
9038 klass->nested_classes_inited = TRUE;
9040 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9044 guint32 cols [MONO_NESTED_CLASS_SIZE];
9045 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9046 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9047 if (!mono_error_ok (&error)) {
9048 /*FIXME don't swallow the error message*/
9049 mono_error_cleanup (&error);
9051 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9055 classes = g_list_prepend (classes, nclass);
9057 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9060 mono_class_alloc_ext (klass);
9062 nested_classes = NULL;
9063 for (l = classes; l; l = l->next)
9064 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9065 g_list_free (classes);
9067 mono_image_lock (klass->image);
9069 mono_memory_barrier ();
9070 if (!klass->nested_classes_inited) {
9071 klass->ext->nested_classes = nested_classes;
9072 mono_memory_barrier ();
9073 klass->nested_classes_inited = TRUE;
9076 mono_image_unlock (klass->image);
9080 * mono_class_get_nested_types
9081 * @klass: the MonoClass to act on
9083 * This routine is an iterator routine for retrieving the nested types of a class.
9084 * This works only if @klass is non-generic, or a generic type definition.
9086 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9087 * iterate over all of the elements. When no more values are
9088 * available, the return value is NULL.
9090 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9093 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9099 if (!klass->nested_classes_inited)
9100 setup_nested_types (klass);
9103 /* start from the first */
9104 if (klass->ext && klass->ext->nested_classes) {
9105 *iter = klass->ext->nested_classes;
9106 return klass->ext->nested_classes->data;
9108 /* no nested types */
9123 * mono_class_is_delegate
9124 * @klass: the MonoClass to act on
9126 * Returns: true if the MonoClass represents a System.Delegate.
9129 mono_class_is_delegate (MonoClass *klass)
9131 return klass->delegate;
9135 * mono_class_implements_interface
9136 * @klass: The MonoClass to act on
9137 * @interface: The interface to check if @klass implements.
9139 * Returns: true if @klass implements @interface.
9142 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9144 return mono_class_is_assignable_from (iface, klass);
9148 * mono_field_get_name:
9149 * @field: the MonoClassField to act on
9151 * Returns: the name of the field.
9154 mono_field_get_name (MonoClassField *field)
9160 * mono_field_get_type:
9161 * @field: the MonoClassField to act on
9163 * Returns: MonoType of the field.
9166 mono_field_get_type (MonoClassField *field)
9169 MonoType *type = mono_field_get_type_checked (field, &error);
9170 if (!mono_error_ok (&error)) {
9171 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9172 mono_error_cleanup (&error);
9179 * mono_field_get_type_checked:
9180 * @field: the MonoClassField to act on
9181 * @error: used to return any erro found while retrieving @field type
9183 * Returns: MonoType of the field.
9186 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9188 mono_error_init (error);
9190 mono_field_resolve_type (field, error);
9195 * mono_field_get_parent:
9196 * @field: the MonoClassField to act on
9198 * Returns: MonoClass where the field was defined.
9201 mono_field_get_parent (MonoClassField *field)
9203 return field->parent;
9207 * mono_field_get_flags;
9208 * @field: the MonoClassField to act on
9210 * The metadata flags for a field are encoded using the
9211 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9213 * Returns: the flags for the field.
9216 mono_field_get_flags (MonoClassField *field)
9219 return mono_field_resolve_flags (field);
9220 return field->type->attrs;
9224 * mono_field_get_offset;
9225 * @field: the MonoClassField to act on
9227 * Returns: the field offset.
9230 mono_field_get_offset (MonoClassField *field)
9232 return field->offset;
9236 mono_field_get_rva (MonoClassField *field)
9240 MonoClass *klass = field->parent;
9241 MonoFieldDefaultValue *field_def_values;
9243 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9245 if (!klass->ext || !klass->ext->field_def_values) {
9246 mono_class_alloc_ext (klass);
9248 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9250 mono_image_lock (klass->image);
9251 if (!klass->ext->field_def_values)
9252 klass->ext->field_def_values = field_def_values;
9253 mono_image_unlock (klass->image);
9256 field_index = mono_field_get_index (field);
9258 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9259 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9261 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9262 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9265 return klass->ext->field_def_values [field_index].data;
9269 * mono_field_get_data;
9270 * @field: the MonoClassField to act on
9272 * Returns: pointer to the metadata constant value or to the field
9273 * data if it has an RVA flag.
9276 mono_field_get_data (MonoClassField *field)
9278 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9279 MonoTypeEnum def_type;
9281 return mono_class_get_field_default_value (field, &def_type);
9282 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9283 return mono_field_get_rva (field);
9290 * mono_property_get_name:
9291 * @prop: the MonoProperty to act on
9293 * Returns: the name of the property
9296 mono_property_get_name (MonoProperty *prop)
9302 * mono_property_get_set_method
9303 * @prop: the MonoProperty to act on.
9305 * Returns: the setter method of the property (A MonoMethod)
9308 mono_property_get_set_method (MonoProperty *prop)
9314 * mono_property_get_get_method
9315 * @prop: the MonoProperty to act on.
9317 * Returns: the setter method of the property (A MonoMethod)
9320 mono_property_get_get_method (MonoProperty *prop)
9326 * mono_property_get_parent:
9327 * @prop: the MonoProperty to act on.
9329 * Returns: the MonoClass where the property was defined.
9332 mono_property_get_parent (MonoProperty *prop)
9334 return prop->parent;
9338 * mono_property_get_flags:
9339 * @prop: the MonoProperty to act on.
9341 * The metadata flags for a property are encoded using the
9342 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9344 * Returns: the flags for the property.
9347 mono_property_get_flags (MonoProperty *prop)
9353 * mono_event_get_name:
9354 * @event: the MonoEvent to act on
9356 * Returns: the name of the event.
9359 mono_event_get_name (MonoEvent *event)
9365 * mono_event_get_add_method:
9366 * @event: The MonoEvent to act on.
9368 * Returns: the @add' method for the event (a MonoMethod).
9371 mono_event_get_add_method (MonoEvent *event)
9377 * mono_event_get_remove_method:
9378 * @event: The MonoEvent to act on.
9380 * Returns: the @remove method for the event (a MonoMethod).
9383 mono_event_get_remove_method (MonoEvent *event)
9385 return event->remove;
9389 * mono_event_get_raise_method:
9390 * @event: The MonoEvent to act on.
9392 * Returns: the @raise method for the event (a MonoMethod).
9395 mono_event_get_raise_method (MonoEvent *event)
9397 return event->raise;
9401 * mono_event_get_parent:
9402 * @event: the MonoEvent to act on.
9404 * Returns: the MonoClass where the event is defined.
9407 mono_event_get_parent (MonoEvent *event)
9409 return event->parent;
9413 * mono_event_get_flags
9414 * @event: the MonoEvent to act on.
9416 * The metadata flags for an event are encoded using the
9417 * EVENT_* constants. See the tabledefs.h file for details.
9419 * Returns: the flags for the event.
9422 mono_event_get_flags (MonoEvent *event)
9424 return event->attrs;
9428 * mono_class_get_method_from_name:
9429 * @klass: where to look for the method
9430 * @name: name of the method
9431 * @param_count: number of parameters. -1 for any number.
9433 * Obtains a MonoMethod with a given name and number of parameters.
9434 * It only works if there are no multiple signatures for any given method name.
9437 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9439 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9443 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9445 MonoMethod *res = NULL;
9448 /* Search directly in the metadata to avoid calling setup_methods () */
9449 for (i = 0; i < klass->method.count; ++i) {
9450 guint32 cols [MONO_METHOD_SIZE];
9452 MonoMethodSignature *sig;
9454 /* class->method.first points into the methodptr table */
9455 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9457 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9458 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9459 if (param_count == -1) {
9463 sig = mono_method_signature (method);
9464 if (sig && sig->param_count == param_count) {
9475 * mono_class_get_method_from_name_flags:
9476 * @klass: where to look for the method
9477 * @name_space: name of the method
9478 * @param_count: number of parameters. -1 for any number.
9479 * @flags: flags which must be set in the method
9481 * Obtains a MonoMethod with a given name and number of parameters.
9482 * It only works if there are no multiple signatures for any given method name.
9485 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9487 MonoMethod *res = NULL;
9490 mono_class_init (klass);
9492 if (klass->generic_class && !klass->methods) {
9493 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9495 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9499 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9500 mono_class_setup_methods (klass);
9502 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9503 See mono/tests/array_load_exception.il
9504 FIXME we should better report this error to the caller
9506 if (!klass->methods)
9508 for (i = 0; i < klass->method.count; ++i) {
9509 MonoMethod *method = klass->methods [i];
9511 if (method->name[0] == name [0] &&
9512 !strcmp (name, method->name) &&
9513 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9514 ((method->flags & flags) == flags)) {
9521 res = find_method_in_metadata (klass, name, param_count, flags);
9528 * mono_class_set_failure:
9529 * @klass: class in which the failure was detected
9530 * @ex_type: the kind of exception/error to be thrown (later)
9531 * @ex_data: exception data (specific to each type of exception/error)
9533 * Keep a detected failure informations in the class for later processing.
9534 * Note that only the first failure is kept.
9536 * LOCKING: Acquires the loader lock.
9539 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9541 if (klass->exception_type)
9544 mono_loader_lock ();
9545 klass->exception_type = ex_type;
9547 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9548 mono_loader_unlock ();
9554 * mono_class_get_exception_data:
9556 * Return the exception_data property of KLASS.
9558 * LOCKING: Acquires the loader lock.
9561 mono_class_get_exception_data (MonoClass *klass)
9563 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9567 * mono_classes_init:
9569 * Initialize the resources used by this module.
9572 mono_classes_init (void)
9574 mono_mutex_init (&classes_mutex);
9576 mono_counters_register ("Inflated methods size",
9577 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9578 mono_counters_register ("Inflated classes",
9579 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9580 mono_counters_register ("Inflated classes size",
9581 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9582 mono_counters_register ("MonoClass size",
9583 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9584 mono_counters_register ("MonoClassExt size",
9585 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9589 * mono_classes_cleanup:
9591 * Free the resources used by this module.
9594 mono_classes_cleanup (void)
9596 if (global_interface_bitset)
9597 mono_bitset_free (global_interface_bitset);
9598 global_interface_bitset = NULL;
9599 mono_mutex_destroy (&classes_mutex);
9603 * mono_class_get_exception_for_failure:
9604 * @klass: class in which the failure was detected
9606 * Return a constructed MonoException than the caller can then throw
9607 * using mono_raise_exception - or NULL if no failure is present (or
9608 * doesn't result in an exception).
9611 mono_class_get_exception_for_failure (MonoClass *klass)
9613 gpointer exception_data = mono_class_get_exception_data (klass);
9615 switch (klass->exception_type) {
9616 #ifndef DISABLE_SECURITY
9617 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9618 MonoDomain *domain = mono_domain_get ();
9619 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9620 MonoMethod *method = exception_data;
9621 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9622 MonoObject *exc = NULL;
9626 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9627 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9628 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9630 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9631 return (MonoException*) exc;
9634 case MONO_EXCEPTION_TYPE_LOAD: {
9637 char *str = mono_type_get_full_name (klass);
9638 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9639 name = mono_string_new (mono_domain_get (), str);
9641 ex = mono_get_exception_type_load (name, astr);
9645 case MONO_EXCEPTION_MISSING_METHOD: {
9646 char *class_name = exception_data;
9647 char *assembly_name = class_name + strlen (class_name) + 1;
9649 return mono_get_exception_missing_method (class_name, assembly_name);
9651 case MONO_EXCEPTION_MISSING_FIELD: {
9652 char *class_name = exception_data;
9653 char *member_name = class_name + strlen (class_name) + 1;
9655 return mono_get_exception_missing_field (class_name, member_name);
9657 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9658 char *msg_format = exception_data;
9659 char *assembly_name = msg_format + strlen (msg_format) + 1;
9660 char *msg = g_strdup_printf (msg_format, assembly_name);
9663 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9669 case MONO_EXCEPTION_BAD_IMAGE: {
9670 return mono_get_exception_bad_image_format (exception_data);
9673 MonoLoaderError *error;
9676 error = mono_loader_get_last_error ();
9678 ex = mono_loader_error_prepare_exception (error);
9682 /* TODO - handle other class related failures */
9689 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9691 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9692 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9694 if (outer_klass == inner_klass)
9696 inner_klass = inner_klass->nested_in;
9697 } while (inner_klass);
9702 mono_class_get_generic_type_definition (MonoClass *klass)
9704 return klass->generic_class ? klass->generic_class->container_class : klass;
9708 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9710 * Generic instantiations are ignored for all super types of @klass.
9712 * Visibility checks ignoring generic instantiations.
9715 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9718 klass = mono_class_get_generic_type_definition (klass);
9719 parent = mono_class_get_generic_type_definition (parent);
9720 mono_class_setup_supertypes (klass);
9722 for (i = 0; i < klass->idepth; ++i) {
9723 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9729 * Subtype can only access parent members with family protection if the site object
9730 * is subclass of Subtype. For example:
9731 * class A { protected int x; }
9733 * void valid_access () {
9737 * void invalid_access () {
9744 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9746 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9749 if (context_klass == NULL)
9751 /*if access_klass is not member_klass context_klass must be type compat*/
9752 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9758 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9761 if (accessing == accessed)
9763 if (!accessed || !accessing)
9766 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9767 * anywhere so untrusted friends are not safe to access platform's code internals */
9768 if (mono_security_core_clr_enabled ()) {
9769 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9773 mono_assembly_load_friends (accessed);
9774 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9775 MonoAssemblyName *friend = tmp->data;
9776 /* Be conservative with checks */
9779 if (strcmp (accessing->aname.name, friend->name))
9781 if (friend->public_key_token [0]) {
9782 if (!accessing->aname.public_key_token [0])
9784 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9793 * If klass is a generic type or if it is derived from a generic type, return the
9794 * MonoClass of the generic definition
9795 * Returns NULL if not found
9798 get_generic_definition_class (MonoClass *klass)
9801 if (klass->generic_class && klass->generic_class->container_class)
9802 return klass->generic_class->container_class;
9803 klass = klass->parent;
9809 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9812 for (i = 0; i < ginst->type_argc; ++i) {
9813 MonoType *type = ginst->type_argv[i];
9814 switch (type->type) {
9815 case MONO_TYPE_SZARRAY:
9816 if (!can_access_type (access_klass, type->data.klass))
9819 case MONO_TYPE_ARRAY:
9820 if (!can_access_type (access_klass, type->data.array->eklass))
9824 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9827 case MONO_TYPE_CLASS:
9828 case MONO_TYPE_VALUETYPE:
9829 case MONO_TYPE_GENERICINST:
9830 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9838 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9842 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9845 if (access_klass->element_class && !access_klass->enumtype)
9846 access_klass = access_klass->element_class;
9848 if (member_klass->element_class && !member_klass->enumtype)
9849 member_klass = member_klass->element_class;
9851 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9853 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9856 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9859 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9862 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9865 /*Non nested type with nested visibility. We just fail it.*/
9866 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9869 switch (access_level) {
9870 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9871 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9873 case TYPE_ATTRIBUTE_PUBLIC:
9876 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9879 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9880 return is_nesting_type (member_klass, access_klass);
9882 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9883 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9885 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9886 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9888 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9889 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9890 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9892 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9893 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9894 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9899 /* FIXME: check visibility of type, too */
9901 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9903 MonoClass *member_generic_def;
9904 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9907 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9908 access_klass->generic_container) &&
9909 (member_generic_def = get_generic_definition_class (member_klass))) {
9910 MonoClass *access_container;
9912 if (access_klass->generic_container)
9913 access_container = access_klass;
9915 access_container = access_klass->generic_class->container_class;
9917 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9921 /* Partition I 8.5.3.2 */
9922 /* the access level values are the same for fields and methods */
9923 switch (access_level) {
9924 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9925 /* same compilation unit */
9926 return access_klass->image == member_klass->image;
9927 case FIELD_ATTRIBUTE_PRIVATE:
9928 return access_klass == member_klass;
9929 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9930 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9931 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9934 case FIELD_ATTRIBUTE_ASSEMBLY:
9935 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9936 case FIELD_ATTRIBUTE_FAMILY:
9937 if (is_valid_family_access (access_klass, member_klass, context_klass))
9940 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9941 if (is_valid_family_access (access_klass, member_klass, context_klass))
9943 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9944 case FIELD_ATTRIBUTE_PUBLIC:
9951 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9953 /* FIXME: check all overlapping fields */
9954 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9956 MonoClass *nested = method->klass->nested_in;
9958 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9961 nested = nested->nested_in;
9968 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9970 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9972 MonoClass *nested = method->klass->nested_in;
9974 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9977 nested = nested->nested_in;
9982 * with generics calls to explicit interface implementations can be expressed
9983 * directly: the method is private, but we must allow it. This may be opening
9984 * a hole or the generics code should handle this differently.
9985 * Maybe just ensure the interface type is public.
9987 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9993 * mono_method_can_access_method_full:
9994 * @method: The caller method
9995 * @called: The called method
9996 * @context_klass: The static type on stack of the owner @called object used
9998 * This function must be used with instance calls, as they have more strict family accessibility.
9999 * It can be used with static methods, but context_klass should be NULL.
10001 * Returns: TRUE if caller have proper visibility and acessibility to @called
10004 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10006 MonoClass *access_class = method->klass;
10007 MonoClass *member_class = called->klass;
10008 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10010 MonoClass *nested = access_class->nested_in;
10012 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10015 nested = nested->nested_in;
10022 can = can_access_type (access_class, member_class);
10024 MonoClass *nested = access_class->nested_in;
10026 can = can_access_type (nested, member_class);
10029 nested = nested->nested_in;
10036 if (called->is_inflated) {
10037 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10038 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10047 * mono_method_can_access_field_full:
10048 * @method: The caller method
10049 * @field: The accessed field
10050 * @context_klass: The static type on stack of the owner @field object used
10052 * This function must be used with instance fields, as they have more strict family accessibility.
10053 * It can be used with static fields, but context_klass should be NULL.
10055 * Returns: TRUE if caller have proper visibility and acessibility to @field
10058 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10060 MonoClass *access_class = method->klass;
10061 MonoClass *member_class = field->parent;
10062 /* FIXME: check all overlapping fields */
10063 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10065 MonoClass *nested = access_class->nested_in;
10067 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10070 nested = nested->nested_in;
10077 can = can_access_type (access_class, member_class);
10079 MonoClass *nested = access_class->nested_in;
10081 can = can_access_type (nested, member_class);
10084 nested = nested->nested_in;
10094 * mono_class_can_access_class:
10095 * @source_class: The source class
10096 * @target_class: The accessed class
10098 * This function returns is @target_class is visible to @source_class
10100 * Returns: TRUE if source have proper visibility and acessibility to target
10103 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10105 return can_access_type (source_class, target_class);
10109 * mono_type_is_valid_enum_basetype:
10110 * @type: The MonoType to check
10112 * Returns: TRUE if the type can be used as the basetype of an enum
10114 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10115 switch (type->type) {
10118 case MONO_TYPE_BOOLEAN:
10121 case MONO_TYPE_CHAR:
10134 * mono_class_is_valid_enum:
10135 * @klass: An enum class to be validated
10137 * This method verify the required properties an enum should have.
10139 * Returns: TRUE if the informed enum class is valid
10141 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10142 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10143 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10145 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10146 MonoClassField * field;
10147 gpointer iter = NULL;
10148 gboolean found_base_field = FALSE;
10150 g_assert (klass->enumtype);
10151 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10152 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10156 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10159 while ((field = mono_class_get_fields (klass, &iter))) {
10160 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10161 if (found_base_field)
10163 found_base_field = TRUE;
10164 if (!mono_type_is_valid_enum_basetype (field->type))
10169 if (!found_base_field)
10172 if (klass->method.count > 0)
10179 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10181 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10185 * mono_class_setup_interface_id:
10187 * Initializes MonoClass::interface_id if required.
10189 * LOCKING: Acquires the loader lock.
10192 mono_class_setup_interface_id (MonoClass *class)
10194 mono_loader_lock ();
10195 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10196 class->interface_id = mono_get_unique_iid (class);
10197 mono_loader_unlock ();
10201 * mono_class_alloc_ext:
10203 * Allocate klass->ext if not already done.
10206 mono_class_alloc_ext (MonoClass *klass)
10213 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10214 mono_image_lock (klass->image);
10215 mono_memory_barrier ();
10218 class_ext_size += sizeof (MonoClassExt);
10219 mono_image_unlock (klass->image);
10223 * mono_class_setup_interfaces:
10225 * Initialize class->interfaces/interfaces_count.
10226 * LOCKING: Acquires the loader lock.
10227 * This function can fail the type.
10230 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10232 int i, interface_count;
10233 MonoClass **interfaces;
10235 mono_error_init (error);
10237 if (klass->interfaces_inited)
10240 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10241 MonoType *args [1];
10243 /* generic IList, ICollection, IEnumerable */
10244 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10245 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10247 args [0] = &klass->element_class->byval_arg;
10248 interfaces [0] = mono_class_bind_generic_parameters (
10249 mono_defaults.generic_ilist_class, 1, args, FALSE);
10250 if (interface_count > 1)
10251 interfaces [1] = mono_class_bind_generic_parameters (
10252 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10253 } else if (klass->generic_class) {
10254 MonoClass *gklass = klass->generic_class->container_class;
10256 mono_class_setup_interfaces (gklass, error);
10257 if (!mono_error_ok (error)) {
10258 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10262 interface_count = gklass->interface_count;
10263 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10264 for (i = 0; i < interface_count; i++) {
10265 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10266 if (!mono_error_ok (error)) {
10267 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10272 interface_count = 0;
10276 mono_image_lock (klass->image);
10278 if (!klass->interfaces_inited) {
10279 klass->interface_count = interface_count;
10280 klass->interfaces = interfaces;
10282 mono_memory_barrier ();
10284 klass->interfaces_inited = TRUE;
10287 mono_image_unlock (klass->image);
10291 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10293 MonoClass *class = field->parent;
10294 MonoImage *image = class->image;
10295 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10296 int field_idx = field - class->fields;
10298 mono_error_init (error);
10301 MonoClassField *gfield = >d->fields [field_idx];
10302 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10303 if (!mono_error_ok (error)) {
10304 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10305 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10309 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10310 if (!mono_error_ok (error)) {
10311 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10312 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10317 guint32 cols [MONO_FIELD_SIZE];
10318 MonoGenericContainer *container = NULL;
10319 int idx = class->field.first + field_idx;
10321 /*FIXME, in theory we do not lazy load SRE fields*/
10322 g_assert (!image_is_dynamic (image));
10324 if (class->generic_container) {
10325 container = class->generic_container;
10327 container = gtd->generic_container;
10328 g_assert (container);
10331 /* class->field.first and idx points into the fieldptr table */
10332 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10334 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10335 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10336 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10340 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10342 mono_metadata_decode_value (sig, &sig);
10343 /* FIELD signature == 0x06 */
10344 g_assert (*sig == 0x06);
10345 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10347 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10352 mono_field_resolve_flags (MonoClassField *field)
10354 MonoClass *class = field->parent;
10355 MonoImage *image = class->image;
10356 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10357 int field_idx = field - class->fields;
10361 MonoClassField *gfield = >d->fields [field_idx];
10362 return mono_field_get_flags (gfield);
10364 int idx = class->field.first + field_idx;
10366 /*FIXME, in theory we do not lazy load SRE fields*/
10367 g_assert (!image_is_dynamic (image));
10369 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10374 * mono_class_setup_basic_field_info:
10375 * @class: The class to initialize
10377 * Initializes the class->fields array of fields.
10378 * Aquires the loader lock.
10381 mono_class_setup_basic_field_info_locking (MonoClass *class)
10383 mono_loader_lock ();
10384 mono_class_setup_basic_field_info (class);
10385 mono_loader_unlock ();
10389 * mono_class_get_fields_lazy:
10390 * @klass: the MonoClass to act on
10392 * This routine is an iterator routine for retrieving the fields in a class.
10393 * Only minimal information about fields are loaded. Accessors must be used
10394 * for all MonoClassField returned.
10396 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10397 * iterate over all of the elements. When no more values are
10398 * available, the return value is NULL.
10400 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10403 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10405 MonoClassField* field;
10409 mono_class_setup_basic_field_info_locking (klass);
10410 if (!klass->fields)
10412 /* start from the first */
10413 if (klass->field.count) {
10414 return *iter = &klass->fields [0];
10422 if (field < &klass->fields [klass->field.count]) {
10423 return *iter = field;
10429 mono_class_full_name (MonoClass *klass)
10431 return mono_type_full_name (&klass->byval_arg);