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:
1948 for (i = 0; i < top; i++) {
1953 field = &class->fields [i];
1956 * There must be info about all the fields in a type if it
1957 * uses explicit layout.
1960 if (mono_field_is_deleted (field))
1962 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1965 size = mono_type_size (field->type, &align);
1966 align = class->packing_size ? MIN (class->packing_size, align): align;
1967 class->min_align = MAX (align, class->min_align);
1970 * When we get here, field->offset is already set by the
1971 * loader (for either runtime fields or fields loaded from metadata).
1972 * The offset is from the start of the object: this works for both
1973 * classes and valuetypes.
1975 field->offset += sizeof (MonoObject);
1976 ftype = mono_type_get_underlying_type (field->type);
1977 ftype = mono_type_get_basic_type_from_generic (ftype);
1978 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1979 if (field->offset % sizeof (gpointer)) {
1980 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1987 real_size = MAX (real_size, size + field->offset);
1989 class->instance_size = MAX (real_size, class->instance_size);
1990 if (class->instance_size & (class->min_align - 1)) {
1991 class->instance_size += class->min_align - 1;
1992 class->instance_size &= ~(class->min_align - 1);
1997 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1999 * For small structs, set min_align to at least the struct size to improve
2000 * performance, and since the JIT memset/memcpy code assumes this and generates
2001 * unaligned accesses otherwise. See #78990 for a testcase.
2003 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2004 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2007 mono_memory_barrier ();
2008 class->size_inited = 1;
2011 * Compute static field layout and size
2013 for (i = 0; i < top; i++){
2017 field = &class->fields [i];
2019 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2021 if (mono_field_is_deleted (field))
2024 if (mono_type_has_exceptions (field->type)) {
2025 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2029 has_static_fields = TRUE;
2031 size = mono_type_size (field->type, &align);
2032 field->offset = class->sizes.class_size;
2033 /*align is always non-zero here*/
2034 field->offset += align - 1;
2035 field->offset &= ~(align - 1);
2036 class->sizes.class_size = field->offset + size;
2039 if (has_static_fields && class->sizes.class_size == 0)
2040 /* Simplify code which depends on class_size != 0 if the class has static fields */
2041 class->sizes.class_size = 8;
2045 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2049 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2050 method->klass = class;
2051 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2052 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2053 method->signature = sig;
2054 method->name = name;
2057 if (name [0] == '.') {
2058 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2060 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2066 * mono_class_setup_methods:
2069 * Initializes the 'methods' array in CLASS.
2070 * Calling this method should be avoided if possible since it allocates a lot
2071 * of long-living MonoMethod structures.
2072 * Methods belonging to an interface are assigned a sequential slot starting
2075 * On failure this function sets class->exception_type
2078 mono_class_setup_methods (MonoClass *class)
2081 MonoMethod **methods;
2086 if (class->generic_class) {
2088 MonoClass *gklass = class->generic_class->container_class;
2090 mono_class_init (gklass);
2091 if (!gklass->exception_type)
2092 mono_class_setup_methods (gklass);
2093 if (gklass->exception_type) {
2094 /* FIXME make exception_data less opaque so it's possible to dup it here */
2095 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2099 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2100 count = gklass->method.count;
2101 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2103 for (i = 0; i < count; i++) {
2104 methods [i] = mono_class_inflate_generic_method_full_checked (
2105 gklass->methods [i], class, mono_class_get_context (class), &error);
2106 if (!mono_error_ok (&error)) {
2107 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2108 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)));
2111 mono_error_cleanup (&error);
2115 } else if (class->rank) {
2117 MonoMethod *amethod;
2118 MonoMethodSignature *sig;
2119 int count_generic = 0, first_generic = 0;
2122 count = 3 + (class->rank > 1? 2: 1);
2124 mono_class_setup_interfaces (class, &error);
2125 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2127 if (class->interface_count) {
2128 count_generic = generic_array_methods (class);
2129 first_generic = count;
2130 count += class->interface_count * count_generic;
2133 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2135 sig = mono_metadata_signature_alloc (class->image, class->rank);
2136 sig->ret = &mono_defaults.void_class->byval_arg;
2137 sig->pinvoke = TRUE;
2138 sig->hasthis = TRUE;
2139 for (i = 0; i < class->rank; ++i)
2140 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2142 amethod = create_array_method (class, ".ctor", sig);
2143 methods [method_num++] = amethod;
2144 if (class->rank > 1) {
2145 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2146 sig->ret = &mono_defaults.void_class->byval_arg;
2147 sig->pinvoke = TRUE;
2148 sig->hasthis = TRUE;
2149 for (i = 0; i < class->rank * 2; ++i)
2150 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2152 amethod = create_array_method (class, ".ctor", sig);
2153 methods [method_num++] = amethod;
2155 /* element Get (idx11, [idx2, ...]) */
2156 sig = mono_metadata_signature_alloc (class->image, class->rank);
2157 sig->ret = &class->element_class->byval_arg;
2158 sig->pinvoke = TRUE;
2159 sig->hasthis = TRUE;
2160 for (i = 0; i < class->rank; ++i)
2161 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2162 amethod = create_array_method (class, "Get", sig);
2163 methods [method_num++] = amethod;
2164 /* element& Address (idx11, [idx2, ...]) */
2165 sig = mono_metadata_signature_alloc (class->image, class->rank);
2166 sig->ret = &class->element_class->this_arg;
2167 sig->pinvoke = TRUE;
2168 sig->hasthis = TRUE;
2169 for (i = 0; i < class->rank; ++i)
2170 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2171 amethod = create_array_method (class, "Address", sig);
2172 methods [method_num++] = amethod;
2173 /* void Set (idx11, [idx2, ...], element) */
2174 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
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;
2180 sig->params [i] = &class->element_class->byval_arg;
2181 amethod = create_array_method (class, "Set", sig);
2182 methods [method_num++] = amethod;
2184 for (i = 0; i < class->interface_count; i++)
2185 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2187 count = class->method.count;
2188 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2189 for (i = 0; i < count; ++i) {
2190 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2191 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2195 if (MONO_CLASS_IS_INTERFACE (class)) {
2197 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2198 for (i = 0; i < count; ++i) {
2199 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2200 methods [i]->slot = slot++;
2204 mono_image_lock (class->image);
2206 if (!class->methods) {
2207 class->method.count = count;
2209 /* Needed because of the double-checking locking pattern */
2210 mono_memory_barrier ();
2212 class->methods = methods;
2215 mono_image_unlock (class->image);
2219 * mono_class_get_method_by_index:
2221 * Returns class->methods [index], initializing class->methods if neccesary.
2223 * LOCKING: Acquires the loader lock.
2226 mono_class_get_method_by_index (MonoClass *class, int index)
2228 /* Avoid calling setup_methods () if possible */
2229 if (class->generic_class && !class->methods) {
2230 MonoClass *gklass = class->generic_class->container_class;
2233 m = mono_class_inflate_generic_method_full (
2234 gklass->methods [index], class, mono_class_get_context (class));
2236 * If setup_methods () is called later for this class, no duplicates are created,
2237 * since inflate_generic_method guarantees that only one instance of a method
2238 * is created for each context.
2241 mono_class_setup_methods (class);
2242 g_assert (m == class->methods [index]);
2246 mono_class_setup_methods (class);
2247 if (class->exception_type) /*FIXME do proper error handling*/
2249 g_assert (index >= 0 && index < class->method.count);
2250 return class->methods [index];
2255 * mono_class_get_inflated_method:
2257 * Given an inflated class CLASS and a method METHOD which should be a method of
2258 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2261 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2263 MonoClass *gklass = class->generic_class->container_class;
2266 g_assert (method->klass == gklass);
2268 mono_class_setup_methods (gklass);
2269 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2271 for (i = 0; i < gklass->method.count; ++i) {
2272 if (gklass->methods [i] == method) {
2274 return class->methods [i];
2276 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2284 * mono_class_get_vtable_entry:
2286 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2287 * LOCKING: Acquires the loader lock.
2290 mono_class_get_vtable_entry (MonoClass *class, int offset)
2294 if (class->rank == 1) {
2296 * szarrays do not overwrite any methods of Array, so we can avoid
2297 * initializing their vtables in some cases.
2299 mono_class_setup_vtable (class->parent);
2300 if (offset < class->parent->vtable_size)
2301 return class->parent->vtable [offset];
2304 if (class->generic_class) {
2305 MonoClass *gklass = class->generic_class->container_class;
2306 mono_class_setup_vtable (gklass);
2307 m = gklass->vtable [offset];
2309 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2311 mono_class_setup_vtable (class);
2312 if (class->exception_type)
2314 m = class->vtable [offset];
2321 * mono_class_get_vtable_size:
2323 * Return the vtable size for KLASS.
2326 mono_class_get_vtable_size (MonoClass *klass)
2328 mono_class_setup_vtable (klass);
2330 return klass->vtable_size;
2334 * mono_class_setup_properties:
2336 * Initialize class->ext.property and class->ext.properties.
2338 * This method can fail the class.
2341 mono_class_setup_properties (MonoClass *class)
2343 guint startm, endm, i, j;
2344 guint32 cols [MONO_PROPERTY_SIZE];
2345 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2346 MonoProperty *properties;
2350 if (class->ext && class->ext->properties)
2353 if (class->generic_class) {
2354 MonoClass *gklass = class->generic_class->container_class;
2356 mono_class_init (gklass);
2357 mono_class_setup_properties (gklass);
2358 if (gklass->exception_type) {
2359 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2363 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2365 for (i = 0; i < gklass->ext->property.count; i++) {
2366 MonoProperty *prop = &properties [i];
2368 *prop = gklass->ext->properties [i];
2371 prop->get = mono_class_inflate_generic_method_full (
2372 prop->get, class, mono_class_get_context (class));
2374 prop->set = mono_class_inflate_generic_method_full (
2375 prop->set, class, mono_class_get_context (class));
2377 prop->parent = class;
2380 first = gklass->ext->property.first;
2381 count = gklass->ext->property.count;
2383 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2384 count = last - first;
2387 mono_class_setup_methods (class);
2388 if (class->exception_type)
2392 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2393 for (i = first; i < last; ++i) {
2394 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2395 properties [i - first].parent = class;
2396 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2397 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2399 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2400 for (j = startm; j < endm; ++j) {
2403 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2405 if (class->image->uncompressed_metadata)
2406 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2407 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2409 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2411 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2412 case METHOD_SEMANTIC_SETTER:
2413 properties [i - first].set = method;
2415 case METHOD_SEMANTIC_GETTER:
2416 properties [i - first].get = method;
2425 mono_class_alloc_ext (class);
2427 mono_image_lock (class->image);
2429 if (class->ext->properties) {
2430 /* We leak 'properties' which was allocated from the image mempool */
2431 mono_image_unlock (class->image);
2435 class->ext->property.first = first;
2436 class->ext->property.count = count;
2438 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2439 mono_memory_barrier ();
2441 /* Leave this assignment as the last op in the function */
2442 class->ext->properties = properties;
2444 mono_image_unlock (class->image);
2448 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2450 MonoMethod **om, **retval;
2453 for (om = methods, count = 0; *om; ++om, ++count)
2456 retval = g_new0 (MonoMethod*, count + 1);
2458 for (om = methods, count = 0; *om; ++om, ++count)
2459 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2464 /*This method can fail the class.*/
2466 mono_class_setup_events (MonoClass *class)
2469 guint startm, endm, i, j;
2470 guint32 cols [MONO_EVENT_SIZE];
2471 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2475 if (class->ext && class->ext->events)
2478 if (class->generic_class) {
2479 MonoClass *gklass = class->generic_class->container_class;
2480 MonoGenericContext *context = NULL;
2482 mono_class_setup_events (gklass);
2483 if (gklass->exception_type) {
2484 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2488 first = gklass->ext->event.first;
2489 count = gklass->ext->event.count;
2491 events = mono_class_new0 (class, MonoEvent, count);
2494 context = mono_class_get_context (class);
2496 for (i = 0; i < count; i++) {
2497 MonoEvent *event = &events [i];
2498 MonoEvent *gevent = &gklass->ext->events [i];
2500 event->parent = class;
2501 event->name = gevent->name;
2502 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2503 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2504 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2505 #ifndef MONO_SMALL_CONFIG
2506 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2508 event->attrs = gevent->attrs;
2511 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2512 count = last - first;
2515 mono_class_setup_methods (class);
2516 if (class->exception_type) {
2517 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2522 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2523 for (i = first; i < last; ++i) {
2524 MonoEvent *event = &events [i - first];
2526 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2527 event->parent = class;
2528 event->attrs = cols [MONO_EVENT_FLAGS];
2529 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2531 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2532 for (j = startm; j < endm; ++j) {
2535 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2537 if (class->image->uncompressed_metadata)
2538 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2539 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2541 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2543 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2544 case METHOD_SEMANTIC_ADD_ON:
2545 event->add = method;
2547 case METHOD_SEMANTIC_REMOVE_ON:
2548 event->remove = method;
2550 case METHOD_SEMANTIC_FIRE:
2551 event->raise = method;
2553 case METHOD_SEMANTIC_OTHER: {
2554 #ifndef MONO_SMALL_CONFIG
2557 if (event->other == NULL) {
2558 event->other = g_new0 (MonoMethod*, 2);
2560 while (event->other [n])
2562 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2564 event->other [n] = method;
2565 /* NULL terminated */
2566 event->other [n + 1] = NULL;
2577 mono_class_alloc_ext (class);
2579 mono_image_lock (class->image);
2581 if (class->ext->events) {
2582 mono_image_unlock (class->image);
2586 class->ext->event.first = first;
2587 class->ext->event.count = count;
2589 /* Flush any pending writes as we do double checked locking on class->ext.events */
2590 mono_memory_barrier ();
2592 /* Leave this assignment as the last op in the function */
2593 class->ext->events = events;
2595 mono_image_unlock (class->image);
2599 * Global pool of interface IDs, represented as a bitset.
2600 * LOCKING: Protected by the classes lock.
2602 static MonoBitSet *global_interface_bitset = NULL;
2605 * mono_unload_interface_ids:
2606 * @bitset: bit set of interface IDs
2608 * When an image is unloaded, the interface IDs associated with
2609 * the image are put back in the global pool of IDs so the numbers
2613 mono_unload_interface_ids (MonoBitSet *bitset)
2616 mono_bitset_sub (global_interface_bitset, bitset);
2621 mono_unload_interface_id (MonoClass *class)
2623 if (global_interface_bitset && class->interface_id) {
2625 mono_bitset_clear (global_interface_bitset, class->interface_id);
2631 * mono_get_unique_iid:
2634 * Assign a unique integer ID to the interface represented by @class.
2635 * The ID will positive and as small as possible.
2636 * LOCKING: Acquires the classes lock.
2637 * Returns: the new ID.
2640 mono_get_unique_iid (MonoClass *class)
2644 g_assert (MONO_CLASS_IS_INTERFACE (class));
2648 if (!global_interface_bitset) {
2649 global_interface_bitset = mono_bitset_new (128, 0);
2652 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2654 int old_size = mono_bitset_size (global_interface_bitset);
2655 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2656 mono_bitset_free (global_interface_bitset);
2657 global_interface_bitset = new_set;
2660 mono_bitset_set (global_interface_bitset, iid);
2661 /* set the bit also in the per-image set */
2662 if (!class->generic_class) {
2663 if (class->image->interface_bitset) {
2664 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2665 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2666 mono_bitset_free (class->image->interface_bitset);
2667 class->image->interface_bitset = new_set;
2670 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2672 mono_bitset_set (class->image->interface_bitset, iid);
2677 #ifndef MONO_SMALL_CONFIG
2678 if (mono_print_vtable) {
2680 char *type_name = mono_type_full_name (&class->byval_arg);
2681 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2682 generic_id = class->generic_class->context.class_inst->id;
2683 g_assert (generic_id != 0);
2687 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2692 g_assert (iid <= 65535);
2697 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2702 mono_class_setup_interfaces (klass, error);
2703 if (!mono_error_ok (error))
2706 for (i = 0; i < klass->interface_count; i++) {
2707 ic = klass->interfaces [i];
2710 *res = g_ptr_array_new ();
2711 g_ptr_array_add (*res, ic);
2712 mono_class_init (ic);
2713 if (ic->exception_type) {
2714 mono_error_set_type_load_class (error, ic, "Error Loading class");
2718 collect_implemented_interfaces_aux (ic, res, error);
2719 if (!mono_error_ok (error))
2725 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2727 GPtrArray *res = NULL;
2729 collect_implemented_interfaces_aux (klass, &res, error);
2730 if (!mono_error_ok (error)) {
2732 g_ptr_array_free (res, TRUE);
2739 compare_interface_ids (const void *p_key, const void *p_element) {
2740 const MonoClass *key = p_key;
2741 const MonoClass *element = *(MonoClass**) p_element;
2743 return (key->interface_id - element->interface_id);
2746 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2748 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2749 MonoClass **result = mono_binary_search (
2751 klass->interfaces_packed,
2752 klass->interface_offsets_count,
2753 sizeof (MonoClass *),
2754 compare_interface_ids);
2756 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2763 * mono_class_interface_offset_with_variance:
2765 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2766 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2768 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2770 * FIXME figure out MS disambiguation rules and fix this function.
2773 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2774 int i = mono_class_interface_offset (klass, itf);
2775 *non_exact_match = FALSE;
2779 if (!mono_class_has_variant_generic_params (itf))
2782 for (i = 0; i < klass->interface_offsets_count; i++) {
2783 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2784 *non_exact_match = TRUE;
2785 return klass->interface_offsets_packed [i];
2793 print_implemented_interfaces (MonoClass *klass) {
2796 GPtrArray *ifaces = NULL;
2798 int ancestor_level = 0;
2800 name = mono_type_get_full_name (klass);
2801 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2804 for (i = 0; i < klass->interface_offsets_count; i++)
2805 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2806 klass->interfaces_packed [i]->interface_id,
2807 klass->interface_offsets_packed [i],
2808 klass->interfaces_packed [i]->method.count,
2809 klass->interfaces_packed [i]->name_space,
2810 klass->interfaces_packed [i]->name );
2811 printf ("Interface flags: ");
2812 for (i = 0; i <= klass->max_interface_id; i++)
2813 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2814 printf ("(%d,T)", i);
2816 printf ("(%d,F)", i);
2818 printf ("Dump interface flags:");
2819 #ifdef COMPRESSED_INTERFACE_BITMAP
2821 const uint8_t* p = klass->interface_bitmap;
2822 i = klass->max_interface_id;
2824 printf (" %d x 00 %02X", p [0], p [1]);
2830 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2831 printf (" %02X", klass->interface_bitmap [i]);
2834 while (klass != NULL) {
2835 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2836 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2837 if (!mono_error_ok (&error)) {
2838 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2839 mono_error_cleanup (&error);
2840 } else if (ifaces) {
2841 for (i = 0; i < ifaces->len; i++) {
2842 MonoClass *ic = g_ptr_array_index (ifaces, i);
2843 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2844 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2846 mono_class_interface_offset (klass, ic),
2851 g_ptr_array_free (ifaces, TRUE);
2854 klass = klass->parent;
2859 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2862 args [0] = &arg0->byval_arg;
2864 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2868 array_class_get_if_rank (MonoClass *class, guint rank)
2870 return rank ? mono_array_class_get (class, rank) : class;
2874 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2876 valuetype_types [0] = eclass;
2877 if (eclass == mono_defaults.int16_class)
2878 valuetype_types [1] = mono_defaults.uint16_class;
2879 else if (eclass == mono_defaults.uint16_class)
2880 valuetype_types [1] = mono_defaults.int16_class;
2881 else if (eclass == mono_defaults.int32_class)
2882 valuetype_types [1] = mono_defaults.uint32_class;
2883 else if (eclass == mono_defaults.uint32_class)
2884 valuetype_types [1] = mono_defaults.int32_class;
2885 else if (eclass == mono_defaults.int64_class)
2886 valuetype_types [1] = mono_defaults.uint64_class;
2887 else if (eclass == mono_defaults.uint64_class)
2888 valuetype_types [1] = mono_defaults.int64_class;
2889 else if (eclass == mono_defaults.byte_class)
2890 valuetype_types [1] = mono_defaults.sbyte_class;
2891 else if (eclass == mono_defaults.sbyte_class)
2892 valuetype_types [1] = mono_defaults.byte_class;
2893 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2894 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2897 /* this won't be needed once bug #325495 is completely fixed
2898 * though we'll need something similar to know which interfaces to allow
2899 * in arrays when they'll be lazyly created
2901 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2902 * MS returns diferrent types based on which instance is called. For example:
2903 * object obj = new byte[10][];
2904 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2905 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2908 * Fixing this should kill quite some code, save some bits and improve compatibility.
2911 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2913 MonoClass *eclass = class->element_class;
2914 static MonoClass* generic_icollection_class = NULL;
2915 static MonoClass* generic_ienumerable_class = NULL;
2916 static MonoClass* generic_ienumerator_class = NULL;
2917 static MonoClass* generic_ireadonlylist_class = NULL;
2918 static MonoClass* generic_ireadonlycollection_class = NULL;
2919 MonoClass *valuetype_types[2] = { NULL, NULL };
2920 MonoClass **interfaces = NULL;
2921 int i, nifaces, interface_count, real_count, original_rank;
2923 gboolean internal_enumerator;
2924 gboolean eclass_is_valuetype;
2926 if (!mono_defaults.generic_ilist_class) {
2930 internal_enumerator = FALSE;
2931 eclass_is_valuetype = FALSE;
2932 original_rank = eclass->rank;
2933 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2934 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2936 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2938 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2939 original_rank = eclass->rank;
2941 eclass = eclass->element_class;
2942 internal_enumerator = TRUE;
2943 *is_enumerator = TRUE;
2951 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2952 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2954 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2956 if (!generic_icollection_class) {
2957 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2958 "System.Collections.Generic", "ICollection`1");
2959 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2960 "System.Collections.Generic", "IEnumerable`1");
2961 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2962 "System.Collections.Generic", "IEnumerator`1");
2963 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2964 "System.Collections.Generic", "IReadOnlyList`1");
2965 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2966 "System.Collections.Generic", "IReadOnlyCollection`1");
2969 mono_class_init (eclass);
2972 * Arrays in 2.0 need to implement a number of generic interfaces
2973 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2974 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2975 * We collect the types needed to build the
2976 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2977 * the generic interfaces needed to implement.
2979 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2980 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2982 if (eclass->valuetype) {
2983 nifaces = generic_ireadonlylist_class ? 5 : 3;
2984 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2986 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2987 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2988 if (internal_enumerator) {
2990 if (valuetype_types [1])
2994 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2995 interfaces [0] = valuetype_types [0];
2996 if (valuetype_types [1])
2997 interfaces [nifaces] = valuetype_types [1];
2999 eclass_is_valuetype = TRUE;
3002 int idepth = eclass->idepth;
3003 if (!internal_enumerator)
3005 nifaces = generic_ireadonlylist_class ? 2 : 3;
3007 // FIXME: This doesn't seem to work/required for generic params
3008 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3009 mono_class_setup_interface_offsets (eclass);
3011 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3012 /* we add object for interfaces and the supertypes for the other
3013 * types. The last of the supertypes is the element class itself which we
3014 * already created the explicit interfaces for (so we include it for IEnumerator
3015 * and exclude it for arrays).
3017 if (MONO_CLASS_IS_INTERFACE (eclass))
3020 interface_count += idepth;
3021 if (eclass->rank && eclass->element_class->valuetype) {
3022 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3023 if (valuetype_types [1])
3026 /* IList, ICollection, IEnumerable, IReadOnlyList */
3027 interface_count *= nifaces;
3028 real_count = interface_count;
3029 if (internal_enumerator) {
3030 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3031 if (valuetype_types [1])
3034 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3035 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3036 interfaces [0] = mono_defaults.object_class;
3040 for (i = 0; i < idepth; i++) {
3041 mono_class_init (eclass->supertypes [i]);
3042 interfaces [j] = eclass->supertypes [i];
3046 if (all_interfaces) {
3047 for (i = 0; i < eclass->interface_offsets_count; i++) {
3048 interfaces [j] = eclass->interfaces_packed [i];
3052 for (i = 0; i < eclass->interface_count; i++) {
3053 interfaces [j] = eclass->interfaces [i];
3057 if (valuetype_types [1]) {
3058 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3063 /* instantiate the generic interfaces */
3064 for (i = 0; i < interface_count; i += nifaces) {
3065 MonoClass *iface = interfaces [i];
3067 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3068 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3070 if (eclass->valuetype) {
3071 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3072 if (generic_ireadonlylist_class) {
3073 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3074 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3077 if (!generic_ireadonlylist_class)
3078 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3081 if (internal_enumerator) {
3083 /* instantiate IEnumerator<iface> */
3084 for (i = 0; i < interface_count; i++) {
3085 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3087 j = interface_count;
3088 if (!eclass_is_valuetype) {
3089 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3090 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3093 for (i = 0; i < eclass->idepth; i++) {
3094 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3098 for (i = 0; i < eclass->interface_offsets_count; i++) {
3099 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3103 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3105 if (valuetype_types [1])
3106 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3110 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3111 for (i = 0; i < real_count; ++i) {
3112 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3113 g_print ("%s implements %s\n", type_name, name);
3124 find_array_interface (MonoClass *klass, const char *name)
3127 for (i = 0; i < klass->interface_count; ++i) {
3128 if (strcmp (klass->interfaces [i]->name, name) == 0)
3135 * Return the number of virtual methods.
3136 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3137 * Return -1 on failure.
3138 * FIXME It would be nice if this information could be cached somewhere.
3141 count_virtual_methods (MonoClass *class)
3145 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3147 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3148 mono_class_setup_methods (class);
3149 if (class->exception_type)
3152 for (i = 0; i < class->method.count; ++i) {
3153 flags = class->methods [i]->flags;
3154 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3158 for (i = 0; i < class->method.count; ++i) {
3159 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3161 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3169 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3177 m = (l + num_ifaces) / 2;
3178 if (interfaces_full [m] == ic)
3180 if (l == num_ifaces)
3182 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3191 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3193 int i = find_interface (num_ifaces, interfaces_full, ic);
3195 return interface_offsets_full [i];
3200 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3202 int i = find_interface (num_ifaces, interfaces_full, ic);
3206 interface_offsets_full [i] = offset;
3209 for (i = 0; i < num_ifaces; ++i) {
3210 if (interfaces_full [i]) {
3212 if (interfaces_full [i]->interface_id < ic->interface_id)
3215 while (end < num_ifaces && interfaces_full [end]) end++;
3216 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3217 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3219 interfaces_full [i] = ic;
3220 interface_offsets_full [i] = offset;
3226 #ifdef COMPRESSED_INTERFACE_BITMAP
3229 * Compressed interface bitmap design.
3231 * Interface bitmaps take a large amount of memory, because their size is
3232 * linear with the maximum interface id assigned in the process (each interface
3233 * is assigned a unique id as it is loaded). The number of interface classes
3234 * is high because of the many implicit interfaces implemented by arrays (we'll
3235 * need to lazy-load them in the future).
3236 * Most classes implement a very small number of interfaces, so the bitmap is
3237 * sparse. This bitmap needs to be checked by interface casts, so access to the
3238 * needed bit must be fast and doable with few jit instructions.
3240 * The current compression format is as follows:
3241 * *) it is a sequence of one or more two-byte elements
3242 * *) the first byte in the element is the count of empty bitmap bytes
3243 * at the current bitmap position
3244 * *) the second byte in the element is an actual bitmap byte at the current
3247 * As an example, the following compressed bitmap bytes:
3248 * 0x07 0x01 0x00 0x7
3249 * correspond to the following bitmap:
3250 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3252 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3253 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3254 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3258 * mono_compress_bitmap:
3259 * @dest: destination buffer
3260 * @bitmap: bitmap buffer
3261 * @size: size of @bitmap in bytes
3263 * This is a mono internal function.
3264 * The @bitmap data is compressed into a format that is small but
3265 * still searchable in few instructions by the JIT and runtime.
3266 * The compressed data is stored in the buffer pointed to by the
3267 * @dest array. Passing a #NULL value for @dest allows to just compute
3268 * the size of the buffer.
3269 * This compression algorithm assumes the bits set in the bitmap are
3270 * few and far between, like in interface bitmaps.
3271 * Returns: the size of the compressed bitmap in bytes.
3274 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3278 const uint8_t *end = bitmap + size;
3279 while (bitmap < end) {
3280 if (*bitmap || numz == 255) {
3304 * mono_class_interface_match:
3305 * @bitmap: a compressed bitmap buffer
3306 * @id: the index to check in the bitmap
3308 * This is a mono internal function.
3309 * Checks if a bit is set in a compressed interface bitmap. @id must
3310 * be already checked for being smaller than the maximum id encoded in the
3313 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3317 mono_class_interface_match (const uint8_t *bitmap, int id)
3320 id -= bitmap [0] * 8;
3324 return bitmap [1] & (1 << id);
3333 * LOCKING: this is supposed to be called with the loader lock held.
3334 * Return -1 on failure and set exception_type
3337 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3341 int i, j, max_iid, num_ifaces;
3342 MonoClass **interfaces_full = NULL;
3343 int *interface_offsets_full = NULL;
3345 GPtrArray **ifaces_array = NULL;
3346 int interface_offsets_count;
3347 MonoClass **array_interfaces = NULL;
3348 int num_array_interfaces;
3349 int is_enumerator = FALSE;
3351 mono_class_setup_supertypes (class);
3353 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3354 * implicit interfaces have the property that they are assigned the same slot in the
3355 * vtables for compatible interfaces
3357 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3359 /* compute maximum number of slots and maximum interface id */
3361 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3362 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3363 for (j = 0; j < class->idepth; j++) {
3364 k = class->supertypes [j];
3365 num_ifaces += k->interface_count;
3366 for (i = 0; i < k->interface_count; i++) {
3367 ic = k->interfaces [i];
3370 mono_class_init (ic);
3372 if (max_iid < ic->interface_id)
3373 max_iid = ic->interface_id;
3375 ifaces = mono_class_get_implemented_interfaces (k, &error);
3376 if (!mono_error_ok (&error)) {
3377 char *name = mono_type_get_full_name (k);
3378 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)));
3380 mono_error_cleanup (&error);
3385 num_ifaces += ifaces->len;
3386 for (i = 0; i < ifaces->len; ++i) {
3387 ic = g_ptr_array_index (ifaces, i);
3388 if (max_iid < ic->interface_id)
3389 max_iid = ic->interface_id;
3391 ifaces_array [j] = ifaces;
3395 for (i = 0; i < num_array_interfaces; ++i) {
3396 ic = array_interfaces [i];
3397 mono_class_init (ic);
3398 if (max_iid < ic->interface_id)
3399 max_iid = ic->interface_id;
3402 if (MONO_CLASS_IS_INTERFACE (class)) {
3404 if (max_iid < class->interface_id)
3405 max_iid = class->interface_id;
3407 class->max_interface_id = max_iid;
3408 /* compute vtable offset for interfaces */
3409 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3410 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3412 for (i = 0; i < num_ifaces; i++) {
3413 interface_offsets_full [i] = -1;
3416 /* skip the current class */
3417 for (j = 0; j < class->idepth - 1; j++) {
3418 k = class->supertypes [j];
3419 ifaces = ifaces_array [j];
3422 for (i = 0; i < ifaces->len; ++i) {
3424 ic = g_ptr_array_index (ifaces, i);
3426 /*Force the sharing of interface offsets between parent and subtypes.*/
3427 io = mono_class_interface_offset (k, ic);
3429 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3434 g_assert (class == class->supertypes [class->idepth - 1]);
3435 ifaces = ifaces_array [class->idepth - 1];
3437 for (i = 0; i < ifaces->len; ++i) {
3439 ic = g_ptr_array_index (ifaces, i);
3440 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3442 count = count_virtual_methods (ic);
3444 char *name = mono_type_get_full_name (ic);
3445 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3454 if (MONO_CLASS_IS_INTERFACE (class))
3455 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3457 if (num_array_interfaces) {
3458 if (is_enumerator) {
3459 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3460 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3461 g_assert (ienumerator_offset >= 0);
3462 for (i = 0; i < num_array_interfaces; ++i) {
3463 ic = array_interfaces [i];
3464 if (strcmp (ic->name, "IEnumerator`1") == 0)
3465 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3467 g_assert_not_reached ();
3468 /*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);*/
3471 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3472 int ilist_iface_idx = find_array_interface (class, "IList`1");
3473 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3474 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3475 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3476 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3477 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3478 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3479 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3480 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3481 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3482 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3483 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3484 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3485 for (i = 0; i < num_array_interfaces; ++i) {
3487 ic = array_interfaces [i];
3488 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3489 offset = ilist_offset;
3490 else if (strcmp (ic->name, "ICollection`1") == 0)
3491 offset = icollection_offset;
3492 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3493 offset = ienumerable_offset;
3494 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3495 offset = ireadonlylist_offset;
3496 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3497 offset = ireadonlycollection_offset;
3499 g_assert_not_reached ();
3500 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3501 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3506 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3507 if (interface_offsets_full [i] != -1) {
3508 interface_offsets_count ++;
3513 * We might get called multiple times:
3514 * - mono_class_init ()
3515 * - mono_class_setup_vtable ().
3516 * - mono_class_setup_interface_offsets ().
3517 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3518 * means we have to overwrite those when called from other places (#4440).
3520 if (class->interfaces_packed && !overwrite) {
3521 g_assert (class->interface_offsets_count == interface_offsets_count);
3525 class->interface_offsets_count = interface_offsets_count;
3526 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3527 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3528 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3529 #ifdef COMPRESSED_INTERFACE_BITMAP
3530 bitmap = g_malloc0 (bsize);
3532 bitmap = mono_class_alloc0 (class, bsize);
3534 for (i = 0; i < interface_offsets_count; i++) {
3535 int id = interfaces_full [i]->interface_id;
3536 bitmap [id >> 3] |= (1 << (id & 7));
3537 class->interfaces_packed [i] = interfaces_full [i];
3538 class->interface_offsets_packed [i] = interface_offsets_full [i];
3539 /*if (num_array_interfaces)
3540 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]);*/
3542 #ifdef COMPRESSED_INTERFACE_BITMAP
3543 i = mono_compress_bitmap (NULL, bitmap, bsize);
3544 class->interface_bitmap = mono_class_alloc0 (class, i);
3545 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3548 class->interface_bitmap = bitmap;
3553 g_free (interfaces_full);
3554 g_free (interface_offsets_full);
3555 g_free (array_interfaces);
3556 for (i = 0; i < class->idepth; i++) {
3557 ifaces = ifaces_array [i];
3559 g_ptr_array_free (ifaces, TRUE);
3561 g_free (ifaces_array);
3563 //printf ("JUST DONE: ");
3564 //print_implemented_interfaces (class);
3570 * Setup interface offsets for interfaces.
3572 * - class->max_interface_id
3573 * - class->interface_offsets_count
3574 * - class->interfaces_packed
3575 * - class->interface_offsets_packed
3576 * - class->interface_bitmap
3578 * This function can fail @class.
3581 mono_class_setup_interface_offsets (MonoClass *class)
3583 mono_loader_lock ();
3585 setup_interface_offsets (class, 0, FALSE);
3587 mono_loader_unlock ();
3590 /*Checks if @klass has @parent as one of it's parents type gtd
3594 * Bar<T> : Foo<Bar<Bar<T>>>
3598 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3600 klass = mono_class_get_generic_type_definition (klass);
3601 parent = mono_class_get_generic_type_definition (parent);
3602 mono_class_setup_supertypes (klass);
3603 mono_class_setup_supertypes (parent);
3605 return klass->idepth >= parent->idepth &&
3606 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3610 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3612 MonoGenericInst *ginst;
3614 if (!class->generic_class) {
3615 mono_class_setup_vtable_full (class, in_setup);
3616 return class->exception_type == 0;
3619 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3620 if (class->generic_class->container_class->exception_type) {
3621 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3625 ginst = class->generic_class->context.class_inst;
3626 for (i = 0; i < ginst->type_argc; ++i) {
3628 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3630 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3631 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3632 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3634 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3635 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3643 * mono_class_setup_vtable:
3645 * Creates the generic vtable of CLASS.
3646 * Initializes the following fields in MonoClass:
3649 * Plus all the fields initialized by setup_interface_offsets ().
3650 * If there is an error during vtable construction, class->exception_type is set.
3652 * LOCKING: Acquires the loader lock.
3655 mono_class_setup_vtable (MonoClass *class)
3657 mono_class_setup_vtable_full (class, NULL);
3661 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3663 MonoMethod **overrides;
3664 MonoGenericContext *context;
3672 if (MONO_CLASS_IS_INTERFACE (class)) {
3673 /* This sets method->slot for all methods if this is an interface */
3674 mono_class_setup_methods (class);
3678 if (class->exception_type)
3681 if (g_list_find (in_setup, class))
3684 mono_loader_lock ();
3686 if (class->vtable) {
3687 mono_loader_unlock ();
3691 mono_stats.generic_vtable_count ++;
3692 in_setup = g_list_prepend (in_setup, class);
3694 if (class->generic_class) {
3695 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3696 mono_loader_unlock ();
3697 g_list_remove (in_setup, class);
3701 context = mono_class_get_context (class);
3702 type_token = class->generic_class->container_class->type_token;
3704 context = (MonoGenericContext *) class->generic_container;
3705 type_token = class->type_token;
3708 if (image_is_dynamic (class->image)) {
3709 /* Generic instances can have zero method overrides without causing any harm.
3710 * This is true since we don't do layout all over again for them, we simply inflate
3711 * the layout of the parent.
3713 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3715 /* The following call fails if there are missing methods in the type */
3716 /* FIXME it's probably a good idea to avoid this for generic instances. */
3717 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3721 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3723 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3727 mono_loader_unlock ();
3728 g_list_remove (in_setup, class);
3733 #define DEBUG_INTERFACE_VTABLE_CODE 0
3734 #define TRACE_INTERFACE_VTABLE_CODE 0
3735 #define VERIFY_INTERFACE_VTABLE_CODE 0
3736 #define VTABLE_SELECTOR (1)
3738 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3739 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3740 if (!(VTABLE_SELECTOR)) break; \
3744 #define DEBUG_INTERFACE_VTABLE(stmt)
3747 #if TRACE_INTERFACE_VTABLE_CODE
3748 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3749 if (!(VTABLE_SELECTOR)) break; \
3753 #define TRACE_INTERFACE_VTABLE(stmt)
3756 #if VERIFY_INTERFACE_VTABLE_CODE
3757 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3758 if (!(VTABLE_SELECTOR)) break; \
3762 #define VERIFY_INTERFACE_VTABLE(stmt)
3766 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3768 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3772 GString *res = g_string_new ("");
3774 g_string_append_c (res, '(');
3775 for (i = 0; i < sig->param_count; ++i) {
3777 g_string_append_c (res, ',');
3778 mono_type_get_desc (res, sig->params [i], include_namespace);
3780 g_string_append (res, ")=>");
3781 if (sig->ret != NULL) {
3782 mono_type_get_desc (res, sig->ret, include_namespace);
3784 g_string_append (res, "NULL");
3787 g_string_free (res, FALSE);
3791 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3792 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3793 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3794 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3802 is_wcf_hack_disabled (void)
3804 static gboolean disabled;
3805 static gboolean inited = FALSE;
3807 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3814 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) {
3815 MonoMethodSignature *cmsig, *imsig;
3816 if (strcmp (im->name, cm->name) == 0) {
3817 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3818 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3821 if (! slot_is_empty) {
3822 if (require_newslot) {
3823 if (! interface_is_explicitly_implemented_by_class) {
3824 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3827 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3828 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3832 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3835 cmsig = mono_method_signature (cm);
3836 imsig = mono_method_signature (im);
3837 if (!cmsig || !imsig) {
3838 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3842 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3843 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3844 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3845 TRACE_INTERFACE_VTABLE (printf ("]"));
3848 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3849 /* CAS - SecurityAction.InheritanceDemand on interface */
3850 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3851 mono_secman_inheritancedemand_method (cm, im);
3854 if (mono_security_core_clr_enabled ())
3855 mono_security_core_clr_check_override (class, cm, im);
3857 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3858 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3859 char *body_name = mono_method_full_name (cm, TRUE);
3860 char *decl_name = mono_method_full_name (im, TRUE);
3861 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));
3869 MonoClass *ic = im->klass;
3870 const char *ic_name_space = ic->name_space;
3871 const char *ic_name = ic->name;
3874 if (! require_newslot) {
3875 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3878 if (cm->klass->rank == 0) {
3879 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3882 cmsig = mono_method_signature (cm);
3883 imsig = mono_method_signature (im);
3884 if (!cmsig || !imsig) {
3885 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3889 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3890 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3891 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3892 TRACE_INTERFACE_VTABLE (printf ("]"));
3895 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3896 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3899 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3900 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3903 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))) {
3904 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3908 subname = strstr (cm->name, ic_name_space);
3909 if (subname != cm->name) {
3910 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3913 subname += strlen (ic_name_space);
3914 if (subname [0] != '.') {
3915 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3919 if (strstr (subname, ic_name) != subname) {
3920 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3923 subname += strlen (ic_name);
3924 if (subname [0] != '.') {
3925 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3929 if (strcmp (subname, im->name) != 0) {
3930 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3934 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3935 /* CAS - SecurityAction.InheritanceDemand on interface */
3936 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3937 mono_secman_inheritancedemand_method (cm, im);
3940 if (mono_security_core_clr_enabled ())
3941 mono_security_core_clr_check_override (class, cm, im);
3943 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3944 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3945 char *body_name = mono_method_full_name (cm, TRUE);
3946 char *decl_name = mono_method_full_name (im, TRUE);
3947 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));
3957 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3959 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3960 MonoMethod *method = key;
3961 MonoMethod *override = value;
3962 MonoClass *method_class = mono_method_get_class (method);
3963 MonoClass *override_class = mono_method_get_class (override);
3965 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3966 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3967 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3970 print_overrides (GHashTable *override_map, const char *message) {
3972 printf ("Override map \"%s\" START:\n", message);
3973 g_hash_table_foreach (override_map, foreach_override, NULL);
3974 printf ("Override map \"%s\" END.\n", message);
3976 printf ("Override map \"%s\" EMPTY.\n", message);
3980 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3981 char *full_name = mono_type_full_name (&class->byval_arg);
3985 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3987 if (print_interfaces) {
3988 print_implemented_interfaces (class);
3989 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3992 if (class->parent) {
3993 parent_size = class->parent->vtable_size;
3997 for (i = 0; i < size; ++i) {
3998 MonoMethod *cm = vtable [i];
3999 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4000 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4002 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4010 #if VERIFY_INTERFACE_VTABLE_CODE
4012 mono_method_try_get_vtable_index (MonoMethod *method)
4014 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4015 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4016 if (imethod->declaring->is_generic)
4017 return imethod->declaring->slot;
4019 return method->slot;
4023 mono_class_verify_vtable (MonoClass *class)
4026 char *full_name = mono_type_full_name (&class->byval_arg);
4028 printf ("*** Verifying VTable of class '%s' \n", full_name);
4032 if (!class->methods)
4035 for (i = 0; i < class->method.count; ++i) {
4036 MonoMethod *cm = class->methods [i];
4039 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4043 full_name = mono_method_full_name (cm, TRUE);
4045 slot = mono_method_try_get_vtable_index (cm);
4047 if (slot >= class->vtable_size) {
4048 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4052 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4053 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4054 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4055 g_free (other_name);
4058 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4065 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4067 char *method_signature;
4070 for (index = 0; index < onum; ++index) {
4071 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4072 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4074 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4075 type_name = mono_type_full_name (&class->byval_arg);
4076 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4077 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4078 g_free (method_signature);
4080 mono_class_setup_methods (class);
4081 if (class->exception_type) {
4082 char *name = mono_type_get_full_name (class);
4083 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4087 for (index = 0; index < class->method.count; ++index) {
4088 MonoMethod *cm = class->methods [index];
4089 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4091 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4092 g_free (method_signature);
4097 mono_method_get_method_definition (MonoMethod *method)
4099 while (method->is_inflated)
4100 method = ((MonoMethodInflated*)method)->declaring;
4105 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4109 for (i = 0; i < onum; ++i) {
4110 MonoMethod *decl = overrides [i * 2];
4111 MonoMethod *body = overrides [i * 2 + 1];
4113 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4114 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4118 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4119 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4120 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4122 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4126 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4127 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4128 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4130 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4134 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4135 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4139 body = mono_method_get_method_definition (body);
4140 decl = mono_method_get_method_definition (decl);
4142 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4143 char *body_name = mono_method_full_name (body, TRUE);
4144 char *decl_name = mono_method_full_name (decl, TRUE);
4145 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));
4155 mono_class_need_stelemref_method (MonoClass *class)
4157 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4161 * LOCKING: this is supposed to be called with the loader lock held.
4164 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4168 MonoMethod **vtable;
4169 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4170 GPtrArray *ifaces = NULL;
4171 GHashTable *override_map = NULL;
4172 gboolean security_enabled = mono_security_enabled ();
4174 gpointer class_iter;
4175 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4176 int first_non_interface_slot;
4178 GSList *virt_methods = NULL, *l;
4179 int stelemref_slot = 0;
4184 if (overrides && !verify_class_overrides (class, overrides, onum))
4187 ifaces = mono_class_get_implemented_interfaces (class, &error);
4188 if (!mono_error_ok (&error)) {
4189 char *name = mono_type_get_full_name (class);
4190 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)));
4192 mono_error_cleanup (&error);
4194 } else if (ifaces) {
4195 for (i = 0; i < ifaces->len; i++) {
4196 MonoClass *ic = g_ptr_array_index (ifaces, i);
4197 max_vtsize += ic->method.count;
4199 g_ptr_array_free (ifaces, TRUE);
4203 if (class->parent) {
4204 mono_class_init (class->parent);
4205 mono_class_setup_vtable_full (class->parent, in_setup);
4207 if (class->parent->exception_type) {
4208 char *name = mono_type_get_full_name (class->parent);
4209 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4214 max_vtsize += class->parent->vtable_size;
4215 cur_slot = class->parent->vtable_size;
4218 max_vtsize += class->method.count;
4220 /*Array have a slot for stelemref*/
4221 if (mono_class_need_stelemref_method (class)) {
4222 stelemref_slot = cur_slot;
4227 vtable = alloca (sizeof (gpointer) * max_vtsize);
4228 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4230 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4232 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4233 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4236 max_iid = class->max_interface_id;
4237 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4239 /* Optimized version for generic instances */
4240 if (class->generic_class) {
4242 MonoClass *gklass = class->generic_class->container_class;
4245 mono_class_setup_vtable_full (gklass, in_setup);
4246 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4247 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4251 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4252 class->vtable_size = gklass->vtable_size;
4253 for (i = 0; i < gklass->vtable_size; ++i)
4254 if (gklass->vtable [i]) {
4255 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4256 if (!mono_error_ok (&error)) {
4257 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4258 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4260 mono_error_cleanup (&error);
4264 tmp [i]->slot = gklass->vtable [i]->slot;
4266 mono_memory_barrier ();
4267 class->vtable = tmp;
4269 /* Have to set method->slot for abstract virtual methods */
4270 if (class->methods && gklass->methods) {
4271 for (i = 0; i < class->method.count; ++i)
4272 if (class->methods [i]->slot == -1)
4273 class->methods [i]->slot = gklass->methods [i]->slot;
4279 if (class->parent && class->parent->vtable_size) {
4280 MonoClass *parent = class->parent;
4283 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4285 // Also inherit parent interface vtables, just as a starting point.
4286 // This is needed otherwise bug-77127.exe fails when the property methods
4287 // have different names in the iterface and the class, because for child
4288 // classes the ".override" information is not used anymore.
4289 for (i = 0; i < parent->interface_offsets_count; i++) {
4290 MonoClass *parent_interface = parent->interfaces_packed [i];
4291 int interface_offset = mono_class_interface_offset (class, parent_interface);
4292 /*FIXME this is now dead code as this condition will never hold true.
4293 Since interface offsets are inherited then the offset of an interface implemented
4294 by a parent will never be the out of it's vtable boundary.
4296 if (interface_offset >= parent->vtable_size) {
4297 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4300 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4301 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4302 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4303 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4304 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4305 parent_interface_offset + j, parent_interface_offset, j,
4306 interface_offset + j, interface_offset, j));
4313 /*Array have a slot for stelemref*/
4314 if (mono_class_need_stelemref_method (class)) {
4315 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4317 method->slot = stelemref_slot;
4319 g_assert (method->slot == stelemref_slot);
4321 vtable [stelemref_slot] = method;
4324 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4325 /* override interface methods */
4326 for (i = 0; i < onum; i++) {
4327 MonoMethod *decl = overrides [i*2];
4328 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4330 dslot = mono_method_get_vtable_slot (decl);
4332 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4336 dslot += mono_class_interface_offset (class, decl->klass);
4337 vtable [dslot] = overrides [i*2 + 1];
4338 vtable [dslot]->slot = dslot;
4340 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4342 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4344 if (mono_security_core_clr_enabled ())
4345 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4348 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4349 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4352 * Create a list of virtual methods to avoid calling
4353 * mono_class_get_virtual_methods () which is slow because of the metadata
4357 gpointer iter = NULL;
4360 virt_methods = NULL;
4361 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4362 virt_methods = g_slist_prepend (virt_methods, cm);
4364 if (class->exception_type)
4368 // Loop on all implemented interfaces...
4369 for (i = 0; i < class->interface_offsets_count; i++) {
4370 MonoClass *parent = class->parent;
4372 gboolean interface_is_explicitly_implemented_by_class;
4375 ic = class->interfaces_packed [i];
4376 ic_offset = mono_class_interface_offset (class, ic);
4378 mono_class_setup_methods (ic);
4379 if (ic->exception_type)
4382 // Check if this interface is explicitly implemented (instead of just inherited)
4383 if (parent != NULL) {
4384 int implemented_interfaces_index;
4385 interface_is_explicitly_implemented_by_class = FALSE;
4386 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4387 if (ic == class->interfaces [implemented_interfaces_index]) {
4388 interface_is_explicitly_implemented_by_class = TRUE;
4393 interface_is_explicitly_implemented_by_class = TRUE;
4396 // Loop on all interface methods...
4397 for (im_index = 0; im_index < ic->method.count; im_index++) {
4398 MonoMethod *im = ic->methods [im_index];
4399 int im_slot = ic_offset + im->slot;
4400 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4402 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4405 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4407 // If there is an explicit implementation, just use it right away,
4408 // otherwise look for a matching method
4409 if (override_im == NULL) {
4414 // First look for a suitable method among the class methods
4416 for (l = virt_methods; l; l = l->next) {
4418 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)));
4419 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4420 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4421 vtable [im_slot] = cm;
4422 /* Why do we need this? */
4427 TRACE_INTERFACE_VTABLE (printf ("\n"));
4428 if (class->exception_type) /*Might be set by check_interface_method_override*/
4432 // If the slot is still empty, look in all the inherited virtual methods...
4433 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4434 MonoClass *parent = class->parent;
4435 // Reverse order, so that last added methods are preferred
4436 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4437 MonoMethod *cm = parent->vtable [cm_index];
4439 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));
4440 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4441 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4442 vtable [im_slot] = cm;
4443 /* Why do we need this? */
4449 if (class->exception_type) /*Might be set by check_interface_method_override*/
4451 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4455 g_assert (vtable [im_slot] == override_im);
4460 // If the class is not abstract, check that all its interface slots are full.
4461 // The check is done here and not directly at the end of the loop above because
4462 // it can happen (for injected generic array interfaces) that the same slot is
4463 // processed multiple times (those interfaces have overlapping slots), and it
4464 // will not always be the first pass the one that fills the slot.
4465 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4466 for (i = 0; i < class->interface_offsets_count; i++) {
4470 ic = class->interfaces_packed [i];
4471 ic_offset = mono_class_interface_offset (class, ic);
4473 for (im_index = 0; im_index < ic->method.count; im_index++) {
4474 MonoMethod *im = ic->methods [im_index];
4475 int im_slot = ic_offset + im->slot;
4477 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4480 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4481 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4482 if (vtable [im_slot] == NULL) {
4483 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4490 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4492 for (l = virt_methods; l; l = l->next) {
4495 * If the method is REUSE_SLOT, we must check in the
4496 * base class for a method to override.
4498 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4500 for (k = class->parent; k ; k = k->parent) {
4505 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4506 MonoMethodSignature *cmsig, *m1sig;
4508 cmsig = mono_method_signature (cm);
4509 m1sig = mono_method_signature (m1);
4511 if (!cmsig || !m1sig) {
4512 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4516 if (!strcmp(cm->name, m1->name) &&
4517 mono_metadata_signature_equal (cmsig, m1sig)) {
4519 /* CAS - SecurityAction.InheritanceDemand */
4520 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4521 mono_secman_inheritancedemand_method (cm, m1);
4524 if (mono_security_core_clr_enabled ())
4525 mono_security_core_clr_check_override (class, cm, m1);
4527 slot = mono_method_get_vtable_slot (m1);
4531 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4532 char *body_name = mono_method_full_name (cm, TRUE);
4533 char *decl_name = mono_method_full_name (m1, TRUE);
4534 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));
4540 g_assert (cm->slot < max_vtsize);
4542 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4543 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4544 mono_method_full_name (m1, 1), m1,
4545 mono_method_full_name (cm, 1), cm));
4546 g_hash_table_insert (override_map, m1, cm);
4550 if (k->exception_type)
4560 /*Non final newslot methods must be given a non-interface vtable slot*/
4561 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4565 cm->slot = cur_slot++;
4567 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4568 vtable [cm->slot] = cm;
4571 /* override non interface methods */
4572 for (i = 0; i < onum; i++) {
4573 MonoMethod *decl = overrides [i*2];
4574 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4575 g_assert (decl->slot != -1);
4576 vtable [decl->slot] = overrides [i*2 + 1];
4577 overrides [i * 2 + 1]->slot = decl->slot;
4579 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4580 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4581 mono_method_full_name (decl, 1), decl,
4582 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4583 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4585 if (mono_security_core_clr_enabled ())
4586 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4591 * If a method occupies more than one place in the vtable, and it is
4592 * overriden, then change the other occurances too.
4597 for (i = 0; i < max_vtsize; ++i)
4599 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4601 cm = g_hash_table_lookup (override_map, vtable [i]);
4606 g_hash_table_destroy (override_map);
4607 override_map = NULL;
4610 g_slist_free (virt_methods);
4611 virt_methods = NULL;
4613 /* Ensure that all vtable slots are filled with concrete instance methods */
4614 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4615 for (i = 0; i < cur_slot; ++i) {
4616 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4617 char *type_name = mono_type_get_full_name (class);
4618 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4619 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));
4621 g_free (method_name);
4627 if (class->generic_class) {
4628 MonoClass *gklass = class->generic_class->container_class;
4630 mono_class_init (gklass);
4632 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4634 /* Check that the vtable_size value computed in mono_class_init () is correct */
4635 if (class->vtable_size)
4636 g_assert (cur_slot == class->vtable_size);
4637 class->vtable_size = cur_slot;
4640 /* Try to share the vtable with our parent. */
4641 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4642 mono_memory_barrier ();
4643 class->vtable = class->parent->vtable;
4645 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4646 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4647 mono_memory_barrier ();
4648 class->vtable = tmp;
4651 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4652 if (mono_print_vtable) {
4655 print_implemented_interfaces (class);
4657 for (i = 0; i <= max_iid; i++)
4658 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4661 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4662 class->vtable_size, icount);
4664 for (i = 0; i < cur_slot; ++i) {
4669 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4670 mono_method_full_name (cm, TRUE));
4676 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4677 class->name, max_iid);
4679 for (i = 0; i < class->interface_count; i++) {
4680 ic = class->interfaces [i];
4681 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4682 mono_class_interface_offset (class, ic),
4683 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4686 for (k = class->parent; k ; k = k->parent) {
4687 for (i = 0; i < k->interface_count; i++) {
4688 ic = k->interfaces [i];
4689 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4690 mono_class_interface_offset (class, ic),
4691 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4697 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4702 char *name = mono_type_get_full_name (class);
4703 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4706 g_hash_table_destroy (override_map);
4708 g_slist_free (virt_methods);
4713 * mono_method_get_vtable_slot:
4715 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4716 * LOCKING: Acquires the loader lock.
4718 * FIXME Use proper MonoError machinery here.
4721 mono_method_get_vtable_slot (MonoMethod *method)
4723 if (method->slot == -1) {
4724 mono_class_setup_vtable (method->klass);
4725 if (method->klass->exception_type)
4727 if (method->slot == -1) {
4731 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4732 g_assert (method->klass->generic_class);
4733 gklass = method->klass->generic_class->container_class;
4734 mono_class_setup_methods (method->klass);
4735 g_assert (method->klass->methods);
4736 for (i = 0; i < method->klass->method.count; ++i) {
4737 if (method->klass->methods [i] == method)
4740 g_assert (i < method->klass->method.count);
4741 g_assert (gklass->methods);
4742 method->slot = gklass->methods [i]->slot;
4744 g_assert (method->slot != -1);
4746 return method->slot;
4750 * mono_method_get_vtable_index:
4753 * Returns the index into the runtime vtable to access the method or,
4754 * in the case of a virtual generic method, the virtual generic method
4755 * thunk. Returns -1 on failure.
4757 * FIXME Use proper MonoError machinery here.
4760 mono_method_get_vtable_index (MonoMethod *method)
4762 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4763 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4764 if (imethod->declaring->is_generic)
4765 return mono_method_get_vtable_slot (imethod->declaring);
4767 return mono_method_get_vtable_slot (method);
4770 static MonoMethod *default_ghc = NULL;
4771 static MonoMethod *default_finalize = NULL;
4772 static int finalize_slot = -1;
4773 static int ghc_slot = -1;
4776 initialize_object_slots (MonoClass *class)
4781 if (class == mono_defaults.object_class) {
4782 mono_class_setup_vtable (class);
4783 for (i = 0; i < class->vtable_size; ++i) {
4784 MonoMethod *cm = class->vtable [i];
4786 if (!strcmp (cm->name, "GetHashCode"))
4788 else if (!strcmp (cm->name, "Finalize"))
4792 g_assert (ghc_slot > 0);
4793 default_ghc = class->vtable [ghc_slot];
4795 g_assert (finalize_slot > 0);
4796 default_finalize = class->vtable [finalize_slot];
4801 MonoMethod *array_method;
4803 } GenericArrayMethodInfo;
4805 static int generic_array_method_num = 0;
4806 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4809 generic_array_methods (MonoClass *class)
4811 int i, count_generic = 0;
4812 GList *list = NULL, *tmp;
4813 if (generic_array_method_num)
4814 return generic_array_method_num;
4815 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4816 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4817 for (i = 0; i < class->parent->method.count; i++) {
4818 MonoMethod *m = class->parent->methods [i];
4819 if (!strncmp (m->name, "InternalArray__", 15)) {
4821 list = g_list_prepend (list, m);
4824 list = g_list_reverse (list);
4825 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4827 for (tmp = list; tmp; tmp = tmp->next) {
4828 const char *mname, *iname;
4830 MonoMethod *m = tmp->data;
4831 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4832 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4834 generic_array_method_info [i].array_method = m;
4835 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4836 iname = "System.Collections.Generic.ICollection`1.";
4837 mname = m->name + 27;
4838 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4839 iname = "System.Collections.Generic.IEnumerable`1.";
4840 mname = m->name + 27;
4841 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4842 iname = "System.Collections.Generic.IReadOnlyList`1.";
4843 mname = m->name + strlen (ireadonlylist_prefix);
4844 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4845 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4846 mname = m->name + strlen (ireadonlycollection_prefix);
4847 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4848 iname = "System.Collections.Generic.IList`1.";
4849 mname = m->name + 15;
4851 g_assert_not_reached ();
4854 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4855 strcpy (name, iname);
4856 strcpy (name + strlen (iname), mname);
4857 generic_array_method_info [i].name = name;
4860 /*g_print ("array generic methods: %d\n", count_generic);*/
4862 generic_array_method_num = count_generic;
4864 return generic_array_method_num;
4868 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4870 MonoGenericContext tmp_context;
4873 tmp_context.class_inst = NULL;
4874 tmp_context.method_inst = iface->generic_class->context.class_inst;
4875 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4877 for (i = 0; i < generic_array_method_num; i++) {
4878 MonoMethod *m = generic_array_method_info [i].array_method;
4879 MonoMethod *inflated;
4881 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4882 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4887 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4889 int null_length = strlen ("(null)");
4890 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4891 char *s = mono_image_alloc (image, len);
4894 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4895 g_assert (result == len - 1);
4901 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4903 gpointer exception_data = NULL;
4905 switch (error->exception_type) {
4906 case MONO_EXCEPTION_TYPE_LOAD:
4907 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4910 case MONO_EXCEPTION_MISSING_METHOD:
4911 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4914 case MONO_EXCEPTION_MISSING_FIELD: {
4915 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4916 const char *class_name;
4919 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4921 class_name = error->klass->name;
4923 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4926 g_free ((void*)class_name);
4930 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4933 if (error->ref_only)
4934 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.";
4936 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4938 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4942 case MONO_EXCEPTION_BAD_IMAGE:
4943 exception_data = error->msg;
4947 g_assert_not_reached ();
4950 mono_class_set_failure (class, error->exception_type, exception_data);
4955 * @class: the class to initialize
4957 * Compute the instance_size, class_size and other infos that cannot be
4958 * computed at mono_class_get() time. Also compute vtable_size if possible.
4959 * Returns TRUE on success or FALSE if there was a problem in loading
4960 * the type (incorrect assemblies, missing assemblies, methods, etc).
4962 * LOCKING: Acquires the loader lock.
4965 mono_class_init (MonoClass *class)
4968 MonoCachedClassInfo cached_info;
4969 gboolean has_cached_info;
4973 /* Double-checking locking pattern */
4974 if (class->inited || class->exception_type)
4975 return class->exception_type == MONO_EXCEPTION_NONE;
4977 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4979 /* We do everything inside the lock to prevent races */
4980 mono_loader_lock ();
4982 if (class->inited || class->exception_type) {
4983 mono_loader_unlock ();
4984 /* Somebody might have gotten in before us */
4985 return class->exception_type == MONO_EXCEPTION_NONE;
4988 if (class->init_pending) {
4989 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4993 class->init_pending = 1;
4995 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4996 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5001 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5002 MonoClass *element_class = class->element_class;
5003 if (!element_class->inited)
5004 mono_class_init (element_class);
5005 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5006 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5011 /* CAS - SecurityAction.InheritanceDemand */
5012 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5013 mono_secman_inheritancedemand_class (class, class->parent);
5016 mono_stats.initialized_class_count++;
5018 if (class->generic_class && !class->generic_class->is_dynamic) {
5019 MonoClass *gklass = class->generic_class->container_class;
5021 mono_stats.generic_class_count++;
5023 class->method = gklass->method;
5024 class->field = gklass->field;
5026 mono_class_init (gklass);
5027 // FIXME: Why is this needed ?
5028 if (!gklass->exception_type)
5029 mono_class_setup_methods (gklass);
5030 if (gklass->exception_type) {
5031 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5035 if (MONO_CLASS_IS_INTERFACE (class))
5036 class->interface_id = mono_get_unique_iid (class);
5039 if (class->parent && !class->parent->inited)
5040 mono_class_init (class->parent);
5042 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5044 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5045 class->nested_classes_inited = TRUE;
5048 * Computes the size used by the fields, and their locations
5050 if (has_cached_info) {
5051 class->instance_size = cached_info.instance_size;
5052 class->sizes.class_size = cached_info.class_size;
5053 class->packing_size = cached_info.packing_size;
5054 class->min_align = cached_info.min_align;
5055 class->blittable = cached_info.blittable;
5056 class->has_references = cached_info.has_references;
5057 class->has_static_refs = cached_info.has_static_refs;
5058 class->no_special_static_fields = cached_info.no_special_static_fields;
5061 if (!class->size_inited){
5062 mono_class_setup_fields (class);
5063 if (class->exception_type || mono_loader_get_last_error ())
5067 /* Initialize arrays */
5069 class->method.count = 3 + (class->rank > 1? 2: 1);
5071 if (class->interface_count) {
5072 int count_generic = generic_array_methods (class);
5073 class->method.count += class->interface_count * count_generic;
5077 mono_class_setup_supertypes (class);
5080 initialize_object_slots (class);
5083 * Initialize the rest of the data without creating a generic vtable if possible.
5084 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5085 * also avoid computing a generic vtable.
5087 if (has_cached_info) {
5089 class->vtable_size = cached_info.vtable_size;
5090 class->has_finalize = cached_info.has_finalize;
5091 class->has_finalize_inited = TRUE;
5092 class->ghcimpl = cached_info.ghcimpl;
5093 class->has_cctor = cached_info.has_cctor;
5094 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5095 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5096 * The first slot if for array with.
5098 static int szarray_vtable_size[2] = { 0 };
5100 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5103 if (!szarray_vtable_size [slot]) {
5104 mono_class_setup_vtable (class);
5105 szarray_vtable_size [slot] = class->vtable_size;
5107 class->vtable_size = szarray_vtable_size[slot];
5109 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5110 MonoClass *gklass = class->generic_class->container_class;
5112 /* Generic instance case */
5113 class->ghcimpl = gklass->ghcimpl;
5114 class->has_cctor = gklass->has_cctor;
5116 mono_class_setup_vtable (gklass);
5117 if (gklass->exception_type) {
5118 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5122 class->vtable_size = gklass->vtable_size;
5126 /* ghcimpl is not currently used
5128 if (class->parent) {
5129 MonoMethod *cmethod = class->vtable [ghc_slot];
5130 if (cmethod->is_inflated)
5131 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5132 if (cmethod == default_ghc) {
5138 /* C# doesn't allow interfaces to have cctors */
5139 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5140 MonoMethod *cmethod = NULL;
5142 if (class->type_token) {
5143 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5144 /* The find_method function ignores the 'flags' argument */
5145 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5146 class->has_cctor = 1;
5148 mono_class_setup_methods (class);
5149 if (class->exception_type)
5152 for (i = 0; i < class->method.count; ++i) {
5153 MonoMethod *method = class->methods [i];
5154 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5155 (strcmp (".cctor", method->name) == 0)) {
5156 class->has_cctor = 1;
5164 if (class->parent) {
5165 int first_iface_slot;
5166 /* This will compute class->parent->vtable_size for some classes */
5167 mono_class_init (class->parent);
5168 if (class->parent->exception_type) {
5169 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5172 if (mono_loader_get_last_error ())
5174 if (!class->parent->vtable_size) {
5175 /* FIXME: Get rid of this somehow */
5176 mono_class_setup_vtable (class->parent);
5177 if (class->parent->exception_type) {
5178 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5181 if (mono_loader_get_last_error ())
5184 first_iface_slot = class->parent->vtable_size;
5185 if (mono_class_need_stelemref_method (class))
5187 setup_interface_offsets (class, first_iface_slot, TRUE);
5189 setup_interface_offsets (class, 0, TRUE);
5192 if (mono_security_core_clr_enabled ())
5193 mono_security_core_clr_check_inheritance (class);
5195 if (mono_loader_get_last_error ()) {
5196 if (class->exception_type == MONO_EXCEPTION_NONE) {
5197 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5199 mono_loader_clear_error ();
5202 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5203 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5208 /* Because of the double-checking locking pattern */
5209 mono_memory_barrier ();
5211 class->init_pending = 0;
5213 mono_loader_unlock ();
5215 if (mono_debugger_class_init_func)
5216 mono_debugger_class_init_func (class);
5218 return class->exception_type == MONO_EXCEPTION_NONE;
5222 * mono_class_has_finalizer:
5224 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5228 mono_class_has_finalizer (MonoClass *klass)
5230 MonoClass *class = klass;
5231 gboolean has_finalize = FALSE;
5233 if (klass->has_finalize_inited)
5234 return klass->has_finalize;
5236 /* Interfaces and valuetypes are not supposed to have finalizers */
5237 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5238 MonoMethod *cmethod = NULL;
5240 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5241 } else if (class->generic_class) {
5242 MonoClass *gklass = class->generic_class->container_class;
5244 has_finalize = mono_class_has_finalizer (gklass);
5245 } else if (class->parent && class->parent->has_finalize) {
5246 has_finalize = TRUE;
5248 if (class->parent) {
5250 * Can't search in metadata for a method named Finalize, because that
5251 * ignores overrides.
5253 mono_class_setup_vtable (class);
5254 if (class->exception_type || mono_loader_get_last_error ())
5257 cmethod = class->vtable [finalize_slot];
5261 g_assert (class->vtable_size > finalize_slot);
5263 if (class->parent) {
5264 if (cmethod->is_inflated)
5265 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5266 if (cmethod != default_finalize)
5267 has_finalize = TRUE;
5273 mono_image_lock (klass->image);
5275 if (!klass->has_finalize_inited) {
5276 klass->has_finalize = has_finalize ? 1 : 0;
5278 mono_memory_barrier ();
5279 klass->has_finalize_inited = TRUE;
5282 mono_image_unlock (klass->image);
5284 return klass->has_finalize;
5288 mono_is_corlib_image (MonoImage *image)
5290 /* FIXME: allow the dynamic case for our compilers and with full trust */
5291 if (image_is_dynamic (image))
5292 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5294 return image == mono_defaults.corlib;
5298 * LOCKING: this assumes the loader lock is held
5301 mono_class_setup_mono_type (MonoClass *class)
5303 const char *name = class->name;
5304 const char *nspace = class->name_space;
5305 gboolean is_corlib = mono_is_corlib_image (class->image);
5307 class->this_arg.byref = 1;
5308 class->this_arg.data.klass = class;
5309 class->this_arg.type = MONO_TYPE_CLASS;
5310 class->byval_arg.data.klass = class;
5311 class->byval_arg.type = MONO_TYPE_CLASS;
5313 if (is_corlib && !strcmp (nspace, "System")) {
5314 if (!strcmp (name, "ValueType")) {
5316 * do not set the valuetype bit for System.ValueType.
5317 * class->valuetype = 1;
5319 class->blittable = TRUE;
5320 } else if (!strcmp (name, "Enum")) {
5322 * do not set the valuetype bit for System.Enum.
5323 * class->valuetype = 1;
5325 class->valuetype = 0;
5326 class->enumtype = 0;
5327 } else if (!strcmp (name, "Object")) {
5328 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5329 } else if (!strcmp (name, "String")) {
5330 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5331 } else if (!strcmp (name, "TypedReference")) {
5332 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5336 if (class->valuetype) {
5337 int t = MONO_TYPE_VALUETYPE;
5339 if (is_corlib && !strcmp (nspace, "System")) {
5342 if (!strcmp (name, "Boolean")) {
5343 t = MONO_TYPE_BOOLEAN;
5344 } else if (!strcmp(name, "Byte")) {
5346 class->blittable = TRUE;
5350 if (!strcmp (name, "Char")) {
5355 if (!strcmp (name, "Double")) {
5357 class->blittable = TRUE;
5361 if (!strcmp (name, "Int32")) {
5363 class->blittable = TRUE;
5364 } else if (!strcmp(name, "Int16")) {
5366 class->blittable = TRUE;
5367 } else if (!strcmp(name, "Int64")) {
5369 class->blittable = TRUE;
5370 } else if (!strcmp(name, "IntPtr")) {
5372 class->blittable = TRUE;
5376 if (!strcmp (name, "Single")) {
5378 class->blittable = TRUE;
5379 } else if (!strcmp(name, "SByte")) {
5381 class->blittable = TRUE;
5385 if (!strcmp (name, "UInt32")) {
5387 class->blittable = TRUE;
5388 } else if (!strcmp(name, "UInt16")) {
5390 class->blittable = TRUE;
5391 } else if (!strcmp(name, "UInt64")) {
5393 class->blittable = TRUE;
5394 } else if (!strcmp(name, "UIntPtr")) {
5396 class->blittable = TRUE;
5400 if (!strcmp (name, "TypedReference")) {
5401 t = MONO_TYPE_TYPEDBYREF;
5402 class->blittable = TRUE;
5406 if (!strcmp (name, "Void")) {
5414 class->this_arg.type = class->byval_arg.type = t;
5417 if (MONO_CLASS_IS_INTERFACE (class))
5418 class->interface_id = mono_get_unique_iid (class);
5424 * COM initialization is delayed until needed.
5425 * However when a [ComImport] attribute is present on a type it will trigger
5426 * the initialization. This is not a problem unless the BCL being executed
5427 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5430 init_com_from_comimport (MonoClass *class)
5432 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5433 if (mono_security_core_clr_enabled ()) {
5434 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5435 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5436 /* but it can not be made available for application (i.e. user code) since all COM calls
5437 * are considered native calls. In this case we fail with a TypeLoadException (just like
5438 * Silverlight 2 does */
5439 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5444 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5446 #endif /*DISABLE_COM*/
5449 * LOCKING: this assumes the loader lock is held
5452 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5454 gboolean system_namespace;
5455 gboolean is_corlib = mono_is_corlib_image (class->image);
5457 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5459 /* if root of the hierarchy */
5460 if (system_namespace && !strcmp (class->name, "Object")) {
5461 class->parent = NULL;
5462 class->instance_size = sizeof (MonoObject);
5465 if (!strcmp (class->name, "<Module>")) {
5466 class->parent = NULL;
5467 class->instance_size = 0;
5471 if (!MONO_CLASS_IS_INTERFACE (class)) {
5472 /* Imported COM Objects always derive from __ComObject. */
5474 if (MONO_CLASS_IS_IMPORT (class)) {
5475 init_com_from_comimport (class);
5476 if (parent == mono_defaults.object_class)
5477 parent = mono_class_get_com_object_class ();
5481 /* set the parent to something useful and safe, but mark the type as broken */
5482 parent = mono_defaults.object_class;
5483 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5486 class->parent = parent;
5488 if (parent->generic_class && !parent->name) {
5490 * If the parent is a generic instance, we may get
5491 * called before it is fully initialized, especially
5492 * before it has its name.
5497 #ifndef DISABLE_REMOTING
5498 class->marshalbyref = parent->marshalbyref;
5499 class->contextbound = parent->contextbound;
5502 class->delegate = parent->delegate;
5504 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5505 mono_class_set_is_com_object (class);
5507 if (system_namespace) {
5508 #ifndef DISABLE_REMOTING
5509 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5510 class->marshalbyref = 1;
5512 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5513 class->contextbound = 1;
5515 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5516 class->delegate = 1;
5519 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5520 (strcmp (class->parent->name_space, "System") == 0)))
5521 class->valuetype = 1;
5522 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5523 class->valuetype = class->enumtype = 1;
5525 /*class->enumtype = class->parent->enumtype; */
5527 /* initialize com types if COM interfaces are present */
5529 if (MONO_CLASS_IS_IMPORT (class))
5530 init_com_from_comimport (class);
5532 class->parent = NULL;
5538 * mono_class_setup_supertypes:
5541 * Build the data structure needed to make fast type checks work.
5542 * This currently sets two fields in @class:
5543 * - idepth: distance between @class and System.Object in the type
5545 * - supertypes: array of classes: each element has a class in the hierarchy
5546 * starting from @class up to System.Object
5548 * LOCKING: This function is atomic, in case of contention we waste memory.
5551 mono_class_setup_supertypes (MonoClass *class)
5554 MonoClass **supertypes;
5556 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5560 if (class->parent && !class->parent->supertypes)
5561 mono_class_setup_supertypes (class->parent);
5563 class->idepth = class->parent->idepth + 1;
5567 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5568 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5570 if (class->parent) {
5571 supertypes [class->idepth - 1] = class;
5572 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5574 supertypes [0] = class;
5577 mono_atomic_store_release (&class->supertypes, supertypes);
5581 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5583 MonoClass *gtd = (MonoClass*)user_data;
5584 /* Only try to fix generic instances of @gtd */
5585 if (gclass->generic_class->container_class != gtd)
5588 /* Check if the generic instance has no parent. */
5589 if (gtd->parent && !gclass->parent)
5590 mono_generic_class_setup_parent (gclass, gtd);
5596 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5598 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5599 mono_error_set_type_load_class (error, class, msg);
5603 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5605 MonoLoaderError *lerror = mono_loader_get_last_error ();
5608 set_failure_from_loader_error (class, lerror);
5609 mono_error_set_from_loader_error (error);
5613 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5614 mono_error_set_type_load_class (error, class, msg);
5619 * mono_class_create_from_typedef:
5620 * @image: image where the token is valid
5621 * @type_token: typedef token
5622 * @error: used to return any error found while creating the type
5624 * Create the MonoClass* representing the specified type token.
5625 * @type_token must be a TypeDef token.
5627 * FIXME: don't return NULL on failure, just the the caller figure it out.
5630 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5632 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5633 MonoClass *class, *parent = NULL;
5634 guint32 cols [MONO_TYPEDEF_SIZE];
5635 guint32 cols_next [MONO_TYPEDEF_SIZE];
5636 guint tidx = mono_metadata_token_index (type_token);
5637 MonoGenericContext *context = NULL;
5638 const char *name, *nspace;
5640 MonoClass **interfaces;
5641 guint32 field_last, method_last;
5642 guint32 nesting_tokeen;
5644 mono_error_init (error);
5646 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5647 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5648 g_assert (!mono_loader_get_last_error ());
5652 mono_loader_lock ();
5654 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5655 mono_loader_unlock ();
5656 g_assert (!mono_loader_get_last_error ());
5660 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5662 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5663 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5665 class = mono_image_alloc0 (image, sizeof (MonoClass));
5668 class->name_space = nspace;
5670 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5672 class->image = image;
5673 class->type_token = type_token;
5674 class->flags = cols [MONO_TYPEDEF_FLAGS];
5676 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5678 classes_size += sizeof (MonoClass);
5681 * Check whether we're a generic type definition.
5683 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5684 if (class->generic_container) {
5685 class->is_generic = 1;
5686 class->generic_container->owner.klass = class;
5687 context = &class->generic_container->context;
5690 if (class->generic_container)
5691 enable_gclass_recording ();
5693 if (cols [MONO_TYPEDEF_EXTENDS]) {
5695 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5697 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5698 /*WARNING: this must satisfy mono_metadata_type_hash*/
5699 class->this_arg.byref = 1;
5700 class->this_arg.data.klass = class;
5701 class->this_arg.type = MONO_TYPE_CLASS;
5702 class->byval_arg.data.klass = class;
5703 class->byval_arg.type = MONO_TYPE_CLASS;
5705 parent = mono_class_get_checked (image, parent_token, error);
5706 if (parent && context) /* Always inflate */
5707 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5709 if (parent == NULL) {
5710 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5711 goto parent_failure;
5714 for (tmp = parent; tmp; tmp = tmp->parent) {
5716 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5717 goto parent_failure;
5719 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5720 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5721 goto parent_failure;
5726 mono_class_setup_parent (class, parent);
5728 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5729 mono_class_setup_mono_type (class);
5731 if (class->generic_container)
5732 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5735 * This might access class->byval_arg for recursion generated by generic constraints,
5736 * so it has to come after setup_mono_type ().
5738 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5739 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5740 if (!mono_error_ok (error)) {
5741 /*FIXME implement a mono_class_set_failure_from_mono_error */
5742 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5743 mono_loader_unlock ();
5744 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5745 g_assert (!mono_loader_get_last_error ());
5750 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5754 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5758 class->cast_class = class->element_class = class;
5760 if (!class->enumtype) {
5761 if (!mono_metadata_interfaces_from_typedef_full (
5762 image, type_token, &interfaces, &icount, FALSE, context)){
5763 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5764 mono_loader_unlock ();
5765 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5769 class->interfaces = interfaces;
5770 class->interface_count = icount;
5771 class->interfaces_inited = 1;
5774 /*g_print ("Load class %s\n", name);*/
5777 * Compute the field and method lists
5779 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5780 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5782 if (tt->rows > tidx){
5783 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5784 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5785 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5787 field_last = image->tables [MONO_TABLE_FIELD].rows;
5788 method_last = image->tables [MONO_TABLE_METHOD].rows;
5791 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5792 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5793 class->field.count = field_last - class->field.first;
5795 class->field.count = 0;
5797 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5798 class->method.count = method_last - class->method.first;
5800 class->method.count = 0;
5802 /* reserve space to store vector pointer in arrays */
5803 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5804 class->instance_size += 2 * sizeof (gpointer);
5805 g_assert (class->field.count == 0);
5808 if (class->enumtype) {
5809 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5810 if (!enum_basetype) {
5811 /*set it to a default value as the whole runtime can't handle this to be null*/
5812 class->cast_class = class->element_class = mono_defaults.int32_class;
5813 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5814 mono_loader_unlock ();
5815 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5816 g_assert (!mono_loader_get_last_error ());
5819 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5823 * If we're a generic type definition, load the constraints.
5824 * We must do this after the class has been constructed to make certain recursive scenarios
5827 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5828 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)));
5829 mono_loader_unlock ();
5830 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5831 g_assert (!mono_loader_get_last_error ());
5835 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5836 if (!strncmp (name, "Vector", 6))
5837 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");
5840 mono_loader_unlock ();
5842 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5843 g_assert (!mono_loader_get_last_error ());
5848 mono_class_setup_mono_type (class);
5849 mono_loader_unlock ();
5850 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5851 g_assert (!mono_loader_get_last_error ());
5855 /** is klass Nullable<T>? */
5857 mono_class_is_nullable (MonoClass *klass)
5859 return klass->generic_class != NULL &&
5860 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5864 /** if klass is T? return T */
5866 mono_class_get_nullable_param (MonoClass *klass)
5868 g_assert (mono_class_is_nullable (klass));
5869 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5873 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5877 MonoGenericClass *gclass = klass->generic_class;
5879 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5880 if (!mono_error_ok (&error)) {
5881 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5882 klass->parent = mono_defaults.object_class;
5883 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5884 mono_error_cleanup (&error);
5888 mono_class_setup_parent (klass, klass->parent);
5890 if (klass->enumtype) {
5891 klass->cast_class = gtd->cast_class;
5892 klass->element_class = gtd->element_class;
5898 * Create the `MonoClass' for an instantiation of a generic type.
5899 * We only do this if we actually need it.
5902 mono_generic_class_get_class (MonoGenericClass *gclass)
5904 MonoClass *klass, *gklass;
5906 if (gclass->cached_class)
5907 return gclass->cached_class;
5909 mono_loader_lock ();
5910 if (gclass->cached_class) {
5911 mono_loader_unlock ();
5912 return gclass->cached_class;
5915 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5917 gklass = gclass->container_class;
5919 if (record_gclass_instantiation > 0)
5920 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5922 if (gklass->nested_in) {
5923 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5924 klass->nested_in = gklass->nested_in;
5927 klass->name = gklass->name;
5928 klass->name_space = gklass->name_space;
5930 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5932 klass->image = gklass->image;
5933 klass->flags = gklass->flags;
5934 klass->type_token = gklass->type_token;
5935 klass->field.count = gklass->field.count;
5937 klass->is_inflated = 1;
5938 klass->generic_class = gclass;
5940 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5941 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5942 klass->this_arg.byref = TRUE;
5943 klass->enumtype = gklass->enumtype;
5944 klass->valuetype = gklass->valuetype;
5946 klass->cast_class = klass->element_class = klass;
5948 if (mono_class_is_nullable (klass))
5949 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5952 * We're not interested in the nested classes of a generic instance.
5953 * We use the generic type definition to look for nested classes.
5956 mono_generic_class_setup_parent (klass, gklass);
5958 if (gclass->is_dynamic) {
5961 mono_class_setup_supertypes (klass);
5963 if (klass->enumtype) {
5965 * For enums, gklass->fields might not been set, but instance_size etc. is
5966 * already set in mono_reflection_create_internal_class (). For non-enums,
5967 * these will be computed normally in mono_class_layout_fields ().
5969 klass->instance_size = gklass->instance_size;
5970 klass->sizes.class_size = gklass->sizes.class_size;
5971 mono_memory_barrier ();
5972 klass->size_inited = 1;
5976 mono_memory_barrier ();
5977 gclass->cached_class = klass;
5979 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5981 inflated_classes ++;
5982 inflated_classes_size += sizeof (MonoClass);
5984 mono_loader_unlock ();
5990 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5992 MonoClass *klass, **ptr;
5994 MonoGenericContainer *container = mono_generic_param_owner (param);
5998 image = mono_defaults.corlib;
6000 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6001 classes_size += sizeof (MonoClass);
6004 klass->name = pinfo->name;
6006 int n = mono_generic_param_num (param);
6007 klass->name = mono_image_alloc0 (image, 16);
6008 sprintf ((char*)klass->name, "%d", n);
6013 MonoMethod *omethod = container->owner.method;
6014 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6016 MonoClass *oklass = container->owner.klass;
6017 klass->name_space = oklass ? oklass->name_space : "";
6020 klass->name_space = "";
6023 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6027 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6031 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6032 klass->parent = pinfo->constraints [0];
6034 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6035 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6037 klass->parent = mono_defaults.object_class;
6040 if (count - pos > 0) {
6041 klass->interface_count = count - pos;
6042 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6043 klass->interfaces_inited = TRUE;
6044 for (i = pos; i < count; i++)
6045 klass->interfaces [i - pos] = pinfo->constraints [i];
6048 klass->image = image;
6050 klass->inited = TRUE;
6051 klass->cast_class = klass->element_class = klass;
6052 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6054 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6055 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6056 klass->this_arg.byref = TRUE;
6058 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6059 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6061 /*Init these fields to sane values*/
6062 klass->min_align = 1;
6063 klass->instance_size = sizeof (gpointer);
6064 mono_memory_barrier ();
6065 klass->size_inited = 1;
6067 mono_class_setup_supertypes (klass);
6069 if (count - pos > 0) {
6070 mono_class_setup_vtable (klass->parent);
6071 if (klass->parent->exception_type)
6072 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6074 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6080 #define FAST_CACHE_SIZE 16
6083 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6085 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6086 MonoImage *image = param->image;
6091 if (n < FAST_CACHE_SIZE) {
6093 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6095 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6097 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6098 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6103 * LOCKING: Acquires the loader lock.
6106 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6108 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6109 MonoImage *image = param->image;
6114 if (n < FAST_CACHE_SIZE) {
6116 /* No locking needed */
6117 if (!image->mvar_cache_fast)
6118 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6119 image->mvar_cache_fast [n] = klass;
6121 if (!image->var_cache_fast)
6122 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6123 image->var_cache_fast [n] = klass;
6127 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6129 mono_image_lock (image);
6130 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6132 ht = g_hash_table_new (NULL, NULL);
6133 mono_memory_barrier ();
6135 image->mvar_cache_slow = ht;
6137 image->var_cache_slow = ht;
6139 mono_image_unlock (image);
6142 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6146 * LOCKING: Acquires the loader lock.
6149 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6151 MonoGenericContainer *container = mono_generic_param_owner (param);
6152 MonoGenericParamInfo *pinfo;
6155 mono_loader_lock ();
6158 pinfo = mono_generic_param_info (param);
6159 if (pinfo->pklass) {
6160 mono_loader_unlock ();
6161 return pinfo->pklass;
6167 klass = get_anon_gparam_class (param, is_mvar);
6169 mono_loader_unlock ();
6174 if (!image && container) {
6176 MonoMethod *method = container->owner.method;
6177 image = (method && method->klass) ? method->klass->image : NULL;
6179 MonoClass *klass = container->owner.klass;
6180 // FIXME: 'klass' should not be null
6181 // But, monodis creates GenericContainers without associating a owner to it
6182 image = klass ? klass->image : NULL;
6186 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6188 mono_memory_barrier ();
6191 pinfo->pklass = klass;
6193 set_anon_gparam_class (param, is_mvar, klass);
6195 mono_loader_unlock ();
6197 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6198 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6204 mono_ptr_class_get (MonoType *type)
6207 MonoClass *el_class;
6211 el_class = mono_class_from_mono_type (type);
6212 image = el_class->image;
6214 mono_loader_lock ();
6216 if (!image->ptr_cache)
6217 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6219 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6220 mono_loader_unlock ();
6223 result = mono_image_alloc0 (image, sizeof (MonoClass));
6225 classes_size += sizeof (MonoClass);
6227 result->parent = NULL; /* no parent for PTR types */
6228 result->name_space = el_class->name_space;
6229 name = g_strdup_printf ("%s*", el_class->name);
6230 result->name = mono_image_strdup (image, name);
6233 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6235 result->image = el_class->image;
6236 result->inited = TRUE;
6237 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6238 /* Can pointers get boxed? */
6239 result->instance_size = sizeof (gpointer);
6240 result->cast_class = result->element_class = el_class;
6241 result->blittable = TRUE;
6243 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6244 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6245 result->this_arg.byref = TRUE;
6247 mono_class_setup_supertypes (result);
6249 g_hash_table_insert (image->ptr_cache, el_class, result);
6251 mono_loader_unlock ();
6253 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6259 mono_fnptr_class_get (MonoMethodSignature *sig)
6262 static GHashTable *ptr_hash = NULL;
6264 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6266 mono_loader_lock ();
6269 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6271 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6272 mono_loader_unlock ();
6275 result = g_new0 (MonoClass, 1);
6277 result->parent = NULL; /* no parent for PTR types */
6278 result->name_space = "System";
6279 result->name = "MonoFNPtrFakeClass";
6281 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6283 result->image = mono_defaults.corlib; /* need to fix... */
6284 result->inited = TRUE;
6285 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6286 /* Can pointers get boxed? */
6287 result->instance_size = sizeof (gpointer);
6288 result->cast_class = result->element_class = result;
6289 result->blittable = TRUE;
6291 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6292 result->this_arg.data.method = result->byval_arg.data.method = sig;
6293 result->this_arg.byref = TRUE;
6294 result->blittable = TRUE;
6296 mono_class_setup_supertypes (result);
6298 g_hash_table_insert (ptr_hash, sig, result);
6300 mono_loader_unlock ();
6302 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6308 mono_class_from_mono_type (MonoType *type)
6310 switch (type->type) {
6311 case MONO_TYPE_OBJECT:
6312 return type->data.klass? type->data.klass: mono_defaults.object_class;
6313 case MONO_TYPE_VOID:
6314 return type->data.klass? type->data.klass: mono_defaults.void_class;
6315 case MONO_TYPE_BOOLEAN:
6316 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6317 case MONO_TYPE_CHAR:
6318 return type->data.klass? type->data.klass: mono_defaults.char_class;
6320 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6322 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6324 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6326 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6328 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6330 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6332 return type->data.klass? type->data.klass: mono_defaults.int_class;
6334 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6336 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6338 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6340 return type->data.klass? type->data.klass: mono_defaults.single_class;
6342 return type->data.klass? type->data.klass: mono_defaults.double_class;
6343 case MONO_TYPE_STRING:
6344 return type->data.klass? type->data.klass: mono_defaults.string_class;
6345 case MONO_TYPE_TYPEDBYREF:
6346 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6347 case MONO_TYPE_ARRAY:
6348 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6350 return mono_ptr_class_get (type->data.type);
6351 case MONO_TYPE_FNPTR:
6352 return mono_fnptr_class_get (type->data.method);
6353 case MONO_TYPE_SZARRAY:
6354 return mono_array_class_get (type->data.klass, 1);
6355 case MONO_TYPE_CLASS:
6356 case MONO_TYPE_VALUETYPE:
6357 return type->data.klass;
6358 case MONO_TYPE_GENERICINST:
6359 return mono_generic_class_get_class (type->data.generic_class);
6361 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6362 case MONO_TYPE_MVAR:
6363 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6365 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6366 g_assert_not_reached ();
6373 * mono_type_retrieve_from_typespec
6374 * @image: context where the image is created
6375 * @type_spec: typespec token
6376 * @context: the generic context used to evaluate generic instantiations in
6379 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6381 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6383 *did_inflate = FALSE;
6388 if (context && (context->class_inst || context->method_inst)) {
6389 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6391 if (!mono_error_ok (error)) {
6392 g_assert (!mono_loader_get_last_error ());
6398 *did_inflate = TRUE;
6405 * mono_class_create_from_typespec
6406 * @image: context where the image is created
6407 * @type_spec: typespec token
6408 * @context: the generic context used to evaluate generic instantiations in
6411 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6414 gboolean inflated = FALSE;
6415 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6416 if (!mono_error_ok (error))
6418 ret = mono_class_from_mono_type (t);
6420 mono_metadata_free_type (t);
6425 * mono_bounded_array_class_get:
6426 * @element_class: element class
6427 * @rank: the dimension of the array class
6428 * @bounded: whenever the array has non-zero bounds
6430 * Returns: a class object describing the array with element type @element_type and
6434 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6438 MonoClass *parent = NULL;
6439 GSList *list, *rootlist = NULL;
6442 gboolean corlib_type = FALSE;
6444 g_assert (rank <= 255);
6447 /* bounded only matters for one-dimensional arrays */
6450 image = eclass->image;
6452 if (rank == 1 && !bounded) {
6454 * This case is very frequent not just during compilation because of calls
6455 * from mono_class_from_mono_type (), mono_array_new (),
6456 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6458 mono_mutex_lock (&image->szarray_cache_lock);
6459 if (!image->szarray_cache)
6460 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6461 class = g_hash_table_lookup (image->szarray_cache, eclass);
6462 mono_mutex_unlock (&image->szarray_cache_lock);
6466 mono_loader_lock ();
6468 mono_loader_lock ();
6470 if (!image->array_cache)
6471 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6473 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6474 for (; list; list = list->next) {
6476 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6477 mono_loader_unlock ();
6484 /* for the building corlib use System.Array from it */
6485 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6486 parent = mono_class_from_name (image, "System", "Array");
6489 parent = mono_defaults.array_class;
6490 if (!parent->inited)
6491 mono_class_init (parent);
6494 class = mono_image_alloc0 (image, sizeof (MonoClass));
6496 class->image = image;
6497 class->name_space = eclass->name_space;
6498 nsize = strlen (eclass->name);
6499 name = g_malloc (nsize + 2 + rank + 1);
6500 memcpy (name, eclass->name, nsize);
6503 memset (name + nsize + 1, ',', rank - 1);
6505 name [nsize + rank] = '*';
6506 name [nsize + rank + bounded] = ']';
6507 name [nsize + rank + bounded + 1] = 0;
6508 class->name = mono_image_strdup (image, name);
6511 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6513 classes_size += sizeof (MonoClass);
6515 class->type_token = 0;
6516 /* all arrays are marked serializable and sealed, bug #42779 */
6517 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6518 class->parent = parent;
6519 class->instance_size = mono_class_instance_size (class->parent);
6521 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6522 /*Arrays of those two types are invalid.*/
6523 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6524 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6525 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6526 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6527 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6529 /* element_size -1 is ok as this is not an instantitable type*/
6530 class->sizes.element_size = -1;
6532 class->sizes.element_size = mono_class_array_element_size (eclass);
6534 mono_class_setup_supertypes (class);
6536 if (eclass->generic_class)
6537 mono_class_init (eclass);
6538 if (!eclass->size_inited)
6539 mono_class_setup_fields (eclass);
6540 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6541 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6543 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6547 if (eclass->enumtype)
6548 class->cast_class = eclass->element_class;
6550 class->cast_class = eclass;
6552 switch (class->cast_class->byval_arg.type) {
6554 class->cast_class = mono_defaults.byte_class;
6557 class->cast_class = mono_defaults.int16_class;
6560 #if SIZEOF_VOID_P == 4
6564 class->cast_class = mono_defaults.int32_class;
6567 #if SIZEOF_VOID_P == 8
6571 class->cast_class = mono_defaults.int64_class;
6575 class->element_class = eclass;
6577 if ((rank > 1) || bounded) {
6578 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6579 class->byval_arg.type = MONO_TYPE_ARRAY;
6580 class->byval_arg.data.array = at;
6581 at->eklass = eclass;
6583 /* FIXME: complete.... */
6585 class->byval_arg.type = MONO_TYPE_SZARRAY;
6586 class->byval_arg.data.klass = eclass;
6588 class->this_arg = class->byval_arg;
6589 class->this_arg.byref = 1;
6594 class->generic_container = eclass->generic_container;
6596 if (rank == 1 && !bounded) {
6597 MonoClass *prev_class;
6599 mono_mutex_lock (&image->szarray_cache_lock);
6600 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6602 /* Someone got in before us */
6605 g_hash_table_insert (image->szarray_cache, eclass, class);
6606 mono_mutex_unlock (&image->szarray_cache_lock);
6608 list = g_slist_append (rootlist, class);
6609 g_hash_table_insert (image->array_cache, eclass, list);
6612 mono_loader_unlock ();
6614 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6620 * mono_array_class_get:
6621 * @element_class: element class
6622 * @rank: the dimension of the array class
6624 * Returns: a class object describing the array with element type @element_type and
6628 mono_array_class_get (MonoClass *eclass, guint32 rank)
6630 return mono_bounded_array_class_get (eclass, rank, FALSE);
6634 * mono_class_instance_size:
6637 * Returns: the size of an object instance
6640 mono_class_instance_size (MonoClass *klass)
6642 if (!klass->size_inited)
6643 mono_class_init (klass);
6645 return klass->instance_size;
6649 * mono_class_min_align:
6652 * Returns: minimm alignment requirements
6655 mono_class_min_align (MonoClass *klass)
6657 if (!klass->size_inited)
6658 mono_class_init (klass);
6660 return klass->min_align;
6664 * mono_class_value_size:
6667 * This function is used for value types, and return the
6668 * space and the alignment to store that kind of value object.
6670 * Returns: the size of a value of kind @klass
6673 mono_class_value_size (MonoClass *klass, guint32 *align)
6677 /* fixme: check disable, because we still have external revereces to
6678 * mscorlib and Dummy Objects
6680 /*g_assert (klass->valuetype);*/
6682 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6685 *align = klass->min_align;
6691 * mono_class_data_size:
6694 * Returns: the size of the static class data
6697 mono_class_data_size (MonoClass *klass)
6700 mono_class_init (klass);
6701 /* This can happen with dynamically created types */
6702 if (!klass->fields_inited)
6703 mono_class_setup_fields_locking (klass);
6705 /* in arrays, sizes.class_size is unioned with element_size
6706 * and arrays have no static fields
6710 return klass->sizes.class_size;
6714 * Auxiliary routine to mono_class_get_field
6716 * Takes a field index instead of a field token.
6718 static MonoClassField *
6719 mono_class_get_field_idx (MonoClass *class, int idx)
6721 mono_class_setup_fields_locking (class);
6722 if (class->exception_type)
6726 if (class->image->uncompressed_metadata) {
6728 * class->field.first points to the FieldPtr table, while idx points into the
6729 * Field table, so we have to do a search.
6731 /*FIXME this is broken for types with multiple fields with the same name.*/
6732 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6735 for (i = 0; i < class->field.count; ++i)
6736 if (mono_field_get_name (&class->fields [i]) == name)
6737 return &class->fields [i];
6738 g_assert_not_reached ();
6740 if (class->field.count) {
6741 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6742 return &class->fields [idx - class->field.first];
6746 class = class->parent;
6752 * mono_class_get_field:
6753 * @class: the class to lookup the field.
6754 * @field_token: the field token
6756 * Returns: A MonoClassField representing the type and offset of
6757 * the field, or a NULL value if the field does not belong to this
6761 mono_class_get_field (MonoClass *class, guint32 field_token)
6763 int idx = mono_metadata_token_index (field_token);
6765 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6767 return mono_class_get_field_idx (class, idx - 1);
6771 * mono_class_get_field_from_name:
6772 * @klass: the class to lookup the field.
6773 * @name: the field name
6775 * Search the class @klass and it's parents for a field with the name @name.
6777 * Returns: the MonoClassField pointer of the named field or NULL
6780 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6782 return mono_class_get_field_from_name_full (klass, name, NULL);
6786 * mono_class_get_field_from_name_full:
6787 * @klass: the class to lookup the field.
6788 * @name: the field name
6789 * @type: the type of the fields. This optional.
6791 * Search the class @klass and it's parents for a field with the name @name and type @type.
6793 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6794 * of its generic type definition.
6796 * Returns: the MonoClassField pointer of the named field or NULL
6799 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6803 mono_class_setup_fields_locking (klass);
6804 if (klass->exception_type)
6808 for (i = 0; i < klass->field.count; ++i) {
6809 MonoClassField *field = &klass->fields [i];
6811 if (strcmp (name, mono_field_get_name (field)) != 0)
6815 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6816 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6821 klass = klass->parent;
6827 * mono_class_get_field_token:
6828 * @field: the field we need the token of
6830 * Get the token of a field. Note that the tokesn is only valid for the image
6831 * the field was loaded from. Don't use this function for fields in dynamic types.
6833 * Returns: the token representing the field in the image it was loaded from.
6836 mono_class_get_field_token (MonoClassField *field)
6838 MonoClass *klass = field->parent;
6841 mono_class_setup_fields_locking (klass);
6846 for (i = 0; i < klass->field.count; ++i) {
6847 if (&klass->fields [i] == field) {
6848 int idx = klass->field.first + i + 1;
6850 if (klass->image->uncompressed_metadata)
6851 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6852 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6855 klass = klass->parent;
6858 g_assert_not_reached ();
6863 mono_field_get_index (MonoClassField *field)
6865 int index = field - field->parent->fields;
6867 g_assert (index >= 0 && index < field->parent->field.count);
6873 * mono_class_get_field_default_value:
6875 * Return the default value of the field as a pointer into the metadata blob.
6878 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6881 guint32 constant_cols [MONO_CONSTANT_SIZE];
6883 MonoClass *klass = field->parent;
6885 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6887 if (!klass->ext || !klass->ext->field_def_values) {
6888 MonoFieldDefaultValue *def_values;
6890 mono_class_alloc_ext (klass);
6892 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6894 mono_image_lock (klass->image);
6895 mono_memory_barrier ();
6896 if (!klass->ext->field_def_values)
6897 klass->ext->field_def_values = def_values;
6898 mono_image_unlock (klass->image);
6901 field_index = mono_field_get_index (field);
6903 if (!klass->ext->field_def_values [field_index].data) {
6904 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6908 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6910 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6911 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6912 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6915 *def_type = klass->ext->field_def_values [field_index].def_type;
6916 return klass->ext->field_def_values [field_index].data;
6920 mono_property_get_index (MonoProperty *prop)
6922 int index = prop - prop->parent->ext->properties;
6924 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6930 * mono_class_get_property_default_value:
6932 * Return the default value of the field as a pointer into the metadata blob.
6935 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6938 guint32 constant_cols [MONO_CONSTANT_SIZE];
6939 MonoClass *klass = property->parent;
6941 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6943 * We don't cache here because it is not used by C# so it's quite rare, but
6944 * we still do the lookup in klass->ext because that is where the data
6945 * is stored for dynamic assemblies.
6948 if (image_is_dynamic (klass->image)) {
6949 int prop_index = mono_property_get_index (property);
6950 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6951 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6952 return klass->ext->prop_def_values [prop_index].data;
6956 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6960 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6961 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6962 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6966 mono_class_get_event_token (MonoEvent *event)
6968 MonoClass *klass = event->parent;
6973 for (i = 0; i < klass->ext->event.count; ++i) {
6974 if (&klass->ext->events [i] == event)
6975 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6978 klass = klass->parent;
6981 g_assert_not_reached ();
6986 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6990 gpointer iter = NULL;
6991 while ((p = mono_class_get_properties (klass, &iter))) {
6992 if (! strcmp (name, p->name))
6995 klass = klass->parent;
7001 mono_class_get_property_token (MonoProperty *prop)
7003 MonoClass *klass = prop->parent;
7007 gpointer iter = NULL;
7008 while ((p = mono_class_get_properties (klass, &iter))) {
7009 if (&klass->ext->properties [i] == prop)
7010 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7014 klass = klass->parent;
7017 g_assert_not_reached ();
7022 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7024 const char *name, *nspace;
7025 if (image_is_dynamic (image))
7026 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7028 switch (type_token & 0xff000000){
7029 case MONO_TOKEN_TYPE_DEF: {
7030 guint32 cols [MONO_TYPEDEF_SIZE];
7031 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7032 guint tidx = mono_metadata_token_index (type_token);
7034 if (tidx > tt->rows)
7035 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7037 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7038 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7039 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7040 if (strlen (nspace) == 0)
7041 return g_strdup_printf ("%s", name);
7043 return g_strdup_printf ("%s.%s", nspace, name);
7046 case MONO_TOKEN_TYPE_REF: {
7048 guint32 cols [MONO_TYPEREF_SIZE];
7049 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7050 guint tidx = mono_metadata_token_index (type_token);
7053 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7055 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7056 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7057 mono_error_cleanup (&error);
7061 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7062 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7063 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7064 if (strlen (nspace) == 0)
7065 return g_strdup_printf ("%s", name);
7067 return g_strdup_printf ("%s.%s", nspace, name);
7070 case MONO_TOKEN_TYPE_SPEC:
7071 return g_strdup_printf ("Typespec 0x%08x", type_token);
7073 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7078 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7080 if (image_is_dynamic (image))
7081 return g_strdup_printf ("DynamicAssembly %s", image->name);
7083 switch (type_token & 0xff000000){
7084 case MONO_TOKEN_TYPE_DEF:
7085 if (image->assembly)
7086 return mono_stringify_assembly_name (&image->assembly->aname);
7087 else if (image->assembly_name)
7088 return g_strdup (image->assembly_name);
7089 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7090 case MONO_TOKEN_TYPE_REF: {
7092 MonoAssemblyName aname;
7093 guint32 cols [MONO_TYPEREF_SIZE];
7094 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7095 guint32 idx = mono_metadata_token_index (type_token);
7098 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7100 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7101 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7102 mono_error_cleanup (&error);
7105 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7107 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7108 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7109 case MONO_RESOLUTION_SCOPE_MODULE:
7111 return g_strdup ("");
7112 case MONO_RESOLUTION_SCOPE_MODULEREF:
7114 return g_strdup ("");
7115 case MONO_RESOLUTION_SCOPE_TYPEREF:
7117 return g_strdup ("");
7118 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7119 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7120 return mono_stringify_assembly_name (&aname);
7122 g_assert_not_reached ();
7126 case MONO_TOKEN_TYPE_SPEC:
7128 return g_strdup ("");
7130 g_assert_not_reached ();
7137 * mono_class_get_full:
7138 * @image: the image where the class resides
7139 * @type_token: the token for the class
7140 * @context: the generic context used to evaluate generic instantiations in
7141 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7143 * Returns: the MonoClass that represents @type_token in @image
7146 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7150 class = mono_class_get_checked (image, type_token, &error);
7152 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7153 class = mono_class_inflate_generic_class_checked (class, context, &error);
7156 mono_loader_set_error_from_mono_error (&error);
7157 mono_error_cleanup (&error); /*FIXME don't swallow this error */
7164 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7168 mono_error_init (error);
7169 class = mono_class_get_checked (image, type_token, error);
7171 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7172 class = mono_class_inflate_generic_class_checked (class, context, error);
7177 * mono_class_get_checked:
7178 * @image: the image where the class resides
7179 * @type_token: the token for the class
7180 * @error: error object to return any error
7182 * Returns: the MonoClass that represents @type_token in @image
7185 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7187 MonoClass *class = NULL;
7189 mono_error_init (error);
7191 if (image_is_dynamic (image)) {
7192 int table = mono_metadata_token_table (type_token);
7194 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7195 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7198 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7202 switch (type_token & 0xff000000){
7203 case MONO_TOKEN_TYPE_DEF:
7204 class = mono_class_create_from_typedef (image, type_token, error);
7206 case MONO_TOKEN_TYPE_REF:
7207 class = mono_class_from_typeref_checked (image, type_token, error);
7209 case MONO_TOKEN_TYPE_SPEC:
7210 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7213 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7217 /* Generic case, should be avoided for when a better error is possible. */
7218 if (!class && mono_error_ok (error)) {
7219 char *name = mono_class_name_from_token (image, type_token);
7220 char *assembly = mono_assembly_name_from_token (image, type_token);
7221 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7229 * mono_type_get_checked:
7230 * @image: the image where the type resides
7231 * @type_token: the token for the type
7232 * @context: the generic context used to evaluate generic instantiations in
7233 * @error: Error handling context
7235 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7237 * Returns: the MonoType that represents @type_token in @image
7240 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7242 MonoType *type = NULL;
7243 gboolean inflated = FALSE;
7245 mono_error_init (error);
7247 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7248 if (image_is_dynamic (image))
7249 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7251 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7252 MonoClass *class = mono_class_get_checked (image, type_token, error);
7255 g_assert (!mono_loader_get_last_error ());
7260 return mono_class_get_type (class);
7263 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7266 g_assert (!mono_loader_get_last_error ());
7271 MonoType *tmp = type;
7272 type = mono_class_get_type (mono_class_from_mono_type (type));
7273 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7274 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7275 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7277 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7279 if (type->type != tmp->type)
7282 mono_metadata_free_type (tmp);
7289 mono_class_get (MonoImage *image, guint32 type_token)
7291 return mono_class_get_full (image, type_token, NULL);
7295 * mono_image_init_name_cache:
7297 * Initializes the class name cache stored in image->name_cache.
7299 * LOCKING: Acquires the corresponding image lock.
7302 mono_image_init_name_cache (MonoImage *image)
7304 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7305 guint32 cols [MONO_TYPEDEF_SIZE];
7308 guint32 i, visib, nspace_index;
7309 GHashTable *name_cache2, *nspace_table;
7311 mono_image_lock (image);
7313 if (image->name_cache) {
7314 mono_image_unlock (image);
7318 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7320 if (image_is_dynamic (image)) {
7321 mono_image_unlock (image);
7325 /* Temporary hash table to avoid lookups in the nspace_table */
7326 name_cache2 = g_hash_table_new (NULL, NULL);
7328 for (i = 1; i <= t->rows; ++i) {
7329 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7330 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7332 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7333 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7335 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7337 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7338 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7340 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7341 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7342 if (!nspace_table) {
7343 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7344 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7345 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7348 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7351 /* Load type names from EXPORTEDTYPES table */
7353 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7354 guint32 cols [MONO_EXP_TYPE_SIZE];
7357 for (i = 0; i < t->rows; ++i) {
7358 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7359 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7360 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7362 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7363 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7364 if (!nspace_table) {
7365 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7366 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7367 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7370 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7374 g_hash_table_destroy (name_cache2);
7375 mono_image_unlock (image);
7378 /*FIXME Only dynamic assemblies should allow this operation.*/
7380 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7381 const char *name, guint32 index)
7383 GHashTable *nspace_table;
7384 GHashTable *name_cache;
7387 mono_image_lock (image);
7389 if (!image->name_cache)
7390 mono_image_init_name_cache (image);
7392 name_cache = image->name_cache;
7393 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7394 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7395 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7398 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7399 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7401 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7403 mono_image_unlock (image);
7412 find_nocase (gpointer key, gpointer value, gpointer user_data)
7414 char *name = (char*)key;
7415 FindUserData *data = (FindUserData*)user_data;
7417 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7418 data->value = value;
7422 * mono_class_from_name_case:
7423 * @image: The MonoImage where the type is looked up in
7424 * @name_space: the type namespace
7425 * @name: the type short name.
7426 * @deprecated: use the _checked variant
7428 * Obtains a MonoClass with a given namespace and a given name which
7429 * is located in the given MonoImage. The namespace and name
7430 * lookups are case insensitive.
7433 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7436 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7437 g_assert (!mono_error_ok (&error));
7442 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7444 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7445 guint32 cols [MONO_TYPEDEF_SIZE];
7450 mono_error_init (error);
7452 if (image_is_dynamic (image)) {
7454 FindUserData user_data;
7456 mono_image_lock (image);
7458 if (!image->name_cache)
7459 mono_image_init_name_cache (image);
7461 user_data.key = name_space;
7462 user_data.value = NULL;
7463 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7465 if (user_data.value) {
7466 GHashTable *nspace_table = (GHashTable*)user_data.value;
7468 user_data.key = name;
7469 user_data.value = NULL;
7471 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7473 if (user_data.value)
7474 token = GPOINTER_TO_UINT (user_data.value);
7477 mono_image_unlock (image);
7480 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7486 /* add a cache if needed */
7487 for (i = 1; i <= t->rows; ++i) {
7488 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7489 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7491 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7492 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7494 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7496 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7497 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7498 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7499 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7505 return_nested_in (MonoClass *class, char *nested)
7508 char *s = strchr (nested, '/');
7509 gpointer iter = NULL;
7516 while ((found = mono_class_get_nested_types (class, &iter))) {
7517 if (strcmp (found->name, nested) == 0) {
7519 return return_nested_in (found, s);
7527 search_modules (MonoImage *image, const char *name_space, const char *name)
7529 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7530 MonoImage *file_image;
7535 * The EXPORTEDTYPES table only contains public types, so have to search the
7537 * Note: image->modules contains the contents of the MODULEREF table, while
7538 * the real module list is in the FILE table.
7540 for (i = 0; i < file_table->rows; i++) {
7541 guint32 cols [MONO_FILE_SIZE];
7542 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7543 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7546 file_image = mono_image_load_file_for_image (image, i + 1);
7548 class = mono_class_from_name (file_image, name_space, name);
7558 * mono_class_from_name:
7559 * @image: The MonoImage where the type is looked up in
7560 * @name_space: the type namespace
7561 * @name: the type short name.
7563 * Obtains a MonoClass with a given namespace and a given name which
7564 * is located in the given MonoImage.
7566 * To reference nested classes, use the "/" character as a separator.
7567 * For example use "Foo/Bar" to reference the class Bar that is nested
7568 * inside Foo, like this: "class Foo { class Bar {} }".
7571 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7573 GHashTable *nspace_table;
7574 MonoImage *loaded_image;
7581 if ((nested = strchr (name, '/'))) {
7582 int pos = nested - name;
7583 int len = strlen (name);
7586 memcpy (buf, name, len + 1);
7588 nested = buf + pos + 1;
7592 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7593 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7594 gboolean res = get_class_from_name (image, name_space, name, &class);
7597 class = search_modules (image, name_space, name);
7599 return class ? return_nested_in (class, nested) : NULL;
7605 mono_image_lock (image);
7607 if (!image->name_cache)
7608 mono_image_init_name_cache (image);
7610 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7613 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7615 mono_image_unlock (image);
7617 if (!token && image_is_dynamic (image) && image->modules) {
7618 /* Search modules as well */
7619 for (i = 0; i < image->module_count; ++i) {
7620 MonoImage *module = image->modules [i];
7622 class = mono_class_from_name (module, name_space, name);
7629 class = search_modules (image, name_space, name);
7637 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7638 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7639 guint32 cols [MONO_EXP_TYPE_SIZE];
7642 idx = mono_metadata_token_index (token);
7644 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7646 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7647 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7648 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7651 class = mono_class_from_name (loaded_image, name_space, name);
7653 return return_nested_in (class, nested);
7655 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7656 guint32 assembly_idx;
7658 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7660 mono_assembly_load_reference (image, assembly_idx - 1);
7661 g_assert (image->references [assembly_idx - 1]);
7662 if (image->references [assembly_idx - 1] == (gpointer)-1)
7665 /* FIXME: Cycle detection */
7666 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7668 g_error ("not yet implemented");
7672 token = MONO_TOKEN_TYPE_DEF | token;
7674 class = mono_class_get (image, token);
7676 return return_nested_in (class, nested);
7681 * mono_class_is_subclass_of:
7682 * @klass: class to probe if it is a subclass of another one
7683 * @klassc: the class we suspect is the base class
7684 * @check_interfaces: whether we should perform interface checks
7686 * This method determines whether @klass is a subclass of @klassc.
7688 * If the @check_interfaces flag is set, then if @klassc is an interface
7689 * this method return true if the @klass implements the interface or
7690 * if @klass is an interface, if one of its base classes is @klass.
7692 * If @check_interfaces is false then, then if @klass is not an interface
7693 * then it returns true if the @klass is a subclass of @klassc.
7695 * if @klass is an interface and @klassc is System.Object, then this function
7700 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7701 gboolean check_interfaces)
7703 /*FIXME test for interfaces with variant generic arguments*/
7705 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7706 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7708 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7711 for (i = 0; i < klass->interface_count; i ++) {
7712 MonoClass *ic = klass->interfaces [i];
7717 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7722 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7725 if (klassc == mono_defaults.object_class)
7732 mono_type_is_generic_argument (MonoType *type)
7734 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7738 mono_class_has_variant_generic_params (MonoClass *klass)
7741 MonoGenericContainer *container;
7743 if (!klass->generic_class)
7746 container = klass->generic_class->container_class->generic_container;
7748 for (i = 0; i < container->type_argc; ++i)
7749 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7756 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7758 if (target == candidate)
7761 if (check_for_reference_conv &&
7762 mono_type_is_generic_argument (&target->byval_arg) &&
7763 mono_type_is_generic_argument (&candidate->byval_arg)) {
7764 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7765 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7767 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7770 if (!mono_class_is_assignable_from (target, candidate))
7776 * @container the generic container from the GTD
7777 * @klass: the class to be assigned to
7778 * @oklass: the source class
7780 * Both klass and oklass must be instances of the same generic interface.
7781 * Return true if @klass can be assigned to a @klass variable
7784 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7787 MonoType **klass_argv, **oklass_argv;
7788 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7789 MonoGenericContainer *container = klass_gtd->generic_container;
7791 if (klass == oklass)
7794 /*Viable candidates are instances of the same generic interface*/
7795 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7798 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7799 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7801 for (j = 0; j < container->type_argc; ++j) {
7802 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7803 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7805 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7809 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7810 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7812 if (param1_class != param2_class) {
7813 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7814 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7816 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7817 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7827 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7829 MonoGenericParam *gparam, *ogparam;
7830 MonoGenericParamInfo *tinfo, *cinfo;
7831 MonoClass **candidate_class;
7832 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7835 if (target == candidate)
7837 if (target->byval_arg.type != candidate->byval_arg.type)
7840 gparam = target->byval_arg.data.generic_param;
7841 ogparam = candidate->byval_arg.data.generic_param;
7842 tinfo = mono_generic_param_info (gparam);
7843 cinfo = mono_generic_param_info (ogparam);
7845 class_constraint_satisfied = FALSE;
7846 valuetype_constraint_satisfied = FALSE;
7848 /*candidate must have a super set of target's special constraints*/
7849 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7850 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7852 if (cinfo->constraints) {
7853 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7854 MonoClass *cc = *candidate_class;
7856 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7857 class_constraint_satisfied = TRUE;
7858 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7859 valuetype_constraint_satisfied = TRUE;
7862 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7863 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7865 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7867 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7869 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7870 valuetype_constraint_satisfied)) {
7875 /*candidate type constraints must be a superset of target's*/
7876 if (tinfo->constraints) {
7877 MonoClass **target_class;
7878 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7879 MonoClass *tc = *target_class;
7882 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7883 * check it's constraints since it satisfy the constraint by itself.
7885 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7888 if (!cinfo->constraints)
7891 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7892 MonoClass *cc = *candidate_class;
7894 if (mono_class_is_assignable_from (tc, cc))
7898 * This happens when we have the following:
7900 * Bar<K> where K : IFace
7901 * Foo<T, U> where T : U where U : IFace
7903 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7906 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7907 if (mono_gparam_is_assignable_from (target, cc))
7911 if (!*candidate_class)
7916 /*candidate itself must have a constraint that satisfy target*/
7917 if (cinfo->constraints) {
7918 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7919 MonoClass *cc = *candidate_class;
7920 if (mono_class_is_assignable_from (target, cc))
7928 * mono_class_is_assignable_from:
7929 * @klass: the class to be assigned to
7930 * @oklass: the source class
7932 * Return: true if an instance of object oklass can be assigned to an
7933 * instance of object @klass
7936 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7938 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7940 mono_class_init (klass);
7942 if (!oklass->inited)
7943 mono_class_init (oklass);
7945 if (klass->exception_type || oklass->exception_type)
7948 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7949 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7951 return mono_gparam_is_assignable_from (klass, oklass);
7954 if (MONO_CLASS_IS_INTERFACE (klass)) {
7955 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7956 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7957 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7961 for (i = 0; constraints [i]; ++i) {
7962 if (mono_class_is_assignable_from (klass, constraints [i]))
7970 /* interface_offsets might not be set for dynamic classes */
7971 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7973 * oklass might be a generic type parameter but they have
7974 * interface_offsets set.
7976 return mono_reflection_call_is_assignable_to (oklass, klass);
7977 if (!oklass->interface_bitmap)
7978 /* Happens with generic instances of not-yet created dynamic types */
7980 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7983 if (mono_class_has_variant_generic_params (klass)) {
7986 mono_class_setup_interfaces (oklass, &error);
7987 if (!mono_error_ok (&error)) {
7988 mono_error_cleanup (&error);
7992 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7993 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7994 MonoClass *iface = oklass->interfaces_packed [i];
7996 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8001 } else if (klass->delegate) {
8002 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8004 }else if (klass->rank) {
8005 MonoClass *eclass, *eoclass;
8007 if (oklass->rank != klass->rank)
8010 /* vectors vs. one dimensional arrays */
8011 if (oklass->byval_arg.type != klass->byval_arg.type)
8014 eclass = klass->cast_class;
8015 eoclass = oklass->cast_class;
8018 * a is b does not imply a[] is b[] when a is a valuetype, and
8019 * b is a reference type.
8022 if (eoclass->valuetype) {
8023 if ((eclass == mono_defaults.enum_class) ||
8024 (eclass == mono_defaults.enum_class->parent) ||
8025 (eclass == mono_defaults.object_class))
8029 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8030 } else if (mono_class_is_nullable (klass)) {
8031 if (mono_class_is_nullable (oklass))
8032 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8034 return mono_class_is_assignable_from (klass->cast_class, oklass);
8035 } else if (klass == mono_defaults.object_class)
8038 return mono_class_has_parent (oklass, klass);
8041 /*Check if @oklass is variant compatible with @klass.*/
8043 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8046 MonoType **klass_argv, **oklass_argv;
8047 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8048 MonoGenericContainer *container = klass_gtd->generic_container;
8050 /*Viable candidates are instances of the same generic interface*/
8051 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8054 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8055 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8057 for (j = 0; j < container->type_argc; ++j) {
8058 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8059 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8061 if (param1_class->valuetype != param2_class->valuetype)
8065 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8066 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8068 if (param1_class != param2_class) {
8069 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8070 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8072 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8073 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8081 /*Check if @candidate implements the interface @target*/
8083 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8087 gboolean is_variant = mono_class_has_variant_generic_params (target);
8089 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8090 if (mono_class_is_variant_compatible_slow (target, candidate))
8095 if (candidate == target)
8098 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8099 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8100 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8102 if (tb && tb->interfaces) {
8103 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8104 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8105 MonoClass *iface_class;
8107 /* we can't realize the type here since it can do pretty much anything. */
8110 iface_class = mono_class_from_mono_type (iface->type);
8111 if (iface_class == target)
8113 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8115 if (mono_class_implement_interface_slow (target, iface_class))
8120 /*setup_interfaces don't mono_class_init anything*/
8121 /*FIXME this doesn't handle primitive type arrays.
8122 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8123 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8125 mono_class_setup_interfaces (candidate, &error);
8126 if (!mono_error_ok (&error)) {
8127 mono_error_cleanup (&error);
8131 for (i = 0; i < candidate->interface_count; ++i) {
8132 if (candidate->interfaces [i] == target)
8135 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8138 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8142 candidate = candidate->parent;
8143 } while (candidate);
8149 * Check if @oklass can be assigned to @klass.
8150 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8153 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8155 if (candidate == target)
8157 if (target == mono_defaults.object_class)
8160 if (mono_class_has_parent (candidate, target))
8163 /*If target is not an interface there is no need to check them.*/
8164 if (MONO_CLASS_IS_INTERFACE (target))
8165 return mono_class_implement_interface_slow (target, candidate);
8167 if (target->delegate && mono_class_has_variant_generic_params (target))
8168 return mono_class_is_variant_compatible (target, candidate, FALSE);
8171 MonoClass *eclass, *eoclass;
8173 if (target->rank != candidate->rank)
8176 /* vectors vs. one dimensional arrays */
8177 if (target->byval_arg.type != candidate->byval_arg.type)
8180 eclass = target->cast_class;
8181 eoclass = candidate->cast_class;
8184 * a is b does not imply a[] is b[] when a is a valuetype, and
8185 * b is a reference type.
8188 if (eoclass->valuetype) {
8189 if ((eclass == mono_defaults.enum_class) ||
8190 (eclass == mono_defaults.enum_class->parent) ||
8191 (eclass == mono_defaults.object_class))
8195 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8197 /*FIXME properly handle nullables */
8198 /*FIXME properly handle (M)VAR */
8203 * mono_class_get_cctor:
8204 * @klass: A MonoClass pointer
8206 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8209 mono_class_get_cctor (MonoClass *klass)
8211 MonoCachedClassInfo cached_info;
8213 if (image_is_dynamic (klass->image)) {
8215 * has_cctor is not set for these classes because mono_class_init () is
8218 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8221 if (!klass->has_cctor)
8224 if (mono_class_get_cached_class_info (klass, &cached_info))
8225 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8227 if (klass->generic_class && !klass->methods)
8228 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8230 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8234 * mono_class_get_finalizer:
8235 * @klass: The MonoClass pointer
8237 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8240 mono_class_get_finalizer (MonoClass *klass)
8242 MonoCachedClassInfo cached_info;
8245 mono_class_init (klass);
8246 if (!mono_class_has_finalizer (klass))
8249 if (mono_class_get_cached_class_info (klass, &cached_info))
8250 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8252 mono_class_setup_vtable (klass);
8253 return klass->vtable [finalize_slot];
8258 * mono_class_needs_cctor_run:
8259 * @klass: the MonoClass pointer
8260 * @caller: a MonoMethod describing the caller
8262 * Determines whenever the class has a static constructor and whenever it
8263 * needs to be called when executing CALLER.
8266 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8270 method = mono_class_get_cctor (klass);
8272 return (method == caller) ? FALSE : TRUE;
8278 * mono_class_array_element_size:
8281 * Returns: the number of bytes an element of type @klass
8282 * uses when stored into an array.
8285 mono_class_array_element_size (MonoClass *klass)
8287 MonoType *type = &klass->byval_arg;
8290 switch (type->type) {
8293 case MONO_TYPE_BOOLEAN:
8297 case MONO_TYPE_CHAR:
8306 case MONO_TYPE_CLASS:
8307 case MONO_TYPE_STRING:
8308 case MONO_TYPE_OBJECT:
8309 case MONO_TYPE_SZARRAY:
8310 case MONO_TYPE_ARRAY:
8312 case MONO_TYPE_MVAR:
8313 return sizeof (gpointer);
8318 case MONO_TYPE_VALUETYPE:
8319 if (type->data.klass->enumtype) {
8320 type = mono_class_enum_basetype (type->data.klass);
8321 klass = klass->element_class;
8324 return mono_class_instance_size (klass) - sizeof (MonoObject);
8325 case MONO_TYPE_GENERICINST:
8326 type = &type->data.generic_class->container_class->byval_arg;
8329 case MONO_TYPE_VOID:
8333 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8339 * mono_array_element_size:
8340 * @ac: pointer to a #MonoArrayClass
8342 * Returns: the size of single array element.
8345 mono_array_element_size (MonoClass *ac)
8347 g_assert (ac->rank);
8348 return ac->sizes.element_size;
8352 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8353 MonoGenericContext *context)
8355 if (image_is_dynamic (image)) {
8356 MonoClass *tmp_handle_class;
8357 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8359 g_assert (tmp_handle_class);
8361 *handle_class = tmp_handle_class;
8363 if (tmp_handle_class == mono_defaults.typehandle_class)
8364 return &((MonoClass*)obj)->byval_arg;
8369 switch (token & 0xff000000) {
8370 case MONO_TOKEN_TYPE_DEF:
8371 case MONO_TOKEN_TYPE_REF:
8372 case MONO_TOKEN_TYPE_SPEC: {
8376 *handle_class = mono_defaults.typehandle_class;
8377 type = mono_type_get_checked (image, token, context, &error);
8379 mono_loader_set_error_from_mono_error (&error);
8380 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8383 mono_class_init (mono_class_from_mono_type (type));
8384 /* We return a MonoType* as handle */
8387 case MONO_TOKEN_FIELD_DEF: {
8390 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8394 *handle_class = mono_defaults.fieldhandle_class;
8395 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8397 mono_loader_set_error_from_mono_error (&error);
8398 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8401 mono_class_init (class);
8402 return mono_class_get_field (class, token);
8404 case MONO_TOKEN_METHOD_DEF:
8405 case MONO_TOKEN_METHOD_SPEC: {
8407 meth = mono_get_method_full (image, token, NULL, context);
8409 *handle_class = mono_defaults.methodhandle_class;
8412 case MONO_TOKEN_MEMBER_REF: {
8413 guint32 cols [MONO_MEMBERREF_SIZE];
8415 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8416 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8417 mono_metadata_decode_blob_size (sig, &sig);
8418 if (*sig == 0x6) { /* it's a field */
8420 MonoClassField *field;
8421 field = mono_field_from_token (image, token, &klass, context);
8423 *handle_class = mono_defaults.fieldhandle_class;
8427 meth = mono_get_method_full (image, token, NULL, context);
8429 *handle_class = mono_defaults.methodhandle_class;
8434 g_warning ("Unknown token 0x%08x in ldtoken", token);
8441 * This function might need to call runtime functions so it can't be part
8442 * of the metadata library.
8444 static MonoLookupDynamicToken lookup_dynamic = NULL;
8447 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8449 lookup_dynamic = func;
8453 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8455 MonoClass *handle_class;
8457 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8461 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8463 return lookup_dynamic (image, token, valid_token, handle_class, context);
8466 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8469 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8471 get_cached_class_info = func;
8475 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8477 if (!get_cached_class_info)
8480 return get_cached_class_info (klass, res);
8484 mono_install_get_class_from_name (MonoGetClassFromName func)
8486 get_class_from_name = func;
8490 mono_class_get_image (MonoClass *klass)
8492 return klass->image;
8496 * mono_class_get_element_class:
8497 * @klass: the MonoClass to act on
8499 * Returns: the element class of an array or an enumeration.
8502 mono_class_get_element_class (MonoClass *klass)
8504 return klass->element_class;
8508 * mono_class_is_valuetype:
8509 * @klass: the MonoClass to act on
8511 * Returns: true if the MonoClass represents a ValueType.
8514 mono_class_is_valuetype (MonoClass *klass)
8516 return klass->valuetype;
8520 * mono_class_is_enum:
8521 * @klass: the MonoClass to act on
8523 * Returns: true if the MonoClass represents an enumeration.
8526 mono_class_is_enum (MonoClass *klass)
8528 return klass->enumtype;
8532 * mono_class_enum_basetype:
8533 * @klass: the MonoClass to act on
8535 * Returns: the underlying type representation for an enumeration.
8538 mono_class_enum_basetype (MonoClass *klass)
8540 if (klass->element_class == klass)
8541 /* SRE or broken types */
8544 return &klass->element_class->byval_arg;
8548 * mono_class_get_parent
8549 * @klass: the MonoClass to act on
8551 * Returns: the parent class for this class.
8554 mono_class_get_parent (MonoClass *klass)
8556 return klass->parent;
8560 * mono_class_get_nesting_type;
8561 * @klass: the MonoClass to act on
8563 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8566 mono_class_get_nesting_type (MonoClass *klass)
8568 return klass->nested_in;
8572 * mono_class_get_rank:
8573 * @klass: the MonoClass to act on
8575 * Returns: the rank for the array (the number of dimensions).
8578 mono_class_get_rank (MonoClass *klass)
8584 * mono_class_get_flags:
8585 * @klass: the MonoClass to act on
8587 * The type flags from the TypeDef table from the metadata.
8588 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8591 * Returns: the flags from the TypeDef table.
8594 mono_class_get_flags (MonoClass *klass)
8596 return klass->flags;
8600 * mono_class_get_name
8601 * @klass: the MonoClass to act on
8603 * Returns: the name of the class.
8606 mono_class_get_name (MonoClass *klass)
8612 * mono_class_get_namespace:
8613 * @klass: the MonoClass to act on
8615 * Returns: the namespace of the class.
8618 mono_class_get_namespace (MonoClass *klass)
8620 return klass->name_space;
8624 * mono_class_get_type:
8625 * @klass: the MonoClass to act on
8627 * This method returns the internal Type representation for the class.
8629 * Returns: the MonoType from the class.
8632 mono_class_get_type (MonoClass *klass)
8634 return &klass->byval_arg;
8638 * mono_class_get_type_token
8639 * @klass: the MonoClass to act on
8641 * This method returns type token for the class.
8643 * Returns: the type token for the class.
8646 mono_class_get_type_token (MonoClass *klass)
8648 return klass->type_token;
8652 * mono_class_get_byref_type:
8653 * @klass: the MonoClass to act on
8658 mono_class_get_byref_type (MonoClass *klass)
8660 return &klass->this_arg;
8664 * mono_class_num_fields:
8665 * @klass: the MonoClass to act on
8667 * Returns: the number of static and instance fields in the class.
8670 mono_class_num_fields (MonoClass *klass)
8672 return klass->field.count;
8676 * mono_class_num_methods:
8677 * @klass: the MonoClass to act on
8679 * Returns: the number of methods in the class.
8682 mono_class_num_methods (MonoClass *klass)
8684 return klass->method.count;
8688 * mono_class_num_properties
8689 * @klass: the MonoClass to act on
8691 * Returns: the number of properties in the class.
8694 mono_class_num_properties (MonoClass *klass)
8696 mono_class_setup_properties (klass);
8698 return klass->ext->property.count;
8702 * mono_class_num_events:
8703 * @klass: the MonoClass to act on
8705 * Returns: the number of events in the class.
8708 mono_class_num_events (MonoClass *klass)
8710 mono_class_setup_events (klass);
8712 return klass->ext->event.count;
8716 * mono_class_get_fields:
8717 * @klass: the MonoClass to act on
8719 * This routine is an iterator routine for retrieving the fields in a class.
8721 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8722 * iterate over all of the elements. When no more values are
8723 * available, the return value is NULL.
8725 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8728 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8730 MonoClassField* field;
8734 mono_class_setup_fields_locking (klass);
8735 if (klass->exception_type)
8737 /* start from the first */
8738 if (klass->field.count) {
8739 return *iter = &klass->fields [0];
8747 if (field < &klass->fields [klass->field.count]) {
8748 return *iter = field;
8754 * mono_class_get_methods
8755 * @klass: the MonoClass to act on
8757 * This routine is an iterator routine for retrieving the fields in a class.
8759 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8760 * iterate over all of the elements. When no more values are
8761 * available, the return value is NULL.
8763 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8766 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8768 MonoMethod** method;
8772 mono_class_setup_methods (klass);
8775 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8776 * FIXME we should better report this error to the caller
8778 if (!klass->methods)
8780 /* start from the first */
8781 if (klass->method.count) {
8782 *iter = &klass->methods [0];
8783 return klass->methods [0];
8791 if (method < &klass->methods [klass->method.count]) {
8799 * mono_class_get_virtual_methods:
8801 * Iterate over the virtual methods of KLASS.
8803 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8806 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8808 MonoMethod** method;
8811 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8813 mono_class_setup_methods (klass);
8815 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8816 * FIXME we should better report this error to the caller
8818 if (!klass->methods)
8820 /* start from the first */
8821 method = &klass->methods [0];
8826 while (method < &klass->methods [klass->method.count]) {
8827 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8831 if (method < &klass->methods [klass->method.count]) {
8838 /* Search directly in metadata to avoid calling setup_methods () */
8839 MonoMethod *res = NULL;
8845 start_index = GPOINTER_TO_UINT (*iter);
8848 for (i = start_index; i < klass->method.count; ++i) {
8851 /* class->method.first points into the methodptr table */
8852 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8854 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8858 if (i < klass->method.count) {
8859 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8860 /* Add 1 here so the if (*iter) check fails */
8861 *iter = GUINT_TO_POINTER (i + 1);
8870 * mono_class_get_properties:
8871 * @klass: the MonoClass to act on
8873 * This routine is an iterator routine for retrieving the properties in a class.
8875 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8876 * iterate over all of the elements. When no more values are
8877 * available, the return value is NULL.
8879 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8882 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8884 MonoProperty* property;
8888 mono_class_setup_properties (klass);
8889 /* start from the first */
8890 if (klass->ext->property.count) {
8891 return *iter = &klass->ext->properties [0];
8899 if (property < &klass->ext->properties [klass->ext->property.count]) {
8900 return *iter = property;
8906 * mono_class_get_events:
8907 * @klass: the MonoClass to act on
8909 * This routine is an iterator routine for retrieving the properties in a class.
8911 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8912 * iterate over all of the elements. When no more values are
8913 * available, the return value is NULL.
8915 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8918 mono_class_get_events (MonoClass* klass, gpointer *iter)
8924 mono_class_setup_events (klass);
8925 /* start from the first */
8926 if (klass->ext->event.count) {
8927 return *iter = &klass->ext->events [0];
8935 if (event < &klass->ext->events [klass->ext->event.count]) {
8936 return *iter = event;
8942 * mono_class_get_interfaces
8943 * @klass: the MonoClass to act on
8945 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8947 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8948 * iterate over all of the elements. When no more values are
8949 * available, the return value is NULL.
8951 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8954 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8962 mono_class_init (klass);
8963 if (!klass->interfaces_inited) {
8964 mono_class_setup_interfaces (klass, &error);
8965 if (!mono_error_ok (&error)) {
8966 mono_error_cleanup (&error);
8970 /* start from the first */
8971 if (klass->interface_count) {
8972 *iter = &klass->interfaces [0];
8973 return klass->interfaces [0];
8981 if (iface < &klass->interfaces [klass->interface_count]) {
8989 setup_nested_types (MonoClass *klass)
8992 GList *classes, *nested_classes, *l;
8995 if (klass->nested_classes_inited)
8998 if (!klass->type_token)
8999 klass->nested_classes_inited = TRUE;
9001 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9005 guint32 cols [MONO_NESTED_CLASS_SIZE];
9006 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9007 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9008 if (!mono_error_ok (&error)) {
9009 /*FIXME don't swallow the error message*/
9010 mono_error_cleanup (&error);
9012 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9016 classes = g_list_prepend (classes, nclass);
9018 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9021 mono_class_alloc_ext (klass);
9023 nested_classes = NULL;
9024 for (l = classes; l; l = l->next)
9025 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9026 g_list_free (classes);
9028 mono_image_lock (klass->image);
9030 mono_memory_barrier ();
9031 if (!klass->nested_classes_inited) {
9032 klass->ext->nested_classes = nested_classes;
9033 mono_memory_barrier ();
9034 klass->nested_classes_inited = TRUE;
9037 mono_image_unlock (klass->image);
9041 * mono_class_get_nested_types
9042 * @klass: the MonoClass to act on
9044 * This routine is an iterator routine for retrieving the nested types of a class.
9045 * This works only if @klass is non-generic, or a generic type definition.
9047 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9048 * iterate over all of the elements. When no more values are
9049 * available, the return value is NULL.
9051 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9054 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9060 if (!klass->nested_classes_inited)
9061 setup_nested_types (klass);
9064 /* start from the first */
9065 if (klass->ext && klass->ext->nested_classes) {
9066 *iter = klass->ext->nested_classes;
9067 return klass->ext->nested_classes->data;
9069 /* no nested types */
9084 * mono_class_is_delegate
9085 * @klass: the MonoClass to act on
9087 * Returns: true if the MonoClass represents a System.Delegate.
9090 mono_class_is_delegate (MonoClass *klass)
9092 return klass->delegate;
9096 * mono_class_implements_interface
9097 * @klass: The MonoClass to act on
9098 * @interface: The interface to check if @klass implements.
9100 * Returns: true if @klass implements @interface.
9103 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9105 return mono_class_is_assignable_from (iface, klass);
9109 * mono_field_get_name:
9110 * @field: the MonoClassField to act on
9112 * Returns: the name of the field.
9115 mono_field_get_name (MonoClassField *field)
9121 * mono_field_get_type:
9122 * @field: the MonoClassField to act on
9124 * Returns: MonoType of the field.
9127 mono_field_get_type (MonoClassField *field)
9130 MonoType *type = mono_field_get_type_checked (field, &error);
9131 if (!mono_error_ok (&error)) {
9132 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9133 mono_error_cleanup (&error);
9140 * mono_field_get_type_checked:
9141 * @field: the MonoClassField to act on
9142 * @error: used to return any erro found while retrieving @field type
9144 * Returns: MonoType of the field.
9147 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9149 mono_error_init (error);
9151 mono_field_resolve_type (field, error);
9156 * mono_field_get_parent:
9157 * @field: the MonoClassField to act on
9159 * Returns: MonoClass where the field was defined.
9162 mono_field_get_parent (MonoClassField *field)
9164 return field->parent;
9168 * mono_field_get_flags;
9169 * @field: the MonoClassField to act on
9171 * The metadata flags for a field are encoded using the
9172 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9174 * Returns: the flags for the field.
9177 mono_field_get_flags (MonoClassField *field)
9180 return mono_field_resolve_flags (field);
9181 return field->type->attrs;
9185 * mono_field_get_offset;
9186 * @field: the MonoClassField to act on
9188 * Returns: the field offset.
9191 mono_field_get_offset (MonoClassField *field)
9193 return field->offset;
9197 mono_field_get_rva (MonoClassField *field)
9201 MonoClass *klass = field->parent;
9202 MonoFieldDefaultValue *field_def_values;
9204 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9206 if (!klass->ext || !klass->ext->field_def_values) {
9207 mono_class_alloc_ext (klass);
9209 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9211 mono_image_lock (klass->image);
9212 if (!klass->ext->field_def_values)
9213 klass->ext->field_def_values = field_def_values;
9214 mono_image_unlock (klass->image);
9217 field_index = mono_field_get_index (field);
9219 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9220 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9222 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9223 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9226 return klass->ext->field_def_values [field_index].data;
9230 * mono_field_get_data;
9231 * @field: the MonoClassField to act on
9233 * Returns: pointer to the metadata constant value or to the field
9234 * data if it has an RVA flag.
9237 mono_field_get_data (MonoClassField *field)
9239 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9240 MonoTypeEnum def_type;
9242 return mono_class_get_field_default_value (field, &def_type);
9243 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9244 return mono_field_get_rva (field);
9251 * mono_property_get_name:
9252 * @prop: the MonoProperty to act on
9254 * Returns: the name of the property
9257 mono_property_get_name (MonoProperty *prop)
9263 * mono_property_get_set_method
9264 * @prop: the MonoProperty to act on.
9266 * Returns: the setter method of the property (A MonoMethod)
9269 mono_property_get_set_method (MonoProperty *prop)
9275 * mono_property_get_get_method
9276 * @prop: the MonoProperty to act on.
9278 * Returns: the setter method of the property (A MonoMethod)
9281 mono_property_get_get_method (MonoProperty *prop)
9287 * mono_property_get_parent:
9288 * @prop: the MonoProperty to act on.
9290 * Returns: the MonoClass where the property was defined.
9293 mono_property_get_parent (MonoProperty *prop)
9295 return prop->parent;
9299 * mono_property_get_flags:
9300 * @prop: the MonoProperty to act on.
9302 * The metadata flags for a property are encoded using the
9303 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9305 * Returns: the flags for the property.
9308 mono_property_get_flags (MonoProperty *prop)
9314 * mono_event_get_name:
9315 * @event: the MonoEvent to act on
9317 * Returns: the name of the event.
9320 mono_event_get_name (MonoEvent *event)
9326 * mono_event_get_add_method:
9327 * @event: The MonoEvent to act on.
9329 * Returns: the @add' method for the event (a MonoMethod).
9332 mono_event_get_add_method (MonoEvent *event)
9338 * mono_event_get_remove_method:
9339 * @event: The MonoEvent to act on.
9341 * Returns: the @remove method for the event (a MonoMethod).
9344 mono_event_get_remove_method (MonoEvent *event)
9346 return event->remove;
9350 * mono_event_get_raise_method:
9351 * @event: The MonoEvent to act on.
9353 * Returns: the @raise method for the event (a MonoMethod).
9356 mono_event_get_raise_method (MonoEvent *event)
9358 return event->raise;
9362 * mono_event_get_parent:
9363 * @event: the MonoEvent to act on.
9365 * Returns: the MonoClass where the event is defined.
9368 mono_event_get_parent (MonoEvent *event)
9370 return event->parent;
9374 * mono_event_get_flags
9375 * @event: the MonoEvent to act on.
9377 * The metadata flags for an event are encoded using the
9378 * EVENT_* constants. See the tabledefs.h file for details.
9380 * Returns: the flags for the event.
9383 mono_event_get_flags (MonoEvent *event)
9385 return event->attrs;
9389 * mono_class_get_method_from_name:
9390 * @klass: where to look for the method
9391 * @name: name of the method
9392 * @param_count: number of parameters. -1 for any number.
9394 * Obtains a MonoMethod with a given name and number of parameters.
9395 * It only works if there are no multiple signatures for any given method name.
9398 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9400 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9404 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9406 MonoMethod *res = NULL;
9409 /* Search directly in the metadata to avoid calling setup_methods () */
9410 for (i = 0; i < klass->method.count; ++i) {
9411 guint32 cols [MONO_METHOD_SIZE];
9413 MonoMethodSignature *sig;
9415 /* class->method.first points into the methodptr table */
9416 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9418 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9419 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9420 if (param_count == -1) {
9424 sig = mono_method_signature (method);
9425 if (sig && sig->param_count == param_count) {
9436 * mono_class_get_method_from_name_flags:
9437 * @klass: where to look for the method
9438 * @name_space: name of the method
9439 * @param_count: number of parameters. -1 for any number.
9440 * @flags: flags which must be set in the method
9442 * Obtains a MonoMethod with a given name and number of parameters.
9443 * It only works if there are no multiple signatures for any given method name.
9446 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9448 MonoMethod *res = NULL;
9451 mono_class_init (klass);
9453 if (klass->generic_class && !klass->methods) {
9454 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9456 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9460 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9461 mono_class_setup_methods (klass);
9463 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9464 See mono/tests/array_load_exception.il
9465 FIXME we should better report this error to the caller
9467 if (!klass->methods)
9469 for (i = 0; i < klass->method.count; ++i) {
9470 MonoMethod *method = klass->methods [i];
9472 if (method->name[0] == name [0] &&
9473 !strcmp (name, method->name) &&
9474 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9475 ((method->flags & flags) == flags)) {
9482 res = find_method_in_metadata (klass, name, param_count, flags);
9489 * mono_class_set_failure:
9490 * @klass: class in which the failure was detected
9491 * @ex_type: the kind of exception/error to be thrown (later)
9492 * @ex_data: exception data (specific to each type of exception/error)
9494 * Keep a detected failure informations in the class for later processing.
9495 * Note that only the first failure is kept.
9497 * LOCKING: Acquires the loader lock.
9500 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9502 if (klass->exception_type)
9505 mono_loader_lock ();
9506 klass->exception_type = ex_type;
9508 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9509 mono_loader_unlock ();
9515 * mono_class_get_exception_data:
9517 * Return the exception_data property of KLASS.
9519 * LOCKING: Acquires the loader lock.
9522 mono_class_get_exception_data (MonoClass *klass)
9524 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9528 * mono_classes_init:
9530 * Initialize the resources used by this module.
9533 mono_classes_init (void)
9535 mono_mutex_init (&classes_mutex);
9537 mono_counters_register ("Inflated methods size",
9538 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9539 mono_counters_register ("Inflated classes",
9540 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9541 mono_counters_register ("Inflated classes size",
9542 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9543 mono_counters_register ("MonoClass size",
9544 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9545 mono_counters_register ("MonoClassExt size",
9546 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9550 * mono_classes_cleanup:
9552 * Free the resources used by this module.
9555 mono_classes_cleanup (void)
9557 if (global_interface_bitset)
9558 mono_bitset_free (global_interface_bitset);
9559 global_interface_bitset = NULL;
9560 mono_mutex_destroy (&classes_mutex);
9564 * mono_class_get_exception_for_failure:
9565 * @klass: class in which the failure was detected
9567 * Return a constructed MonoException than the caller can then throw
9568 * using mono_raise_exception - or NULL if no failure is present (or
9569 * doesn't result in an exception).
9572 mono_class_get_exception_for_failure (MonoClass *klass)
9574 gpointer exception_data = mono_class_get_exception_data (klass);
9576 switch (klass->exception_type) {
9577 #ifndef DISABLE_SECURITY
9578 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9579 MonoDomain *domain = mono_domain_get ();
9580 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9581 MonoMethod *method = exception_data;
9582 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9583 MonoObject *exc = NULL;
9587 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9588 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9589 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9591 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9592 return (MonoException*) exc;
9595 case MONO_EXCEPTION_TYPE_LOAD: {
9598 char *str = mono_type_get_full_name (klass);
9599 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9600 name = mono_string_new (mono_domain_get (), str);
9602 ex = mono_get_exception_type_load (name, astr);
9606 case MONO_EXCEPTION_MISSING_METHOD: {
9607 char *class_name = exception_data;
9608 char *assembly_name = class_name + strlen (class_name) + 1;
9610 return mono_get_exception_missing_method (class_name, assembly_name);
9612 case MONO_EXCEPTION_MISSING_FIELD: {
9613 char *class_name = exception_data;
9614 char *member_name = class_name + strlen (class_name) + 1;
9616 return mono_get_exception_missing_field (class_name, member_name);
9618 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9619 char *msg_format = exception_data;
9620 char *assembly_name = msg_format + strlen (msg_format) + 1;
9621 char *msg = g_strdup_printf (msg_format, assembly_name);
9624 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9630 case MONO_EXCEPTION_BAD_IMAGE: {
9631 return mono_get_exception_bad_image_format (exception_data);
9634 MonoLoaderError *error;
9637 error = mono_loader_get_last_error ();
9639 ex = mono_loader_error_prepare_exception (error);
9643 /* TODO - handle other class related failures */
9650 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9652 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9653 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9655 if (outer_klass == inner_klass)
9657 inner_klass = inner_klass->nested_in;
9658 } while (inner_klass);
9663 mono_class_get_generic_type_definition (MonoClass *klass)
9665 return klass->generic_class ? klass->generic_class->container_class : klass;
9669 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9671 * Generic instantiations are ignored for all super types of @klass.
9673 * Visibility checks ignoring generic instantiations.
9676 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9679 klass = mono_class_get_generic_type_definition (klass);
9680 parent = mono_class_get_generic_type_definition (parent);
9681 mono_class_setup_supertypes (klass);
9683 for (i = 0; i < klass->idepth; ++i) {
9684 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9690 * Subtype can only access parent members with family protection if the site object
9691 * is subclass of Subtype. For example:
9692 * class A { protected int x; }
9694 * void valid_access () {
9698 * void invalid_access () {
9705 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9707 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9710 if (context_klass == NULL)
9712 /*if access_klass is not member_klass context_klass must be type compat*/
9713 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9719 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9722 if (accessing == accessed)
9724 if (!accessed || !accessing)
9727 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9728 * anywhere so untrusted friends are not safe to access platform's code internals */
9729 if (mono_security_core_clr_enabled ()) {
9730 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9734 mono_assembly_load_friends (accessed);
9735 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9736 MonoAssemblyName *friend = tmp->data;
9737 /* Be conservative with checks */
9740 if (strcmp (accessing->aname.name, friend->name))
9742 if (friend->public_key_token [0]) {
9743 if (!accessing->aname.public_key_token [0])
9745 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9754 * If klass is a generic type or if it is derived from a generic type, return the
9755 * MonoClass of the generic definition
9756 * Returns NULL if not found
9759 get_generic_definition_class (MonoClass *klass)
9762 if (klass->generic_class && klass->generic_class->container_class)
9763 return klass->generic_class->container_class;
9764 klass = klass->parent;
9770 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9773 for (i = 0; i < ginst->type_argc; ++i) {
9774 MonoType *type = ginst->type_argv[i];
9775 switch (type->type) {
9776 case MONO_TYPE_SZARRAY:
9777 if (!can_access_type (access_klass, type->data.klass))
9780 case MONO_TYPE_ARRAY:
9781 if (!can_access_type (access_klass, type->data.array->eklass))
9785 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9788 case MONO_TYPE_CLASS:
9789 case MONO_TYPE_VALUETYPE:
9790 case MONO_TYPE_GENERICINST:
9791 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9799 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9803 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9806 if (access_klass->element_class && !access_klass->enumtype)
9807 access_klass = access_klass->element_class;
9809 if (member_klass->element_class && !member_klass->enumtype)
9810 member_klass = member_klass->element_class;
9812 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9814 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9817 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9820 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9823 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9826 /*Non nested type with nested visibility. We just fail it.*/
9827 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9830 switch (access_level) {
9831 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9832 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9834 case TYPE_ATTRIBUTE_PUBLIC:
9837 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9840 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9841 return is_nesting_type (member_klass, access_klass);
9843 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9844 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9846 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9847 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9849 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9850 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9851 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9853 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9854 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9855 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9860 /* FIXME: check visibility of type, too */
9862 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9864 MonoClass *member_generic_def;
9865 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9868 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9869 access_klass->generic_container) &&
9870 (member_generic_def = get_generic_definition_class (member_klass))) {
9871 MonoClass *access_container;
9873 if (access_klass->generic_container)
9874 access_container = access_klass;
9876 access_container = access_klass->generic_class->container_class;
9878 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9882 /* Partition I 8.5.3.2 */
9883 /* the access level values are the same for fields and methods */
9884 switch (access_level) {
9885 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9886 /* same compilation unit */
9887 return access_klass->image == member_klass->image;
9888 case FIELD_ATTRIBUTE_PRIVATE:
9889 return access_klass == member_klass;
9890 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9891 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9892 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9895 case FIELD_ATTRIBUTE_ASSEMBLY:
9896 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9897 case FIELD_ATTRIBUTE_FAMILY:
9898 if (is_valid_family_access (access_klass, member_klass, context_klass))
9901 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9902 if (is_valid_family_access (access_klass, member_klass, context_klass))
9904 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9905 case FIELD_ATTRIBUTE_PUBLIC:
9912 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9914 /* FIXME: check all overlapping fields */
9915 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9917 MonoClass *nested = method->klass->nested_in;
9919 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9922 nested = nested->nested_in;
9929 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9931 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9933 MonoClass *nested = method->klass->nested_in;
9935 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9938 nested = nested->nested_in;
9943 * with generics calls to explicit interface implementations can be expressed
9944 * directly: the method is private, but we must allow it. This may be opening
9945 * a hole or the generics code should handle this differently.
9946 * Maybe just ensure the interface type is public.
9948 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9954 * mono_method_can_access_method_full:
9955 * @method: The caller method
9956 * @called: The called method
9957 * @context_klass: The static type on stack of the owner @called object used
9959 * This function must be used with instance calls, as they have more strict family accessibility.
9960 * It can be used with static methods, but context_klass should be NULL.
9962 * Returns: TRUE if caller have proper visibility and acessibility to @called
9965 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9967 MonoClass *access_class = method->klass;
9968 MonoClass *member_class = called->klass;
9969 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9971 MonoClass *nested = access_class->nested_in;
9973 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9976 nested = nested->nested_in;
9983 can = can_access_type (access_class, member_class);
9985 MonoClass *nested = access_class->nested_in;
9987 can = can_access_type (nested, member_class);
9990 nested = nested->nested_in;
9997 if (called->is_inflated) {
9998 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9999 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10008 * mono_method_can_access_field_full:
10009 * @method: The caller method
10010 * @field: The accessed field
10011 * @context_klass: The static type on stack of the owner @field object used
10013 * This function must be used with instance fields, as they have more strict family accessibility.
10014 * It can be used with static fields, but context_klass should be NULL.
10016 * Returns: TRUE if caller have proper visibility and acessibility to @field
10019 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10021 MonoClass *access_class = method->klass;
10022 MonoClass *member_class = field->parent;
10023 /* FIXME: check all overlapping fields */
10024 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10026 MonoClass *nested = access_class->nested_in;
10028 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10031 nested = nested->nested_in;
10038 can = can_access_type (access_class, member_class);
10040 MonoClass *nested = access_class->nested_in;
10042 can = can_access_type (nested, member_class);
10045 nested = nested->nested_in;
10055 * mono_class_can_access_class:
10056 * @source_class: The source class
10057 * @target_class: The accessed class
10059 * This function returns is @target_class is visible to @source_class
10061 * Returns: TRUE if source have proper visibility and acessibility to target
10064 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10066 return can_access_type (source_class, target_class);
10070 * mono_type_is_valid_enum_basetype:
10071 * @type: The MonoType to check
10073 * Returns: TRUE if the type can be used as the basetype of an enum
10075 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10076 switch (type->type) {
10079 case MONO_TYPE_BOOLEAN:
10082 case MONO_TYPE_CHAR:
10095 * mono_class_is_valid_enum:
10096 * @klass: An enum class to be validated
10098 * This method verify the required properties an enum should have.
10100 * Returns: TRUE if the informed enum class is valid
10102 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10103 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10104 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10106 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10107 MonoClassField * field;
10108 gpointer iter = NULL;
10109 gboolean found_base_field = FALSE;
10111 g_assert (klass->enumtype);
10112 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10113 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10117 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10120 while ((field = mono_class_get_fields (klass, &iter))) {
10121 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10122 if (found_base_field)
10124 found_base_field = TRUE;
10125 if (!mono_type_is_valid_enum_basetype (field->type))
10130 if (!found_base_field)
10133 if (klass->method.count > 0)
10140 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10142 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10146 * mono_class_setup_interface_id:
10148 * Initializes MonoClass::interface_id if required.
10150 * LOCKING: Acquires the loader lock.
10153 mono_class_setup_interface_id (MonoClass *class)
10155 mono_loader_lock ();
10156 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10157 class->interface_id = mono_get_unique_iid (class);
10158 mono_loader_unlock ();
10162 * mono_class_alloc_ext:
10164 * Allocate klass->ext if not already done.
10167 mono_class_alloc_ext (MonoClass *klass)
10174 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10175 mono_image_lock (klass->image);
10176 mono_memory_barrier ();
10179 class_ext_size += sizeof (MonoClassExt);
10180 mono_image_unlock (klass->image);
10184 * mono_class_setup_interfaces:
10186 * Initialize class->interfaces/interfaces_count.
10187 * LOCKING: Acquires the loader lock.
10188 * This function can fail the type.
10191 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10193 int i, interface_count;
10194 MonoClass **interfaces;
10196 mono_error_init (error);
10198 if (klass->interfaces_inited)
10201 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10202 MonoType *args [1];
10204 /* generic IList, ICollection, IEnumerable */
10205 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10206 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10208 args [0] = &klass->element_class->byval_arg;
10209 interfaces [0] = mono_class_bind_generic_parameters (
10210 mono_defaults.generic_ilist_class, 1, args, FALSE);
10211 if (interface_count > 1)
10212 interfaces [1] = mono_class_bind_generic_parameters (
10213 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10214 } else if (klass->generic_class) {
10215 MonoClass *gklass = klass->generic_class->container_class;
10217 mono_class_setup_interfaces (gklass, error);
10218 if (!mono_error_ok (error)) {
10219 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10223 interface_count = gklass->interface_count;
10224 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10225 for (i = 0; i < interface_count; i++) {
10226 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10227 if (!mono_error_ok (error)) {
10228 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10233 interface_count = 0;
10237 mono_image_lock (klass->image);
10239 if (!klass->interfaces_inited) {
10240 klass->interface_count = interface_count;
10241 klass->interfaces = interfaces;
10243 mono_memory_barrier ();
10245 klass->interfaces_inited = TRUE;
10248 mono_image_unlock (klass->image);
10252 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10254 MonoClass *class = field->parent;
10255 MonoImage *image = class->image;
10256 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10257 int field_idx = field - class->fields;
10259 mono_error_init (error);
10262 MonoClassField *gfield = >d->fields [field_idx];
10263 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10264 if (!mono_error_ok (error)) {
10265 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10266 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10270 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10271 if (!mono_error_ok (error)) {
10272 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10273 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10278 guint32 cols [MONO_FIELD_SIZE];
10279 MonoGenericContainer *container = NULL;
10280 int idx = class->field.first + field_idx;
10282 /*FIXME, in theory we do not lazy load SRE fields*/
10283 g_assert (!image_is_dynamic (image));
10285 if (class->generic_container) {
10286 container = class->generic_container;
10288 container = gtd->generic_container;
10289 g_assert (container);
10292 /* class->field.first and idx points into the fieldptr table */
10293 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10295 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10296 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10297 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10301 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10303 mono_metadata_decode_value (sig, &sig);
10304 /* FIELD signature == 0x06 */
10305 g_assert (*sig == 0x06);
10306 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10308 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10313 mono_field_resolve_flags (MonoClassField *field)
10315 MonoClass *class = field->parent;
10316 MonoImage *image = class->image;
10317 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10318 int field_idx = field - class->fields;
10322 MonoClassField *gfield = >d->fields [field_idx];
10323 return mono_field_get_flags (gfield);
10325 int idx = class->field.first + field_idx;
10327 /*FIXME, in theory we do not lazy load SRE fields*/
10328 g_assert (!image_is_dynamic (image));
10330 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10335 * mono_class_setup_basic_field_info:
10336 * @class: The class to initialize
10338 * Initializes the class->fields array of fields.
10339 * Aquires the loader lock.
10342 mono_class_setup_basic_field_info_locking (MonoClass *class)
10344 mono_loader_lock ();
10345 mono_class_setup_basic_field_info (class);
10346 mono_loader_unlock ();
10350 * mono_class_get_fields_lazy:
10351 * @klass: the MonoClass to act on
10353 * This routine is an iterator routine for retrieving the fields in a class.
10354 * Only minimal information about fields are loaded. Accessors must be used
10355 * for all MonoClassField returned.
10357 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10358 * iterate over all of the elements. When no more values are
10359 * available, the return value is NULL.
10361 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10364 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10366 MonoClassField* field;
10370 mono_class_setup_basic_field_info_locking (klass);
10371 if (!klass->fields)
10373 /* start from the first */
10374 if (klass->field.count) {
10375 return *iter = &klass->fields [0];
10383 if (field < &klass->fields [klass->field.count]) {
10384 return *iter = field;
10390 mono_class_full_name (MonoClass *klass)
10392 return mono_type_full_name (&klass->byval_arg);