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 We use gclass recording to allow recursive system f types to be referenced by a parent.
78 Given the following type hierarchy:
80 class TextBox : TextBoxBase<TextBox> {}
81 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
82 class TextInput<T> : Input<T> where T: TextInput<T> {}
85 The runtime tries to load TextBoxBase<>.
86 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
87 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
88 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
90 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
91 at this point, iow, both are registered in the type map and both and a NULL parent. This means
92 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
94 To fix that what we do is to record all generic instantes created while resolving the parent of
95 any generic type definition and, after resolved, correct the parent field if needed.
98 static int record_gclass_instantiation;
99 static GSList *gclass_recorded_list;
100 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
105 mono_locks_acquire (&classes_mutex, ClassesLock);
109 classes_unlock (void)
111 mono_locks_release (&classes_mutex, ClassesLock);
115 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
118 enable_gclass_recording (void)
120 ++record_gclass_instantiation;
124 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
127 disable_gclass_recording (gclass_record_func func, void *user_data)
129 GSList **head = &gclass_recorded_list;
131 g_assert (record_gclass_instantiation > 0);
132 --record_gclass_instantiation;
135 GSList *node = *head;
136 if (func ((MonoClass*)node->data, user_data)) {
138 g_slist_free_1 (node);
144 /* We automatically discard all recorded gclasses when disabled. */
145 if (!record_gclass_instantiation && gclass_recorded_list) {
146 g_slist_free (gclass_recorded_list);
147 gclass_recorded_list = NULL;
152 * mono_class_from_typeref:
153 * @image: a MonoImage
154 * @type_token: a TypeRef token
156 * Creates the MonoClass* structure representing the type defined by
157 * the typeref token valid inside @image.
158 * Returns: the MonoClass* representing the typeref token, NULL ifcould
162 mono_class_from_typeref (MonoImage *image, guint32 type_token)
165 MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
166 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
171 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
173 guint32 cols [MONO_TYPEREF_SIZE];
174 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
176 const char *name, *nspace;
177 MonoClass *res = NULL;
180 mono_error_init (error);
182 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
185 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
187 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
188 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
190 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
191 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
192 case MONO_RESOLUTION_SCOPE_MODULE:
194 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
195 This is not the observed behavior of existing implementations.
196 The defacto behavior is that it's just a typedef in disguise.
198 /* a typedef in disguise */
199 res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
202 case MONO_RESOLUTION_SCOPE_MODULEREF:
203 module = mono_image_load_module (image, idx);
205 res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
208 case MONO_RESOLUTION_SCOPE_TYPEREF: {
209 MonoClass *enclosing;
212 if (idx == mono_metadata_token_index (type_token)) {
213 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
217 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
218 if (!mono_error_ok (error))
221 if (enclosing->nested_classes_inited && enclosing->ext) {
222 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
223 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
225 if (strcmp (res->name, name) == 0)
229 /* Don't call mono_class_init as we might've been called by it recursively */
230 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
232 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
233 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
234 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
236 if (strcmp (nname, name) == 0)
237 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
239 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
242 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
245 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
249 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
250 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
254 if (!image->references || !image->references [idx - 1])
255 mono_assembly_load_reference (image, idx - 1);
256 g_assert (image->references [idx - 1]);
258 /* If the assembly did not load, register this as a type load exception */
259 if (image->references [idx - 1] == REFERENCE_MISSING){
260 MonoAssemblyName aname;
263 mono_assembly_get_assemblyref (image, idx - 1, &aname);
264 human_name = mono_stringify_assembly_name (&aname);
265 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
269 res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
272 /* Generic case, should be avoided for when a better error is possible. */
273 if (!res && mono_error_ok (error)) {
274 char *name = mono_class_name_from_token (image, type_token);
275 char *assembly = mono_assembly_name_from_token (image, type_token);
276 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
283 mono_image_memdup (MonoImage *image, void *data, guint size)
285 void *res = mono_image_alloc (image, size);
286 memcpy (res, data, size);
290 /* Copy everything mono_metadata_free_array free. */
292 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
295 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
297 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
299 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
301 a = g_memdup (a, sizeof (MonoArrayType));
303 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
305 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
310 /* Copy everything mono_metadata_free_method_signature free. */
312 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
316 sig = mono_metadata_signature_dup_full (image, sig);
318 sig->ret = mono_metadata_type_dup (image, sig->ret);
319 for (i = 0; i < sig->param_count; ++i)
320 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
326 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
328 MonoAssembly *ta = klass->image->assembly;
331 name = mono_stringify_assembly_name (&ta->aname);
332 g_string_append_printf (str, ", %s", name);
337 mono_type_name_check_byref (MonoType *type, GString *str)
340 g_string_append_c (str, '&');
344 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
345 MonoTypeNameFormat format)
349 switch (type->type) {
350 case MONO_TYPE_ARRAY: {
351 int i, rank = type->data.array->rank;
352 MonoTypeNameFormat nested_format;
354 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
355 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
357 mono_type_get_name_recurse (
358 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
359 g_string_append_c (str, '[');
361 g_string_append_c (str, '*');
362 for (i = 1; i < rank; i++)
363 g_string_append_c (str, ',');
364 g_string_append_c (str, ']');
366 mono_type_name_check_byref (type, str);
368 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
369 _mono_type_get_assembly_name (type->data.array->eklass, str);
372 case MONO_TYPE_SZARRAY: {
373 MonoTypeNameFormat nested_format;
375 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
376 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
378 mono_type_get_name_recurse (
379 &type->data.klass->byval_arg, str, FALSE, nested_format);
380 g_string_append (str, "[]");
382 mono_type_name_check_byref (type, str);
384 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
385 _mono_type_get_assembly_name (type->data.klass, str);
388 case MONO_TYPE_PTR: {
389 MonoTypeNameFormat nested_format;
391 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
392 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
394 mono_type_get_name_recurse (
395 type->data.type, str, FALSE, nested_format);
396 g_string_append_c (str, '*');
398 mono_type_name_check_byref (type, str);
400 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
401 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
406 if (!mono_generic_param_info (type->data.generic_param))
407 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
409 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
411 mono_type_name_check_byref (type, str);
415 klass = mono_class_from_mono_type (type);
416 if (klass->nested_in) {
417 mono_type_get_name_recurse (
418 &klass->nested_in->byval_arg, str, TRUE, format);
419 if (format == MONO_TYPE_NAME_FORMAT_IL)
420 g_string_append_c (str, '.');
422 g_string_append_c (str, '+');
423 } else if (*klass->name_space) {
424 g_string_append (str, klass->name_space);
425 g_string_append_c (str, '.');
427 if (format == MONO_TYPE_NAME_FORMAT_IL) {
428 char *s = strchr (klass->name, '`');
429 int len = s ? s - klass->name : strlen (klass->name);
431 g_string_append_len (str, klass->name, len);
433 g_string_append (str, klass->name);
436 if (klass->generic_class) {
437 MonoGenericClass *gclass = klass->generic_class;
438 MonoGenericInst *inst = gclass->context.class_inst;
439 MonoTypeNameFormat nested_format;
442 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
443 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
445 if (format == MONO_TYPE_NAME_FORMAT_IL)
446 g_string_append_c (str, '<');
448 g_string_append_c (str, '[');
449 for (i = 0; i < inst->type_argc; i++) {
450 MonoType *t = inst->type_argv [i];
453 g_string_append_c (str, ',');
454 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
455 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
456 g_string_append_c (str, '[');
457 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
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, ']');
462 if (format == MONO_TYPE_NAME_FORMAT_IL)
463 g_string_append_c (str, '>');
465 g_string_append_c (str, ']');
466 } else if (klass->generic_container &&
467 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
468 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
471 if (format == MONO_TYPE_NAME_FORMAT_IL)
472 g_string_append_c (str, '<');
474 g_string_append_c (str, '[');
475 for (i = 0; i < klass->generic_container->type_argc; i++) {
477 g_string_append_c (str, ',');
478 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
480 if (format == MONO_TYPE_NAME_FORMAT_IL)
481 g_string_append_c (str, '>');
483 g_string_append_c (str, ']');
486 mono_type_name_check_byref (type, str);
488 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
489 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
490 _mono_type_get_assembly_name (klass, str);
496 * mono_type_get_name_full:
498 * @format: the format for the return string.
501 * Returns: the string representation in a number of formats:
503 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
504 * returned in the formatrequired by System.Reflection, this is the
505 * inverse of mono_reflection_parse_type ().
507 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
508 * be used by the IL assembler.
510 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
512 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
515 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
519 result = g_string_new ("");
521 mono_type_get_name_recurse (type, result, FALSE, format);
523 return g_string_free (result, FALSE);
527 * mono_type_get_full_name:
530 * Returns: the string representation for type as required by System.Reflection.
531 * The inverse of mono_reflection_parse_type ().
534 mono_type_get_full_name (MonoClass *class)
536 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
540 * mono_type_get_name:
543 * Returns: the string representation for type as it would be represented in IL code.
546 mono_type_get_name (MonoType *type)
548 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
552 * mono_type_get_underlying_type:
555 * Returns: the MonoType for the underlying integer type if @type
556 * is an enum and byref is false, otherwise the type itself.
559 mono_type_get_underlying_type (MonoType *type)
561 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
562 return mono_class_enum_basetype (type->data.klass);
563 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
564 return mono_class_enum_basetype (type->data.generic_class->container_class);
569 * mono_class_is_open_constructed_type:
572 * Returns TRUE if type represents a generics open constructed type.
573 * IOW, not all type parameters required for the instantiation have
574 * been provided or it's a generic type definition.
576 * An open constructed type means it's a non realizable type. Not to
577 * be mixed up with an abstract type - we can't cast or dispatch to
578 * an open type, for example.
581 mono_class_is_open_constructed_type (MonoType *t)
587 case MONO_TYPE_SZARRAY:
588 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
589 case MONO_TYPE_ARRAY:
590 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
592 return mono_class_is_open_constructed_type (t->data.type);
593 case MONO_TYPE_GENERICINST:
594 return t->data.generic_class->context.class_inst->is_open;
595 case MONO_TYPE_CLASS:
596 case MONO_TYPE_VALUETYPE:
597 return t->data.klass->generic_container != NULL;
604 This is a simple function to catch the most common bad instances of generic types.
605 Specially those that might lead to further failures in the runtime.
608 is_valid_generic_argument (MonoType *type)
610 switch (type->type) {
612 //case MONO_TYPE_TYPEDBYREF:
619 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
621 mono_error_init (error);
623 switch (type->type) {
624 case MONO_TYPE_MVAR: {
626 int num = mono_type_get_generic_param_num (type);
627 MonoGenericInst *inst = context->method_inst;
628 if (!inst || !inst->type_argv)
630 if (num >= inst->type_argc) {
631 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
632 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
633 num, info ? info->name : "", inst->type_argc);
637 if (!is_valid_generic_argument (inst->type_argv [num])) {
638 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
639 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
640 num, info ? info->name : "", inst->type_argv [num]->type);
644 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
645 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
646 * ->byref and ->attrs from @type are propagated to the returned type.
648 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
649 nt->byref = type->byref;
650 nt->attrs = type->attrs;
653 case MONO_TYPE_VAR: {
655 int num = mono_type_get_generic_param_num (type);
656 MonoGenericInst *inst = context->class_inst;
659 if (num >= inst->type_argc) {
660 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
661 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
662 num, info ? info->name : "", inst->type_argc);
665 if (!is_valid_generic_argument (inst->type_argv [num])) {
666 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
667 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
668 num, info ? info->name : "", inst->type_argv [num]->type);
671 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
672 nt->byref = type->byref;
673 nt->attrs = type->attrs;
676 case MONO_TYPE_SZARRAY: {
677 MonoClass *eclass = type->data.klass;
678 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
679 if (!inflated || !mono_error_ok (error))
681 nt = mono_metadata_type_dup (image, type);
682 nt->data.klass = mono_class_from_mono_type (inflated);
683 mono_metadata_free_type (inflated);
686 case MONO_TYPE_ARRAY: {
687 MonoClass *eclass = type->data.array->eklass;
688 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
689 if (!inflated || !mono_error_ok (error))
691 nt = mono_metadata_type_dup (image, type);
692 nt->data.array->eklass = mono_class_from_mono_type (inflated);
693 mono_metadata_free_type (inflated);
696 case MONO_TYPE_GENERICINST: {
697 MonoGenericClass *gclass = type->data.generic_class;
698 MonoGenericInst *inst;
700 if (!gclass->context.class_inst->is_open)
703 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
704 if (!mono_error_ok (error))
706 if (inst != gclass->context.class_inst)
707 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
709 if (gclass == type->data.generic_class)
712 nt = mono_metadata_type_dup (image, type);
713 nt->data.generic_class = gclass;
716 case MONO_TYPE_CLASS:
717 case MONO_TYPE_VALUETYPE: {
718 MonoClass *klass = type->data.klass;
719 MonoGenericContainer *container = klass->generic_container;
720 MonoGenericInst *inst;
721 MonoGenericClass *gclass = NULL;
727 /* We can't use context->class_inst directly, since it can have more elements */
728 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
729 if (!mono_error_ok (error))
731 if (inst == container->context.class_inst)
734 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
736 nt = mono_metadata_type_dup (image, type);
737 nt->type = MONO_TYPE_GENERICINST;
738 nt->data.generic_class = gclass;
748 mono_generic_class_get_context (MonoGenericClass *gclass)
750 return &gclass->context;
754 mono_class_get_context (MonoClass *class)
756 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
760 * mono_class_get_generic_container:
762 * Return the generic container of KLASS which should be a generic type definition.
764 MonoGenericContainer*
765 mono_class_get_generic_container (MonoClass *klass)
767 g_assert (klass->is_generic);
769 return klass->generic_container;
773 * mono_class_get_generic_class:
775 * Return the MonoGenericClass of KLASS, which should be a generic instance.
778 mono_class_get_generic_class (MonoClass *klass)
780 g_assert (klass->is_inflated);
782 return klass->generic_class;
786 * mono_class_inflate_generic_type_with_mempool:
787 * @mempool: a mempool
789 * @context: a generics context
790 * @error: error context
792 * The same as mono_class_inflate_generic_type, but allocates the MonoType
793 * from mempool if it is non-NULL. If it is NULL, the MonoType is
794 * allocated on the heap and is owned by the caller.
795 * The returned type can potentially be the same as TYPE, so it should not be
796 * modified by the caller, and it should be freed using mono_metadata_free_type ().
799 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
801 MonoType *inflated = NULL;
802 mono_error_init (error);
805 inflated = inflate_generic_type (image, type, context, error);
806 if (!mono_error_ok (error))
810 MonoType *shared = mono_metadata_get_shared_type (type);
815 return mono_metadata_type_dup (image, type);
819 mono_stats.inflated_type_count++;
824 * mono_class_inflate_generic_type:
826 * @context: a generics context
828 * If @type is a generic type and @context is not NULL, instantiate it using the
829 * generics context @context.
831 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
832 * on the heap and is owned by the caller. Returns NULL on error.
834 * @deprecated Please use mono_class_inflate_generic_type_checked instead
837 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
841 result = mono_class_inflate_generic_type_checked (type, context, &error);
843 if (!mono_error_ok (&error)) {
844 mono_error_cleanup (&error);
851 * mono_class_inflate_generic_type:
853 * @context: a generics context
854 * @error: error context to use
856 * If @type is a generic type and @context is not NULL, instantiate it using the
857 * generics context @context.
859 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
860 * on the heap and is owned by the caller.
863 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
865 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
869 * mono_class_inflate_generic_type_no_copy:
871 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
875 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
877 MonoType *inflated = NULL;
879 mono_error_init (error);
881 inflated = inflate_generic_type (image, type, context, error);
882 if (!mono_error_ok (error))
889 mono_stats.inflated_type_count++;
894 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
899 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
900 if (!mono_error_ok (error))
903 res = mono_class_from_mono_type (inflated);
904 mono_metadata_free_type (inflated);
909 * mono_class_inflate_generic_class:
911 * Inflate the class GKLASS with CONTEXT.
914 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
919 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
920 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
927 static MonoGenericContext
928 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
930 MonoGenericInst *class_inst = NULL;
931 MonoGenericInst *method_inst = NULL;
932 MonoGenericContext res = { NULL, NULL };
934 mono_error_init (error);
936 if (context->class_inst) {
937 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
938 if (!mono_error_ok (error))
942 if (context->method_inst) {
943 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
944 if (!mono_error_ok (error))
948 res.class_inst = class_inst;
949 res.method_inst = method_inst;
955 * mono_class_inflate_generic_method:
956 * @method: a generic method
957 * @context: a generics context
959 * Instantiate the generic method @method using the generics context @context.
961 * Returns: the new instantiated method
964 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
966 return mono_class_inflate_generic_method_full (method, NULL, context);
970 * mono_class_inflate_generic_method_full:
972 * Instantiate method @method with the generic context @context.
973 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
974 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
977 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
980 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
981 if (!mono_error_ok (&error))
982 /*FIXME do proper error handling - on this case, kill this function. */
983 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
989 * mono_class_inflate_generic_method_full_checked:
990 * Same as mono_class_inflate_generic_method_full but return failure using @error.
993 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
996 MonoMethodInflated *iresult, *cached;
997 MonoMethodSignature *sig;
998 MonoGenericContext tmp_context;
999 gboolean is_mb_open = FALSE;
1001 mono_error_init (error);
1003 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1004 while (method->is_inflated) {
1005 MonoGenericContext *method_context = mono_method_get_context (method);
1006 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1008 tmp_context = inflate_generic_context (method_context, context, error);
1009 if (!mono_error_ok (error))
1011 context = &tmp_context;
1013 if (mono_metadata_generic_context_equal (method_context, context))
1016 method = imethod->declaring;
1020 * A method only needs to be inflated if the context has argument for which it is
1023 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1024 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1027 if (!((method->is_generic && context->method_inst) ||
1028 (method->klass->generic_container && context->class_inst)))
1032 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1033 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1034 * This is opposite to the way non-SRE MethodInfos behave.
1036 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1038 * void Example<T> () {
1042 * In Example, the method token must be encoded as: "void Example<!!0>()"
1044 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1045 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1047 * On the other hand, inflating a non-SRE generic method with its own arguments should
1048 * return itself. For example:
1050 * MethodInfo m = ... //m is a generic method definition
1051 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1054 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1055 * what happens with regular methods.
1057 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1058 * everything should behave like a regular type or method.
1061 is_mb_open = method->is_generic &&
1062 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1063 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1065 iresult = g_new0 (MonoMethodInflated, 1);
1066 iresult->context = *context;
1067 iresult->declaring = method;
1068 iresult->method.method.is_mb_open = is_mb_open;
1070 if (!context->method_inst && method->is_generic)
1071 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1073 if (!context->class_inst) {
1074 g_assert (!iresult->declaring->klass->generic_class);
1075 if (iresult->declaring->klass->generic_container)
1076 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1077 else if (iresult->declaring->klass->generic_class)
1078 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1081 cached = mono_method_inflated_lookup (iresult, FALSE);
1084 return (MonoMethod*)cached;
1087 mono_stats.inflated_method_count++;
1089 inflated_methods_size += sizeof (MonoMethodInflated);
1091 sig = mono_method_signature (method);
1093 char *name = mono_type_get_full_name (method->klass);
1094 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1100 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1102 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1105 result = (MonoMethod *) iresult;
1106 result->is_inflated = TRUE;
1107 result->is_generic = FALSE;
1108 result->sre_method = FALSE;
1109 result->signature = NULL;
1110 result->is_mb_open = is_mb_open;
1112 if (!context->method_inst) {
1113 /* Set the generic_container of the result to the generic_container of method */
1114 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1116 if (generic_container) {
1117 result->is_generic = 1;
1118 mono_method_set_generic_container (result, generic_container);
1122 if (!klass_hint || !klass_hint->generic_class ||
1123 klass_hint->generic_class->container_class != method->klass ||
1124 klass_hint->generic_class->context.class_inst != context->class_inst)
1127 if (method->klass->generic_container)
1128 result->klass = klass_hint;
1130 if (!result->klass) {
1131 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1132 if (!mono_error_ok (error))
1135 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1137 mono_metadata_free_type (inflated);
1141 * FIXME: This should hold, but it doesn't:
1143 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1144 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1145 * g_assert (result->is_generic);
1148 * Fixing this here causes other things to break, hence a very
1149 * ugly hack in mini-trampolines.c - see
1150 * is_generic_method_definition().
1153 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1161 * mono_get_inflated_method:
1163 * Obsolete. We keep it around since it's mentioned in the public API.
1166 mono_get_inflated_method (MonoMethod *method)
1172 * mono_method_get_context_general:
1174 * @uninflated: handle uninflated methods?
1176 * Returns the generic context of a method or NULL if it doesn't have
1177 * one. For an inflated method that's the context stored in the
1178 * method. Otherwise it's in the method's generic container or in the
1179 * generic container of the method's class.
1182 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1184 if (method->is_inflated) {
1185 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1186 return &imethod->context;
1190 if (method->is_generic)
1191 return &(mono_method_get_generic_container (method)->context);
1192 if (method->klass->generic_container)
1193 return &method->klass->generic_container->context;
1198 * mono_method_get_context:
1201 * Returns the generic context for method if it's inflated, otherwise
1205 mono_method_get_context (MonoMethod *method)
1207 return mono_method_get_context_general (method, FALSE);
1211 * mono_method_get_generic_container:
1213 * Returns the generic container of METHOD, which should be a generic method definition.
1214 * Returns NULL if METHOD is not a generic method definition.
1215 * LOCKING: Acquires the loader lock.
1217 MonoGenericContainer*
1218 mono_method_get_generic_container (MonoMethod *method)
1220 MonoGenericContainer *container;
1222 if (!method->is_generic)
1225 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1226 g_assert (container);
1232 * mono_method_set_generic_container:
1234 * Sets the generic container of METHOD to CONTAINER.
1235 * LOCKING: Acquires the image lock.
1238 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1240 g_assert (method->is_generic);
1242 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1246 * mono_class_find_enum_basetype:
1247 * @class: The enum class
1249 * Determine the basetype of an enum by iterating through its fields. We do this
1250 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1253 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1255 MonoGenericContainer *container = NULL;
1256 MonoImage *m = class->image;
1257 const int top = class->field.count;
1260 g_assert (class->enumtype);
1262 mono_error_init (error);
1264 if (class->generic_container)
1265 container = class->generic_container;
1266 else if (class->generic_class) {
1267 MonoClass *gklass = class->generic_class->container_class;
1269 container = gklass->generic_container;
1270 g_assert (container);
1274 * Fetch all the field information.
1276 for (i = 0; i < top; i++){
1278 guint32 cols [MONO_FIELD_SIZE];
1279 int idx = class->field.first + i;
1282 /* class->field.first and idx points into the fieldptr table */
1283 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1285 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1288 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1289 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1293 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1294 mono_metadata_decode_value (sig, &sig);
1295 /* FIELD signature == 0x06 */
1297 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1301 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1303 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1304 mono_error_set_from_loader_error (error);
1306 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1309 if (class->generic_class) {
1310 //FIXME do we leak here?
1311 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1312 if (!mono_error_ok (error))
1314 ftype->attrs = cols [MONO_FIELD_FLAGS];
1319 mono_error_set_type_load_class (error, class, "Could not find base type");
1322 g_assert (!mono_loader_get_last_error ());
1327 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1330 mono_type_has_exceptions (MonoType *type)
1332 switch (type->type) {
1333 case MONO_TYPE_CLASS:
1334 case MONO_TYPE_VALUETYPE:
1335 case MONO_TYPE_SZARRAY:
1336 return type->data.klass->exception_type;
1337 case MONO_TYPE_ARRAY:
1338 return type->data.array->eklass->exception_type;
1339 case MONO_TYPE_GENERICINST:
1340 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1348 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1352 mono_class_alloc (MonoClass *class, int size)
1354 if (class->generic_class)
1355 return mono_image_set_alloc (class->generic_class->owner, size);
1357 return mono_image_alloc (class->image, size);
1361 mono_class_alloc0 (MonoClass *class, int size)
1365 res = mono_class_alloc (class, size);
1366 memset (res, 0, size);
1370 #define mono_class_new0(class,struct_type, n_structs) \
1371 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1374 * mono_class_setup_basic_field_info:
1375 * @class: The class to initialize
1377 * Initializes the class->fields.
1378 * LOCKING: Assumes the loader lock is held.
1381 mono_class_setup_basic_field_info (MonoClass *class)
1383 MonoClassField *field;
1391 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1392 image = class->image;
1393 top = class->field.count;
1395 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1397 * This happens when a generic instance of an unfinished generic typebuilder
1398 * is used as an element type for creating an array type. We can't initialize
1399 * the fields of this class using the fields of gklass, since gklass is not
1400 * finished yet, fields could be added to it later.
1406 mono_class_setup_basic_field_info (gtd);
1408 top = gtd->field.count;
1409 class->field.first = gtd->field.first;
1410 class->field.count = gtd->field.count;
1413 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1416 * Fetch all the field information.
1418 for (i = 0; i < top; i++){
1419 field = &class->fields [i];
1420 field->parent = class;
1423 field->name = mono_field_get_name (>d->fields [i]);
1425 int idx = class->field.first + i;
1426 /* class->field.first and idx points into the fieldptr table */
1427 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1428 /* The name is needed for fieldrefs */
1429 field->name = mono_metadata_string_heap (image, name_idx);
1435 * mono_class_setup_fields:
1436 * @class: The class to initialize
1438 * Initializes the class->fields.
1439 * LOCKING: Assumes the loader lock is held.
1442 mono_class_setup_fields (MonoClass *class)
1445 MonoImage *m = class->image;
1447 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1448 int i, blittable = TRUE;
1449 guint32 real_size = 0;
1450 guint32 packing_size = 0;
1451 gboolean explicit_size;
1452 MonoClassField *field;
1453 MonoGenericContainer *container = NULL;
1454 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1457 * FIXME: We have a race condition here. It's possible that this function returns
1458 * to its caller with `instance_size` set to `0` instead of the actual size. This
1459 * is not a problem when the function is called recursively on the same class,
1460 * because the size will be initialized by the outer invocation. What follows is a
1461 * description of how it can occur in other cases, too. There it is a problem,
1462 * because it can lead to the GC being asked to allocate an object of size `0`,
1463 * which SGen chokes on. The race condition is triggered infrequently by
1464 * `tests/sgen-suspend.cs`.
1466 * This function is called for a class whenever one of its subclasses is inited.
1467 * For example, it's called for every subclass of Object. What it does is this:
1469 * if (class->setup_fields_called)
1472 * class->instance_size = 0;
1474 * class->setup_fields_called = 1;
1475 * ... critical point
1476 * class->instance_size = actual_instance_size;
1478 * The last two steps are sometimes reversed, but that only changes the way in which
1479 * the race condition works.
1481 * Assume thread A goes through this function and makes it to the critical point.
1482 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1483 * immediately, but `instance_size` is incorrect.
1485 * The other case looks like this:
1487 * if (class->setup_fields_called)
1489 * ... critical point X
1490 * class->instance_size = 0;
1491 * ... critical point Y
1492 * class->instance_size = actual_instance_size;
1494 * class->setup_fields_called = 1;
1496 * Assume thread A goes through the function and makes it to critical point X. Now
1497 * thread B runs through the whole of the function, returning, assuming
1498 * `instance_size` is set. At that point thread A gets to run and makes it to
1499 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1502 if (class->setup_fields_called)
1505 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1507 * This happens when a generic instance of an unfinished generic typebuilder
1508 * is used as an element type for creating an array type. We can't initialize
1509 * the fields of this class using the fields of gklass, since gklass is not
1510 * finished yet, fields could be added to it later.
1515 mono_class_setup_basic_field_info (class);
1516 top = class->field.count;
1519 mono_class_setup_fields (gtd);
1520 if (gtd->exception_type) {
1521 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1526 class->instance_size = 0;
1528 class->sizes.class_size = 0;
1530 if (class->parent) {
1531 /* For generic instances, class->parent might not have been initialized */
1532 mono_class_init (class->parent);
1533 if (!class->parent->size_inited) {
1534 mono_class_setup_fields (class->parent);
1535 if (class->parent->exception_type) {
1536 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1540 class->instance_size += class->parent->instance_size;
1541 class->min_align = class->parent->min_align;
1542 /* we use |= since it may have been set already */
1543 class->has_references |= class->parent->has_references;
1544 blittable = class->parent->blittable;
1546 class->instance_size = sizeof (MonoObject);
1547 class->min_align = 1;
1550 /* We can't really enable 16 bytes alignment until the GC supports it.
1551 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1552 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1553 Bug #506144 is an example of this issue.
1555 if (class->simd_type)
1556 class->min_align = 16;
1558 /* Get the real size */
1559 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1561 if (explicit_size) {
1562 if ((packing_size & 0xfffffff0) != 0) {
1563 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1564 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1567 class->packing_size = packing_size;
1568 real_size += class->instance_size;
1572 if (explicit_size && real_size) {
1573 class->instance_size = MAX (real_size, class->instance_size);
1575 class->blittable = blittable;
1576 mono_memory_barrier ();
1577 class->size_inited = 1;
1578 class->fields_inited = 1;
1579 class->setup_fields_called = 1;
1583 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1586 /* Prevent infinite loops if the class references itself */
1587 class->setup_fields_called = 1;
1589 if (class->generic_container) {
1590 container = class->generic_container;
1592 container = gtd->generic_container;
1593 g_assert (container);
1597 * Fetch all the field information.
1599 for (i = 0; i < top; i++){
1600 int idx = class->field.first + i;
1601 field = &class->fields [i];
1603 field->parent = class;
1606 mono_field_resolve_type (field, &error);
1607 if (!mono_error_ok (&error)) {
1608 /*mono_field_resolve_type already failed class*/
1609 mono_error_cleanup (&error);
1613 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1614 g_assert (field->type);
1617 if (mono_field_is_deleted (field))
1620 MonoClassField *gfield = >d->fields [i];
1621 field->offset = gfield->offset;
1623 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1625 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1626 field->offset = offset;
1628 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1629 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1632 if (field->offset < -1) { /*-1 is used to encode special static fields */
1633 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1636 if (class->generic_container) {
1637 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1643 /* Only do these checks if we still think this type is blittable */
1644 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1645 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1648 MonoClass *field_class = mono_class_from_mono_type (field->type);
1650 mono_class_setup_fields (field_class);
1651 if (field_class->exception_type) {
1652 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1656 if (!field_class || !field_class->blittable)
1661 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1662 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1663 blittable = class->element_class->blittable;
1666 if (mono_type_has_exceptions (field->type)) {
1667 char *class_name = mono_type_get_full_name (class);
1668 char *type_name = mono_type_full_name (field->type);
1670 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1671 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1672 g_free (class_name);
1676 /* The def_value of fields is compute lazily during vtable creation */
1679 if (class == mono_defaults.string_class)
1682 class->blittable = blittable;
1684 if (class->enumtype && !mono_class_enum_basetype (class)) {
1685 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1688 if (explicit_size && real_size) {
1689 class->instance_size = MAX (real_size, class->instance_size);
1692 if (class->exception_type)
1694 mono_class_layout_fields (class);
1696 /*valuetypes can't be neither bigger than 1Mb or empty. */
1697 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1698 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1700 mono_memory_barrier ();
1701 class->fields_inited = 1;
1705 * mono_class_setup_fields_locking:
1706 * @class: The class to initialize
1708 * Initializes the class->fields array of fields.
1709 * Aquires the loader lock.
1712 mono_class_setup_fields_locking (MonoClass *class)
1714 /* This can be checked without locks */
1715 if (class->fields_inited)
1717 mono_loader_lock ();
1718 mono_class_setup_fields (class);
1719 mono_loader_unlock ();
1723 * mono_class_has_references:
1725 * Returns whenever @klass->has_references is set, initializing it if needed.
1726 * Aquires the loader lock.
1729 mono_class_has_references (MonoClass *klass)
1731 if (klass->init_pending) {
1732 /* Be conservative */
1735 mono_class_init (klass);
1737 return klass->has_references;
1742 * mono_type_get_basic_type_from_generic:
1745 * Returns a closed type corresponding to the possibly open type
1749 mono_type_get_basic_type_from_generic (MonoType *type)
1751 /* When we do generic sharing we let type variables stand for reference types. */
1752 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1753 return &mono_defaults.object_class->byval_arg;
1758 * mono_class_layout_fields:
1761 * Compute the placement of fields inside an object or struct, according to
1762 * the layout rules and set the following fields in @class:
1763 * - has_references (if the class contains instance references firled or structs that contain references)
1764 * - has_static_refs (same, but for static fields)
1765 * - instance_size (size of the object in memory)
1766 * - class_size (size needed for the static fields)
1767 * - size_inited (flag set when the instance_size is set)
1769 * LOCKING: this is supposed to be called with the loader lock held.
1772 mono_class_layout_fields (MonoClass *class)
1775 const int top = class->field.count;
1776 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1777 guint32 pass, passes, real_size;
1778 gboolean gc_aware_layout = FALSE;
1779 gboolean has_static_fields = FALSE;
1780 MonoClassField *field;
1783 * When we do generic sharing we need to have layout
1784 * information for open generic classes (either with a generic
1785 * context containing type variables or with a generic
1786 * container), so we don't return in that case anymore.
1790 * Enable GC aware auto layout: in this mode, reference
1791 * fields are grouped together inside objects, increasing collector
1793 * Requires that all classes whose layout is known to native code be annotated
1794 * with [StructLayout (LayoutKind.Sequential)]
1795 * Value types have gc_aware_layout disabled by default, as per
1796 * what the default is for other runtimes.
1798 /* corlib is missing [StructLayout] directives in many places */
1799 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1800 if (!class->valuetype)
1801 gc_aware_layout = TRUE;
1804 /* Compute klass->has_references */
1806 * Process non-static fields first, since static fields might recursively
1807 * refer to the class itself.
1809 for (i = 0; i < top; i++) {
1812 field = &class->fields [i];
1814 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1815 ftype = mono_type_get_underlying_type (field->type);
1816 ftype = mono_type_get_basic_type_from_generic (ftype);
1817 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1818 class->has_references = TRUE;
1822 for (i = 0; i < top; i++) {
1825 field = &class->fields [i];
1827 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1828 ftype = mono_type_get_underlying_type (field->type);
1829 ftype = mono_type_get_basic_type_from_generic (ftype);
1830 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1831 class->has_static_refs = TRUE;
1835 for (i = 0; i < top; i++) {
1838 field = &class->fields [i];
1840 ftype = mono_type_get_underlying_type (field->type);
1841 ftype = mono_type_get_basic_type_from_generic (ftype);
1842 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1843 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1844 class->has_static_refs = TRUE;
1846 class->has_references = TRUE;
1851 * Compute field layout and total size (not considering static fields)
1855 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1856 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1858 if (gc_aware_layout)
1863 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1866 if (class->parent) {
1867 mono_class_setup_fields (class->parent);
1868 if (class->parent->exception_type) {
1869 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1872 real_size = class->parent->instance_size;
1874 real_size = sizeof (MonoObject);
1877 for (pass = 0; pass < passes; ++pass) {
1878 for (i = 0; i < top; i++){
1883 field = &class->fields [i];
1885 if (mono_field_is_deleted (field))
1887 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1890 ftype = mono_type_get_underlying_type (field->type);
1891 ftype = mono_type_get_basic_type_from_generic (ftype);
1892 if (gc_aware_layout) {
1893 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1902 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1903 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1904 /* This field is a hack inserted by MCS to empty structures */
1908 size = mono_type_size (field->type, &align);
1910 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1911 align = class->packing_size ? MIN (class->packing_size, align): align;
1912 /* if the field has managed references, we need to force-align it
1915 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1916 align = MAX (align, sizeof (gpointer));
1918 class->min_align = MAX (align, class->min_align);
1919 field->offset = real_size;
1921 field->offset += align - 1;
1922 field->offset &= ~(align - 1);
1924 /*TypeBuilders produce all sort of weird things*/
1925 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1926 real_size = field->offset + size;
1929 class->instance_size = MAX (real_size, class->instance_size);
1931 if (class->instance_size & (class->min_align - 1)) {
1932 class->instance_size += class->min_align - 1;
1933 class->instance_size &= ~(class->min_align - 1);
1937 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1941 for (i = 0; i < top; i++) {
1946 field = &class->fields [i];
1949 * There must be info about all the fields in a type if it
1950 * uses explicit layout.
1952 if (mono_field_is_deleted (field))
1954 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1957 size = mono_type_size (field->type, &align);
1958 align = class->packing_size ? MIN (class->packing_size, align): align;
1959 class->min_align = MAX (align, class->min_align);
1962 * When we get here, field->offset is already set by the
1963 * loader (for either runtime fields or fields loaded from metadata).
1964 * The offset is from the start of the object: this works for both
1965 * classes and valuetypes.
1967 field->offset += sizeof (MonoObject);
1968 ftype = mono_type_get_underlying_type (field->type);
1969 ftype = mono_type_get_basic_type_from_generic (ftype);
1970 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1971 if (field->offset % sizeof (gpointer)) {
1972 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1979 real_size = MAX (real_size, size + field->offset);
1982 if (class->has_references) {
1983 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
1985 /* Check for overlapping reference and non-reference fields */
1986 for (i = 0; i < top; i++) {
1989 field = &class->fields [i];
1991 if (mono_field_is_deleted (field))
1993 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1995 ftype = mono_type_get_underlying_type (field->type);
1996 if (MONO_TYPE_IS_REFERENCE (ftype))
1997 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
1999 for (i = 0; i < top; i++) {
2000 field = &class->fields [i];
2002 if (mono_field_is_deleted (field))
2004 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2007 // FIXME: Too much code does this
2009 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2010 char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
2011 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2015 g_free (ref_bitmap);
2018 class->instance_size = MAX (real_size, class->instance_size);
2019 if (class->instance_size & (class->min_align - 1)) {
2020 class->instance_size += class->min_align - 1;
2021 class->instance_size &= ~(class->min_align - 1);
2027 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2029 * For small structs, set min_align to at least the struct size to improve
2030 * performance, and since the JIT memset/memcpy code assumes this and generates
2031 * unaligned accesses otherwise. See #78990 for a testcase.
2033 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2034 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2037 mono_memory_barrier ();
2038 class->size_inited = 1;
2041 * Compute static field layout and size
2043 for (i = 0; i < top; i++){
2047 field = &class->fields [i];
2049 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2051 if (mono_field_is_deleted (field))
2054 if (mono_type_has_exceptions (field->type)) {
2055 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2059 has_static_fields = TRUE;
2061 size = mono_type_size (field->type, &align);
2062 field->offset = class->sizes.class_size;
2063 /*align is always non-zero here*/
2064 field->offset += align - 1;
2065 field->offset &= ~(align - 1);
2066 class->sizes.class_size = field->offset + size;
2069 if (has_static_fields && class->sizes.class_size == 0)
2070 /* Simplify code which depends on class_size != 0 if the class has static fields */
2071 class->sizes.class_size = 8;
2075 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2079 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2080 method->klass = class;
2081 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2082 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2083 method->signature = sig;
2084 method->name = name;
2087 if (name [0] == '.') {
2088 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2090 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2096 * mono_class_setup_methods:
2099 * Initializes the 'methods' array in CLASS.
2100 * Calling this method should be avoided if possible since it allocates a lot
2101 * of long-living MonoMethod structures.
2102 * Methods belonging to an interface are assigned a sequential slot starting
2105 * On failure this function sets class->exception_type
2108 mono_class_setup_methods (MonoClass *class)
2111 MonoMethod **methods;
2116 if (class->generic_class) {
2118 MonoClass *gklass = class->generic_class->container_class;
2120 mono_class_init (gklass);
2121 if (!gklass->exception_type)
2122 mono_class_setup_methods (gklass);
2123 if (gklass->exception_type) {
2124 /* FIXME make exception_data less opaque so it's possible to dup it here */
2125 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2129 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2130 count = gklass->method.count;
2131 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2133 for (i = 0; i < count; i++) {
2134 methods [i] = mono_class_inflate_generic_method_full_checked (
2135 gklass->methods [i], class, mono_class_get_context (class), &error);
2136 if (!mono_error_ok (&error)) {
2137 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2138 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)));
2141 mono_error_cleanup (&error);
2145 } else if (class->rank) {
2147 MonoMethod *amethod;
2148 MonoMethodSignature *sig;
2149 int count_generic = 0, first_generic = 0;
2152 count = 3 + (class->rank > 1? 2: 1);
2154 mono_class_setup_interfaces (class, &error);
2155 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2157 if (class->interface_count) {
2158 count_generic = generic_array_methods (class);
2159 first_generic = count;
2160 count += class->interface_count * count_generic;
2163 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2165 sig = mono_metadata_signature_alloc (class->image, class->rank);
2166 sig->ret = &mono_defaults.void_class->byval_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;
2172 amethod = create_array_method (class, ".ctor", sig);
2173 methods [method_num++] = amethod;
2174 if (class->rank > 1) {
2175 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2176 sig->ret = &mono_defaults.void_class->byval_arg;
2177 sig->pinvoke = TRUE;
2178 sig->hasthis = TRUE;
2179 for (i = 0; i < class->rank * 2; ++i)
2180 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2182 amethod = create_array_method (class, ".ctor", sig);
2183 methods [method_num++] = amethod;
2185 /* element Get (idx11, [idx2, ...]) */
2186 sig = mono_metadata_signature_alloc (class->image, class->rank);
2187 sig->ret = &class->element_class->byval_arg;
2188 sig->pinvoke = TRUE;
2189 sig->hasthis = TRUE;
2190 for (i = 0; i < class->rank; ++i)
2191 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2192 amethod = create_array_method (class, "Get", sig);
2193 methods [method_num++] = amethod;
2194 /* element& Address (idx11, [idx2, ...]) */
2195 sig = mono_metadata_signature_alloc (class->image, class->rank);
2196 sig->ret = &class->element_class->this_arg;
2197 sig->pinvoke = TRUE;
2198 sig->hasthis = TRUE;
2199 for (i = 0; i < class->rank; ++i)
2200 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2201 amethod = create_array_method (class, "Address", sig);
2202 methods [method_num++] = amethod;
2203 /* void Set (idx11, [idx2, ...], element) */
2204 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2205 sig->ret = &mono_defaults.void_class->byval_arg;
2206 sig->pinvoke = TRUE;
2207 sig->hasthis = TRUE;
2208 for (i = 0; i < class->rank; ++i)
2209 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2210 sig->params [i] = &class->element_class->byval_arg;
2211 amethod = create_array_method (class, "Set", sig);
2212 methods [method_num++] = amethod;
2214 for (i = 0; i < class->interface_count; i++)
2215 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2217 count = class->method.count;
2218 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2219 for (i = 0; i < count; ++i) {
2220 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2221 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2225 if (MONO_CLASS_IS_INTERFACE (class)) {
2227 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2228 for (i = 0; i < count; ++i) {
2229 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2230 methods [i]->slot = slot++;
2234 mono_image_lock (class->image);
2236 if (!class->methods) {
2237 class->method.count = count;
2239 /* Needed because of the double-checking locking pattern */
2240 mono_memory_barrier ();
2242 class->methods = methods;
2245 mono_image_unlock (class->image);
2249 * mono_class_get_method_by_index:
2251 * Returns class->methods [index], initializing class->methods if neccesary.
2253 * LOCKING: Acquires the loader lock.
2256 mono_class_get_method_by_index (MonoClass *class, int index)
2258 /* Avoid calling setup_methods () if possible */
2259 if (class->generic_class && !class->methods) {
2260 MonoClass *gklass = class->generic_class->container_class;
2263 m = mono_class_inflate_generic_method_full (
2264 gklass->methods [index], class, mono_class_get_context (class));
2266 * If setup_methods () is called later for this class, no duplicates are created,
2267 * since inflate_generic_method guarantees that only one instance of a method
2268 * is created for each context.
2271 mono_class_setup_methods (class);
2272 g_assert (m == class->methods [index]);
2276 mono_class_setup_methods (class);
2277 if (class->exception_type) /*FIXME do proper error handling*/
2279 g_assert (index >= 0 && index < class->method.count);
2280 return class->methods [index];
2285 * mono_class_get_inflated_method:
2287 * Given an inflated class CLASS and a method METHOD which should be a method of
2288 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2291 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2293 MonoClass *gklass = class->generic_class->container_class;
2296 g_assert (method->klass == gklass);
2298 mono_class_setup_methods (gklass);
2299 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2301 for (i = 0; i < gklass->method.count; ++i) {
2302 if (gklass->methods [i] == method) {
2304 return class->methods [i];
2306 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2314 * mono_class_get_vtable_entry:
2316 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2317 * LOCKING: Acquires the loader lock.
2320 mono_class_get_vtable_entry (MonoClass *class, int offset)
2324 if (class->rank == 1) {
2326 * szarrays do not overwrite any methods of Array, so we can avoid
2327 * initializing their vtables in some cases.
2329 mono_class_setup_vtable (class->parent);
2330 if (offset < class->parent->vtable_size)
2331 return class->parent->vtable [offset];
2334 if (class->generic_class) {
2335 MonoClass *gklass = class->generic_class->container_class;
2336 mono_class_setup_vtable (gklass);
2337 m = gklass->vtable [offset];
2339 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2341 mono_class_setup_vtable (class);
2342 if (class->exception_type)
2344 m = class->vtable [offset];
2351 * mono_class_get_vtable_size:
2353 * Return the vtable size for KLASS.
2356 mono_class_get_vtable_size (MonoClass *klass)
2358 mono_class_setup_vtable (klass);
2360 return klass->vtable_size;
2364 * mono_class_setup_properties:
2366 * Initialize class->ext.property and class->ext.properties.
2368 * This method can fail the class.
2371 mono_class_setup_properties (MonoClass *class)
2373 guint startm, endm, i, j;
2374 guint32 cols [MONO_PROPERTY_SIZE];
2375 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2376 MonoProperty *properties;
2380 if (class->ext && class->ext->properties)
2383 if (class->generic_class) {
2384 MonoClass *gklass = class->generic_class->container_class;
2386 mono_class_init (gklass);
2387 mono_class_setup_properties (gklass);
2388 if (gklass->exception_type) {
2389 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2393 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2395 for (i = 0; i < gklass->ext->property.count; i++) {
2396 MonoProperty *prop = &properties [i];
2398 *prop = gklass->ext->properties [i];
2401 prop->get = mono_class_inflate_generic_method_full (
2402 prop->get, class, mono_class_get_context (class));
2404 prop->set = mono_class_inflate_generic_method_full (
2405 prop->set, class, mono_class_get_context (class));
2407 prop->parent = class;
2410 first = gklass->ext->property.first;
2411 count = gklass->ext->property.count;
2413 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2414 count = last - first;
2417 mono_class_setup_methods (class);
2418 if (class->exception_type)
2422 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2423 for (i = first; i < last; ++i) {
2424 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2425 properties [i - first].parent = class;
2426 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2427 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2429 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2430 for (j = startm; j < endm; ++j) {
2433 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2435 if (class->image->uncompressed_metadata)
2436 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2437 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2439 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2441 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2442 case METHOD_SEMANTIC_SETTER:
2443 properties [i - first].set = method;
2445 case METHOD_SEMANTIC_GETTER:
2446 properties [i - first].get = method;
2455 mono_class_alloc_ext (class);
2457 mono_image_lock (class->image);
2459 if (class->ext->properties) {
2460 /* We leak 'properties' which was allocated from the image mempool */
2461 mono_image_unlock (class->image);
2465 class->ext->property.first = first;
2466 class->ext->property.count = count;
2468 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2469 mono_memory_barrier ();
2471 /* Leave this assignment as the last op in the function */
2472 class->ext->properties = properties;
2474 mono_image_unlock (class->image);
2478 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2480 MonoMethod **om, **retval;
2483 for (om = methods, count = 0; *om; ++om, ++count)
2486 retval = g_new0 (MonoMethod*, count + 1);
2488 for (om = methods, count = 0; *om; ++om, ++count)
2489 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2494 /*This method can fail the class.*/
2496 mono_class_setup_events (MonoClass *class)
2499 guint startm, endm, i, j;
2500 guint32 cols [MONO_EVENT_SIZE];
2501 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2505 if (class->ext && class->ext->events)
2508 if (class->generic_class) {
2509 MonoClass *gklass = class->generic_class->container_class;
2510 MonoGenericContext *context = NULL;
2512 mono_class_setup_events (gklass);
2513 if (gklass->exception_type) {
2514 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2518 first = gklass->ext->event.first;
2519 count = gklass->ext->event.count;
2521 events = mono_class_new0 (class, MonoEvent, count);
2524 context = mono_class_get_context (class);
2526 for (i = 0; i < count; i++) {
2527 MonoEvent *event = &events [i];
2528 MonoEvent *gevent = &gklass->ext->events [i];
2530 event->parent = class;
2531 event->name = gevent->name;
2532 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2533 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2534 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2535 #ifndef MONO_SMALL_CONFIG
2536 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2538 event->attrs = gevent->attrs;
2541 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2542 count = last - first;
2545 mono_class_setup_methods (class);
2546 if (class->exception_type) {
2547 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2552 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2553 for (i = first; i < last; ++i) {
2554 MonoEvent *event = &events [i - first];
2556 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2557 event->parent = class;
2558 event->attrs = cols [MONO_EVENT_FLAGS];
2559 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2561 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2562 for (j = startm; j < endm; ++j) {
2565 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2567 if (class->image->uncompressed_metadata)
2568 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2569 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2571 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2573 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2574 case METHOD_SEMANTIC_ADD_ON:
2575 event->add = method;
2577 case METHOD_SEMANTIC_REMOVE_ON:
2578 event->remove = method;
2580 case METHOD_SEMANTIC_FIRE:
2581 event->raise = method;
2583 case METHOD_SEMANTIC_OTHER: {
2584 #ifndef MONO_SMALL_CONFIG
2587 if (event->other == NULL) {
2588 event->other = g_new0 (MonoMethod*, 2);
2590 while (event->other [n])
2592 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2594 event->other [n] = method;
2595 /* NULL terminated */
2596 event->other [n + 1] = NULL;
2607 mono_class_alloc_ext (class);
2609 mono_image_lock (class->image);
2611 if (class->ext->events) {
2612 mono_image_unlock (class->image);
2616 class->ext->event.first = first;
2617 class->ext->event.count = count;
2619 /* Flush any pending writes as we do double checked locking on class->ext.events */
2620 mono_memory_barrier ();
2622 /* Leave this assignment as the last op in the function */
2623 class->ext->events = events;
2625 mono_image_unlock (class->image);
2629 * Global pool of interface IDs, represented as a bitset.
2630 * LOCKING: Protected by the classes lock.
2632 static MonoBitSet *global_interface_bitset = NULL;
2635 * mono_unload_interface_ids:
2636 * @bitset: bit set of interface IDs
2638 * When an image is unloaded, the interface IDs associated with
2639 * the image are put back in the global pool of IDs so the numbers
2643 mono_unload_interface_ids (MonoBitSet *bitset)
2646 mono_bitset_sub (global_interface_bitset, bitset);
2651 mono_unload_interface_id (MonoClass *class)
2653 if (global_interface_bitset && class->interface_id) {
2655 mono_bitset_clear (global_interface_bitset, class->interface_id);
2661 * mono_get_unique_iid:
2664 * Assign a unique integer ID to the interface represented by @class.
2665 * The ID will positive and as small as possible.
2666 * LOCKING: Acquires the classes lock.
2667 * Returns: the new ID.
2670 mono_get_unique_iid (MonoClass *class)
2674 g_assert (MONO_CLASS_IS_INTERFACE (class));
2678 if (!global_interface_bitset) {
2679 global_interface_bitset = mono_bitset_new (128, 0);
2682 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2684 int old_size = mono_bitset_size (global_interface_bitset);
2685 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2686 mono_bitset_free (global_interface_bitset);
2687 global_interface_bitset = new_set;
2690 mono_bitset_set (global_interface_bitset, iid);
2691 /* set the bit also in the per-image set */
2692 if (!class->generic_class) {
2693 if (class->image->interface_bitset) {
2694 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2695 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2696 mono_bitset_free (class->image->interface_bitset);
2697 class->image->interface_bitset = new_set;
2700 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2702 mono_bitset_set (class->image->interface_bitset, iid);
2707 #ifndef MONO_SMALL_CONFIG
2708 if (mono_print_vtable) {
2710 char *type_name = mono_type_full_name (&class->byval_arg);
2711 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2712 generic_id = class->generic_class->context.class_inst->id;
2713 g_assert (generic_id != 0);
2717 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2722 g_assert (iid <= 65535);
2727 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2732 mono_class_setup_interfaces (klass, error);
2733 if (!mono_error_ok (error))
2736 for (i = 0; i < klass->interface_count; i++) {
2737 ic = klass->interfaces [i];
2740 *res = g_ptr_array_new ();
2741 g_ptr_array_add (*res, ic);
2742 mono_class_init (ic);
2743 if (ic->exception_type) {
2744 mono_error_set_type_load_class (error, ic, "Error Loading class");
2748 collect_implemented_interfaces_aux (ic, res, error);
2749 if (!mono_error_ok (error))
2755 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2757 GPtrArray *res = NULL;
2759 collect_implemented_interfaces_aux (klass, &res, error);
2760 if (!mono_error_ok (error)) {
2762 g_ptr_array_free (res, TRUE);
2769 compare_interface_ids (const void *p_key, const void *p_element) {
2770 const MonoClass *key = p_key;
2771 const MonoClass *element = *(MonoClass**) p_element;
2773 return (key->interface_id - element->interface_id);
2776 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2778 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2779 MonoClass **result = mono_binary_search (
2781 klass->interfaces_packed,
2782 klass->interface_offsets_count,
2783 sizeof (MonoClass *),
2784 compare_interface_ids);
2786 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2793 * mono_class_interface_offset_with_variance:
2795 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2796 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2798 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2800 * FIXME figure out MS disambiguation rules and fix this function.
2803 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2804 int i = mono_class_interface_offset (klass, itf);
2805 *non_exact_match = FALSE;
2809 if (!mono_class_has_variant_generic_params (itf))
2812 for (i = 0; i < klass->interface_offsets_count; i++) {
2813 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2814 *non_exact_match = TRUE;
2815 return klass->interface_offsets_packed [i];
2823 print_implemented_interfaces (MonoClass *klass) {
2826 GPtrArray *ifaces = NULL;
2828 int ancestor_level = 0;
2830 name = mono_type_get_full_name (klass);
2831 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2834 for (i = 0; i < klass->interface_offsets_count; i++)
2835 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2836 klass->interfaces_packed [i]->interface_id,
2837 klass->interface_offsets_packed [i],
2838 klass->interfaces_packed [i]->method.count,
2839 klass->interfaces_packed [i]->name_space,
2840 klass->interfaces_packed [i]->name );
2841 printf ("Interface flags: ");
2842 for (i = 0; i <= klass->max_interface_id; i++)
2843 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2844 printf ("(%d,T)", i);
2846 printf ("(%d,F)", i);
2848 printf ("Dump interface flags:");
2849 #ifdef COMPRESSED_INTERFACE_BITMAP
2851 const uint8_t* p = klass->interface_bitmap;
2852 i = klass->max_interface_id;
2854 printf (" %d x 00 %02X", p [0], p [1]);
2860 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2861 printf (" %02X", klass->interface_bitmap [i]);
2864 while (klass != NULL) {
2865 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2866 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2867 if (!mono_error_ok (&error)) {
2868 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2869 mono_error_cleanup (&error);
2870 } else if (ifaces) {
2871 for (i = 0; i < ifaces->len; i++) {
2872 MonoClass *ic = g_ptr_array_index (ifaces, i);
2873 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2874 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2876 mono_class_interface_offset (klass, ic),
2881 g_ptr_array_free (ifaces, TRUE);
2884 klass = klass->parent;
2889 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2892 args [0] = &arg0->byval_arg;
2894 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2898 array_class_get_if_rank (MonoClass *class, guint rank)
2900 return rank ? mono_array_class_get (class, rank) : class;
2904 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2906 valuetype_types [0] = eclass;
2907 if (eclass == mono_defaults.int16_class)
2908 valuetype_types [1] = mono_defaults.uint16_class;
2909 else if (eclass == mono_defaults.uint16_class)
2910 valuetype_types [1] = mono_defaults.int16_class;
2911 else if (eclass == mono_defaults.int32_class)
2912 valuetype_types [1] = mono_defaults.uint32_class;
2913 else if (eclass == mono_defaults.uint32_class)
2914 valuetype_types [1] = mono_defaults.int32_class;
2915 else if (eclass == mono_defaults.int64_class)
2916 valuetype_types [1] = mono_defaults.uint64_class;
2917 else if (eclass == mono_defaults.uint64_class)
2918 valuetype_types [1] = mono_defaults.int64_class;
2919 else if (eclass == mono_defaults.byte_class)
2920 valuetype_types [1] = mono_defaults.sbyte_class;
2921 else if (eclass == mono_defaults.sbyte_class)
2922 valuetype_types [1] = mono_defaults.byte_class;
2923 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2924 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2927 /* this won't be needed once bug #325495 is completely fixed
2928 * though we'll need something similar to know which interfaces to allow
2929 * in arrays when they'll be lazyly created
2931 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2932 * MS returns diferrent types based on which instance is called. For example:
2933 * object obj = new byte[10][];
2934 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2935 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2938 * Fixing this should kill quite some code, save some bits and improve compatibility.
2941 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2943 MonoClass *eclass = class->element_class;
2944 static MonoClass* generic_icollection_class = NULL;
2945 static MonoClass* generic_ienumerable_class = NULL;
2946 static MonoClass* generic_ienumerator_class = NULL;
2947 static MonoClass* generic_ireadonlylist_class = NULL;
2948 static MonoClass* generic_ireadonlycollection_class = NULL;
2949 MonoClass *valuetype_types[2] = { NULL, NULL };
2950 MonoClass **interfaces = NULL;
2951 int i, nifaces, interface_count, real_count, original_rank;
2953 gboolean internal_enumerator;
2954 gboolean eclass_is_valuetype;
2956 if (!mono_defaults.generic_ilist_class) {
2960 internal_enumerator = FALSE;
2961 eclass_is_valuetype = FALSE;
2962 original_rank = eclass->rank;
2963 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2964 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2966 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2968 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2969 original_rank = eclass->rank;
2971 eclass = eclass->element_class;
2972 internal_enumerator = TRUE;
2973 *is_enumerator = TRUE;
2981 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2982 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2984 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2986 if (!generic_icollection_class) {
2987 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2988 "System.Collections.Generic", "ICollection`1");
2989 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2990 "System.Collections.Generic", "IEnumerable`1");
2991 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2992 "System.Collections.Generic", "IEnumerator`1");
2993 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2994 "System.Collections.Generic", "IReadOnlyList`1");
2995 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2996 "System.Collections.Generic", "IReadOnlyCollection`1");
2999 mono_class_init (eclass);
3002 * Arrays in 2.0 need to implement a number of generic interfaces
3003 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3004 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3005 * We collect the types needed to build the
3006 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3007 * the generic interfaces needed to implement.
3009 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3010 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3012 if (eclass->valuetype) {
3013 nifaces = generic_ireadonlylist_class ? 5 : 3;
3014 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3016 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3017 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3018 if (internal_enumerator) {
3020 if (valuetype_types [1])
3024 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3025 interfaces [0] = valuetype_types [0];
3026 if (valuetype_types [1])
3027 interfaces [nifaces] = valuetype_types [1];
3029 eclass_is_valuetype = TRUE;
3032 int idepth = eclass->idepth;
3033 if (!internal_enumerator)
3035 nifaces = generic_ireadonlylist_class ? 2 : 3;
3037 // FIXME: This doesn't seem to work/required for generic params
3038 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3039 mono_class_setup_interface_offsets (eclass);
3041 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3042 /* we add object for interfaces and the supertypes for the other
3043 * types. The last of the supertypes is the element class itself which we
3044 * already created the explicit interfaces for (so we include it for IEnumerator
3045 * and exclude it for arrays).
3047 if (MONO_CLASS_IS_INTERFACE (eclass))
3050 interface_count += idepth;
3051 if (eclass->rank && eclass->element_class->valuetype) {
3052 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3053 if (valuetype_types [1])
3056 /* IList, ICollection, IEnumerable, IReadOnlyList */
3057 interface_count *= nifaces;
3058 real_count = interface_count;
3059 if (internal_enumerator) {
3060 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3061 if (valuetype_types [1])
3064 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3065 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3066 interfaces [0] = mono_defaults.object_class;
3070 for (i = 0; i < idepth; i++) {
3071 mono_class_init (eclass->supertypes [i]);
3072 interfaces [j] = eclass->supertypes [i];
3076 if (all_interfaces) {
3077 for (i = 0; i < eclass->interface_offsets_count; i++) {
3078 interfaces [j] = eclass->interfaces_packed [i];
3082 for (i = 0; i < eclass->interface_count; i++) {
3083 interfaces [j] = eclass->interfaces [i];
3087 if (valuetype_types [1]) {
3088 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3093 /* instantiate the generic interfaces */
3094 for (i = 0; i < interface_count; i += nifaces) {
3095 MonoClass *iface = interfaces [i];
3097 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3098 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3100 if (eclass->valuetype) {
3101 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3102 if (generic_ireadonlylist_class) {
3103 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3104 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3107 if (!generic_ireadonlylist_class)
3108 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3111 if (internal_enumerator) {
3113 /* instantiate IEnumerator<iface> */
3114 for (i = 0; i < interface_count; i++) {
3115 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3117 j = interface_count;
3118 if (!eclass_is_valuetype) {
3119 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3120 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3123 for (i = 0; i < eclass->idepth; i++) {
3124 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3128 for (i = 0; i < eclass->interface_offsets_count; i++) {
3129 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3133 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3135 if (valuetype_types [1])
3136 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3140 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3141 for (i = 0; i < real_count; ++i) {
3142 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3143 g_print ("%s implements %s\n", type_name, name);
3154 find_array_interface (MonoClass *klass, const char *name)
3157 for (i = 0; i < klass->interface_count; ++i) {
3158 if (strcmp (klass->interfaces [i]->name, name) == 0)
3165 * Return the number of virtual methods.
3166 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3167 * Return -1 on failure.
3168 * FIXME It would be nice if this information could be cached somewhere.
3171 count_virtual_methods (MonoClass *class)
3175 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3177 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3178 mono_class_setup_methods (class);
3179 if (class->exception_type)
3182 for (i = 0; i < class->method.count; ++i) {
3183 flags = class->methods [i]->flags;
3184 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3188 for (i = 0; i < class->method.count; ++i) {
3189 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3191 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3199 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3207 m = (l + num_ifaces) / 2;
3208 if (interfaces_full [m] == ic)
3210 if (l == num_ifaces)
3212 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3221 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3223 int i = find_interface (num_ifaces, interfaces_full, ic);
3225 return interface_offsets_full [i];
3230 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3232 int i = find_interface (num_ifaces, interfaces_full, ic);
3236 interface_offsets_full [i] = offset;
3239 for (i = 0; i < num_ifaces; ++i) {
3240 if (interfaces_full [i]) {
3242 if (interfaces_full [i]->interface_id < ic->interface_id)
3245 while (end < num_ifaces && interfaces_full [end]) end++;
3246 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3247 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3249 interfaces_full [i] = ic;
3250 interface_offsets_full [i] = offset;
3256 #ifdef COMPRESSED_INTERFACE_BITMAP
3259 * Compressed interface bitmap design.
3261 * Interface bitmaps take a large amount of memory, because their size is
3262 * linear with the maximum interface id assigned in the process (each interface
3263 * is assigned a unique id as it is loaded). The number of interface classes
3264 * is high because of the many implicit interfaces implemented by arrays (we'll
3265 * need to lazy-load them in the future).
3266 * Most classes implement a very small number of interfaces, so the bitmap is
3267 * sparse. This bitmap needs to be checked by interface casts, so access to the
3268 * needed bit must be fast and doable with few jit instructions.
3270 * The current compression format is as follows:
3271 * *) it is a sequence of one or more two-byte elements
3272 * *) the first byte in the element is the count of empty bitmap bytes
3273 * at the current bitmap position
3274 * *) the second byte in the element is an actual bitmap byte at the current
3277 * As an example, the following compressed bitmap bytes:
3278 * 0x07 0x01 0x00 0x7
3279 * correspond to the following bitmap:
3280 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3282 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3283 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3284 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3288 * mono_compress_bitmap:
3289 * @dest: destination buffer
3290 * @bitmap: bitmap buffer
3291 * @size: size of @bitmap in bytes
3293 * This is a mono internal function.
3294 * The @bitmap data is compressed into a format that is small but
3295 * still searchable in few instructions by the JIT and runtime.
3296 * The compressed data is stored in the buffer pointed to by the
3297 * @dest array. Passing a #NULL value for @dest allows to just compute
3298 * the size of the buffer.
3299 * This compression algorithm assumes the bits set in the bitmap are
3300 * few and far between, like in interface bitmaps.
3301 * Returns: the size of the compressed bitmap in bytes.
3304 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3308 const uint8_t *end = bitmap + size;
3309 while (bitmap < end) {
3310 if (*bitmap || numz == 255) {
3334 * mono_class_interface_match:
3335 * @bitmap: a compressed bitmap buffer
3336 * @id: the index to check in the bitmap
3338 * This is a mono internal function.
3339 * Checks if a bit is set in a compressed interface bitmap. @id must
3340 * be already checked for being smaller than the maximum id encoded in the
3343 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3347 mono_class_interface_match (const uint8_t *bitmap, int id)
3350 id -= bitmap [0] * 8;
3354 return bitmap [1] & (1 << id);
3363 * LOCKING: this is supposed to be called with the loader lock held.
3364 * Return -1 on failure and set exception_type
3367 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3371 int i, j, max_iid, num_ifaces;
3372 MonoClass **interfaces_full = NULL;
3373 int *interface_offsets_full = NULL;
3375 GPtrArray **ifaces_array = NULL;
3376 int interface_offsets_count;
3377 MonoClass **array_interfaces = NULL;
3378 int num_array_interfaces;
3379 int is_enumerator = FALSE;
3381 mono_class_setup_supertypes (class);
3383 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3384 * implicit interfaces have the property that they are assigned the same slot in the
3385 * vtables for compatible interfaces
3387 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3389 /* compute maximum number of slots and maximum interface id */
3391 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3392 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3393 for (j = 0; j < class->idepth; j++) {
3394 k = class->supertypes [j];
3395 num_ifaces += k->interface_count;
3396 for (i = 0; i < k->interface_count; i++) {
3397 ic = k->interfaces [i];
3400 mono_class_init (ic);
3402 if (max_iid < ic->interface_id)
3403 max_iid = ic->interface_id;
3405 ifaces = mono_class_get_implemented_interfaces (k, &error);
3406 if (!mono_error_ok (&error)) {
3407 char *name = mono_type_get_full_name (k);
3408 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)));
3410 mono_error_cleanup (&error);
3415 num_ifaces += ifaces->len;
3416 for (i = 0; i < ifaces->len; ++i) {
3417 ic = g_ptr_array_index (ifaces, i);
3418 if (max_iid < ic->interface_id)
3419 max_iid = ic->interface_id;
3421 ifaces_array [j] = ifaces;
3425 for (i = 0; i < num_array_interfaces; ++i) {
3426 ic = array_interfaces [i];
3427 mono_class_init (ic);
3428 if (max_iid < ic->interface_id)
3429 max_iid = ic->interface_id;
3432 if (MONO_CLASS_IS_INTERFACE (class)) {
3434 if (max_iid < class->interface_id)
3435 max_iid = class->interface_id;
3437 class->max_interface_id = max_iid;
3438 /* compute vtable offset for interfaces */
3439 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3440 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3442 for (i = 0; i < num_ifaces; i++) {
3443 interface_offsets_full [i] = -1;
3446 /* skip the current class */
3447 for (j = 0; j < class->idepth - 1; j++) {
3448 k = class->supertypes [j];
3449 ifaces = ifaces_array [j];
3452 for (i = 0; i < ifaces->len; ++i) {
3454 ic = g_ptr_array_index (ifaces, i);
3456 /*Force the sharing of interface offsets between parent and subtypes.*/
3457 io = mono_class_interface_offset (k, ic);
3459 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3464 g_assert (class == class->supertypes [class->idepth - 1]);
3465 ifaces = ifaces_array [class->idepth - 1];
3467 for (i = 0; i < ifaces->len; ++i) {
3469 ic = g_ptr_array_index (ifaces, i);
3470 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3472 count = count_virtual_methods (ic);
3474 char *name = mono_type_get_full_name (ic);
3475 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3484 if (MONO_CLASS_IS_INTERFACE (class))
3485 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3487 if (num_array_interfaces) {
3488 if (is_enumerator) {
3489 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3490 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3491 g_assert (ienumerator_offset >= 0);
3492 for (i = 0; i < num_array_interfaces; ++i) {
3493 ic = array_interfaces [i];
3494 if (strcmp (ic->name, "IEnumerator`1") == 0)
3495 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3497 g_assert_not_reached ();
3498 /*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);*/
3501 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3502 int ilist_iface_idx = find_array_interface (class, "IList`1");
3503 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3504 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3505 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3506 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3507 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3508 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3509 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3510 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3511 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3512 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3513 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3514 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3515 for (i = 0; i < num_array_interfaces; ++i) {
3517 ic = array_interfaces [i];
3518 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3519 offset = ilist_offset;
3520 else if (strcmp (ic->name, "ICollection`1") == 0)
3521 offset = icollection_offset;
3522 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3523 offset = ienumerable_offset;
3524 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3525 offset = ireadonlylist_offset;
3526 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3527 offset = ireadonlycollection_offset;
3529 g_assert_not_reached ();
3530 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3531 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3536 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3537 if (interface_offsets_full [i] != -1) {
3538 interface_offsets_count ++;
3543 * We might get called multiple times:
3544 * - mono_class_init ()
3545 * - mono_class_setup_vtable ().
3546 * - mono_class_setup_interface_offsets ().
3547 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3548 * means we have to overwrite those when called from other places (#4440).
3550 if (class->interfaces_packed && !overwrite) {
3551 g_assert (class->interface_offsets_count == interface_offsets_count);
3555 class->interface_offsets_count = interface_offsets_count;
3556 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3557 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3558 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3559 #ifdef COMPRESSED_INTERFACE_BITMAP
3560 bitmap = g_malloc0 (bsize);
3562 bitmap = mono_class_alloc0 (class, bsize);
3564 for (i = 0; i < interface_offsets_count; i++) {
3565 int id = interfaces_full [i]->interface_id;
3566 bitmap [id >> 3] |= (1 << (id & 7));
3567 class->interfaces_packed [i] = interfaces_full [i];
3568 class->interface_offsets_packed [i] = interface_offsets_full [i];
3569 /*if (num_array_interfaces)
3570 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]);*/
3572 #ifdef COMPRESSED_INTERFACE_BITMAP
3573 i = mono_compress_bitmap (NULL, bitmap, bsize);
3574 class->interface_bitmap = mono_class_alloc0 (class, i);
3575 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3578 class->interface_bitmap = bitmap;
3583 g_free (interfaces_full);
3584 g_free (interface_offsets_full);
3585 g_free (array_interfaces);
3586 for (i = 0; i < class->idepth; i++) {
3587 ifaces = ifaces_array [i];
3589 g_ptr_array_free (ifaces, TRUE);
3591 g_free (ifaces_array);
3593 //printf ("JUST DONE: ");
3594 //print_implemented_interfaces (class);
3600 * Setup interface offsets for interfaces.
3602 * - class->max_interface_id
3603 * - class->interface_offsets_count
3604 * - class->interfaces_packed
3605 * - class->interface_offsets_packed
3606 * - class->interface_bitmap
3608 * This function can fail @class.
3611 mono_class_setup_interface_offsets (MonoClass *class)
3613 mono_loader_lock ();
3615 setup_interface_offsets (class, 0, FALSE);
3617 mono_loader_unlock ();
3620 /*Checks if @klass has @parent as one of it's parents type gtd
3624 * Bar<T> : Foo<Bar<Bar<T>>>
3628 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3630 klass = mono_class_get_generic_type_definition (klass);
3631 parent = mono_class_get_generic_type_definition (parent);
3632 mono_class_setup_supertypes (klass);
3633 mono_class_setup_supertypes (parent);
3635 return klass->idepth >= parent->idepth &&
3636 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3640 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3642 MonoGenericInst *ginst;
3644 if (!class->generic_class) {
3645 mono_class_setup_vtable_full (class, in_setup);
3646 return class->exception_type == 0;
3649 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3650 if (class->generic_class->container_class->exception_type) {
3651 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3655 ginst = class->generic_class->context.class_inst;
3656 for (i = 0; i < ginst->type_argc; ++i) {
3658 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3660 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3661 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3662 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3664 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3665 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3673 * mono_class_setup_vtable:
3675 * Creates the generic vtable of CLASS.
3676 * Initializes the following fields in MonoClass:
3679 * Plus all the fields initialized by setup_interface_offsets ().
3680 * If there is an error during vtable construction, class->exception_type is set.
3682 * LOCKING: Acquires the loader lock.
3685 mono_class_setup_vtable (MonoClass *class)
3687 mono_class_setup_vtable_full (class, NULL);
3691 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3693 MonoMethod **overrides;
3694 MonoGenericContext *context;
3702 if (MONO_CLASS_IS_INTERFACE (class)) {
3703 /* This sets method->slot for all methods if this is an interface */
3704 mono_class_setup_methods (class);
3708 if (class->exception_type)
3711 if (g_list_find (in_setup, class))
3714 mono_loader_lock ();
3716 if (class->vtable) {
3717 mono_loader_unlock ();
3721 mono_stats.generic_vtable_count ++;
3722 in_setup = g_list_prepend (in_setup, class);
3724 if (class->generic_class) {
3725 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3726 mono_loader_unlock ();
3727 g_list_remove (in_setup, class);
3731 context = mono_class_get_context (class);
3732 type_token = class->generic_class->container_class->type_token;
3734 context = (MonoGenericContext *) class->generic_container;
3735 type_token = class->type_token;
3738 if (image_is_dynamic (class->image)) {
3739 /* Generic instances can have zero method overrides without causing any harm.
3740 * This is true since we don't do layout all over again for them, we simply inflate
3741 * the layout of the parent.
3743 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3745 /* The following call fails if there are missing methods in the type */
3746 /* FIXME it's probably a good idea to avoid this for generic instances. */
3747 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3751 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3753 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3757 mono_loader_unlock ();
3758 g_list_remove (in_setup, class);
3763 #define DEBUG_INTERFACE_VTABLE_CODE 0
3764 #define TRACE_INTERFACE_VTABLE_CODE 0
3765 #define VERIFY_INTERFACE_VTABLE_CODE 0
3766 #define VTABLE_SELECTOR (1)
3768 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3769 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3770 if (!(VTABLE_SELECTOR)) break; \
3774 #define DEBUG_INTERFACE_VTABLE(stmt)
3777 #if TRACE_INTERFACE_VTABLE_CODE
3778 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3779 if (!(VTABLE_SELECTOR)) break; \
3783 #define TRACE_INTERFACE_VTABLE(stmt)
3786 #if VERIFY_INTERFACE_VTABLE_CODE
3787 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3788 if (!(VTABLE_SELECTOR)) break; \
3792 #define VERIFY_INTERFACE_VTABLE(stmt)
3796 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3798 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3802 GString *res = g_string_new ("");
3804 g_string_append_c (res, '(');
3805 for (i = 0; i < sig->param_count; ++i) {
3807 g_string_append_c (res, ',');
3808 mono_type_get_desc (res, sig->params [i], include_namespace);
3810 g_string_append (res, ")=>");
3811 if (sig->ret != NULL) {
3812 mono_type_get_desc (res, sig->ret, include_namespace);
3814 g_string_append (res, "NULL");
3817 g_string_free (res, FALSE);
3821 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3822 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3823 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3824 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3832 is_wcf_hack_disabled (void)
3834 static gboolean disabled;
3835 static gboolean inited = FALSE;
3837 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3844 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) {
3845 MonoMethodSignature *cmsig, *imsig;
3846 if (strcmp (im->name, cm->name) == 0) {
3847 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3848 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3851 if (! slot_is_empty) {
3852 if (require_newslot) {
3853 if (! interface_is_explicitly_implemented_by_class) {
3854 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3857 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3858 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3862 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3865 cmsig = mono_method_signature (cm);
3866 imsig = mono_method_signature (im);
3867 if (!cmsig || !imsig) {
3868 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3872 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3873 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3874 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3875 TRACE_INTERFACE_VTABLE (printf ("]"));
3878 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3879 /* CAS - SecurityAction.InheritanceDemand on interface */
3880 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3881 mono_secman_inheritancedemand_method (cm, im);
3884 if (mono_security_core_clr_enabled ())
3885 mono_security_core_clr_check_override (class, cm, im);
3887 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3888 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3889 char *body_name = mono_method_full_name (cm, TRUE);
3890 char *decl_name = mono_method_full_name (im, TRUE);
3891 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));
3899 MonoClass *ic = im->klass;
3900 const char *ic_name_space = ic->name_space;
3901 const char *ic_name = ic->name;
3904 if (! require_newslot) {
3905 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3908 if (cm->klass->rank == 0) {
3909 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3912 cmsig = mono_method_signature (cm);
3913 imsig = mono_method_signature (im);
3914 if (!cmsig || !imsig) {
3915 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3919 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3920 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3921 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3922 TRACE_INTERFACE_VTABLE (printf ("]"));
3925 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3926 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3929 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3930 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3933 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))) {
3934 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3938 subname = strstr (cm->name, ic_name_space);
3939 if (subname != cm->name) {
3940 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3943 subname += strlen (ic_name_space);
3944 if (subname [0] != '.') {
3945 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3949 if (strstr (subname, ic_name) != subname) {
3950 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3953 subname += strlen (ic_name);
3954 if (subname [0] != '.') {
3955 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3959 if (strcmp (subname, im->name) != 0) {
3960 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3964 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3965 /* CAS - SecurityAction.InheritanceDemand on interface */
3966 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3967 mono_secman_inheritancedemand_method (cm, im);
3970 if (mono_security_core_clr_enabled ())
3971 mono_security_core_clr_check_override (class, cm, im);
3973 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3974 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3975 char *body_name = mono_method_full_name (cm, TRUE);
3976 char *decl_name = mono_method_full_name (im, TRUE);
3977 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));
3987 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3989 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3990 MonoMethod *method = key;
3991 MonoMethod *override = value;
3992 MonoClass *method_class = mono_method_get_class (method);
3993 MonoClass *override_class = mono_method_get_class (override);
3995 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3996 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3997 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4000 print_overrides (GHashTable *override_map, const char *message) {
4002 printf ("Override map \"%s\" START:\n", message);
4003 g_hash_table_foreach (override_map, foreach_override, NULL);
4004 printf ("Override map \"%s\" END.\n", message);
4006 printf ("Override map \"%s\" EMPTY.\n", message);
4010 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4011 char *full_name = mono_type_full_name (&class->byval_arg);
4015 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4017 if (print_interfaces) {
4018 print_implemented_interfaces (class);
4019 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4022 if (class->parent) {
4023 parent_size = class->parent->vtable_size;
4027 for (i = 0; i < size; ++i) {
4028 MonoMethod *cm = vtable [i];
4029 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4030 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4032 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4040 #if VERIFY_INTERFACE_VTABLE_CODE
4042 mono_method_try_get_vtable_index (MonoMethod *method)
4044 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4045 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4046 if (imethod->declaring->is_generic)
4047 return imethod->declaring->slot;
4049 return method->slot;
4053 mono_class_verify_vtable (MonoClass *class)
4056 char *full_name = mono_type_full_name (&class->byval_arg);
4058 printf ("*** Verifying VTable of class '%s' \n", full_name);
4062 if (!class->methods)
4065 for (i = 0; i < class->method.count; ++i) {
4066 MonoMethod *cm = class->methods [i];
4069 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4073 full_name = mono_method_full_name (cm, TRUE);
4075 slot = mono_method_try_get_vtable_index (cm);
4077 if (slot >= class->vtable_size) {
4078 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4082 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4083 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4084 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4085 g_free (other_name);
4088 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4095 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4097 char *method_signature;
4100 for (index = 0; index < onum; ++index) {
4101 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4102 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4104 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4105 type_name = mono_type_full_name (&class->byval_arg);
4106 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4107 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4108 g_free (method_signature);
4110 mono_class_setup_methods (class);
4111 if (class->exception_type) {
4112 char *name = mono_type_get_full_name (class);
4113 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4117 for (index = 0; index < class->method.count; ++index) {
4118 MonoMethod *cm = class->methods [index];
4119 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4121 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4122 g_free (method_signature);
4127 mono_method_get_method_definition (MonoMethod *method)
4129 while (method->is_inflated)
4130 method = ((MonoMethodInflated*)method)->declaring;
4135 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4139 for (i = 0; i < onum; ++i) {
4140 MonoMethod *decl = overrides [i * 2];
4141 MonoMethod *body = overrides [i * 2 + 1];
4143 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4144 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4148 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4149 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4150 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4152 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4156 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4157 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4158 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4160 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4164 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4165 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4169 body = mono_method_get_method_definition (body);
4170 decl = mono_method_get_method_definition (decl);
4172 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4173 char *body_name = mono_method_full_name (body, TRUE);
4174 char *decl_name = mono_method_full_name (decl, TRUE);
4175 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));
4185 mono_class_need_stelemref_method (MonoClass *class)
4187 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4191 * LOCKING: this is supposed to be called with the loader lock held.
4194 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4198 MonoMethod **vtable;
4199 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4200 GPtrArray *ifaces = NULL;
4201 GHashTable *override_map = NULL;
4202 gboolean security_enabled = mono_security_enabled ();
4204 gpointer class_iter;
4205 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4206 int first_non_interface_slot;
4208 GSList *virt_methods = NULL, *l;
4209 int stelemref_slot = 0;
4214 if (overrides && !verify_class_overrides (class, overrides, onum))
4217 ifaces = mono_class_get_implemented_interfaces (class, &error);
4218 if (!mono_error_ok (&error)) {
4219 char *name = mono_type_get_full_name (class);
4220 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)));
4222 mono_error_cleanup (&error);
4224 } else if (ifaces) {
4225 for (i = 0; i < ifaces->len; i++) {
4226 MonoClass *ic = g_ptr_array_index (ifaces, i);
4227 max_vtsize += ic->method.count;
4229 g_ptr_array_free (ifaces, TRUE);
4233 if (class->parent) {
4234 mono_class_init (class->parent);
4235 mono_class_setup_vtable_full (class->parent, in_setup);
4237 if (class->parent->exception_type) {
4238 char *name = mono_type_get_full_name (class->parent);
4239 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4244 max_vtsize += class->parent->vtable_size;
4245 cur_slot = class->parent->vtable_size;
4248 max_vtsize += class->method.count;
4250 /*Array have a slot for stelemref*/
4251 if (mono_class_need_stelemref_method (class)) {
4252 stelemref_slot = cur_slot;
4257 vtable = alloca (sizeof (gpointer) * max_vtsize);
4258 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4260 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4262 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4263 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4266 max_iid = class->max_interface_id;
4267 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4269 /* Optimized version for generic instances */
4270 if (class->generic_class) {
4272 MonoClass *gklass = class->generic_class->container_class;
4275 mono_class_setup_vtable_full (gklass, in_setup);
4276 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4277 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4281 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4282 class->vtable_size = gklass->vtable_size;
4283 for (i = 0; i < gklass->vtable_size; ++i)
4284 if (gklass->vtable [i]) {
4285 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4286 if (!mono_error_ok (&error)) {
4287 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4288 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4290 mono_error_cleanup (&error);
4294 tmp [i]->slot = gklass->vtable [i]->slot;
4296 mono_memory_barrier ();
4297 class->vtable = tmp;
4299 /* Have to set method->slot for abstract virtual methods */
4300 if (class->methods && gklass->methods) {
4301 for (i = 0; i < class->method.count; ++i)
4302 if (class->methods [i]->slot == -1)
4303 class->methods [i]->slot = gklass->methods [i]->slot;
4309 if (class->parent && class->parent->vtable_size) {
4310 MonoClass *parent = class->parent;
4313 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4315 // Also inherit parent interface vtables, just as a starting point.
4316 // This is needed otherwise bug-77127.exe fails when the property methods
4317 // have different names in the iterface and the class, because for child
4318 // classes the ".override" information is not used anymore.
4319 for (i = 0; i < parent->interface_offsets_count; i++) {
4320 MonoClass *parent_interface = parent->interfaces_packed [i];
4321 int interface_offset = mono_class_interface_offset (class, parent_interface);
4322 /*FIXME this is now dead code as this condition will never hold true.
4323 Since interface offsets are inherited then the offset of an interface implemented
4324 by a parent will never be the out of it's vtable boundary.
4326 if (interface_offset >= parent->vtable_size) {
4327 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4330 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4331 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4332 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4333 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4334 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4335 parent_interface_offset + j, parent_interface_offset, j,
4336 interface_offset + j, interface_offset, j));
4343 /*Array have a slot for stelemref*/
4344 if (mono_class_need_stelemref_method (class)) {
4345 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4347 method->slot = stelemref_slot;
4349 g_assert (method->slot == stelemref_slot);
4351 vtable [stelemref_slot] = method;
4354 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4355 /* override interface methods */
4356 for (i = 0; i < onum; i++) {
4357 MonoMethod *decl = overrides [i*2];
4358 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4360 dslot = mono_method_get_vtable_slot (decl);
4362 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4366 dslot += mono_class_interface_offset (class, decl->klass);
4367 vtable [dslot] = overrides [i*2 + 1];
4368 vtable [dslot]->slot = dslot;
4370 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4372 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4374 if (mono_security_core_clr_enabled ())
4375 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4378 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4379 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4382 * Create a list of virtual methods to avoid calling
4383 * mono_class_get_virtual_methods () which is slow because of the metadata
4387 gpointer iter = NULL;
4390 virt_methods = NULL;
4391 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4392 virt_methods = g_slist_prepend (virt_methods, cm);
4394 if (class->exception_type)
4398 // Loop on all implemented interfaces...
4399 for (i = 0; i < class->interface_offsets_count; i++) {
4400 MonoClass *parent = class->parent;
4402 gboolean interface_is_explicitly_implemented_by_class;
4405 ic = class->interfaces_packed [i];
4406 ic_offset = mono_class_interface_offset (class, ic);
4408 mono_class_setup_methods (ic);
4409 if (ic->exception_type)
4412 // Check if this interface is explicitly implemented (instead of just inherited)
4413 if (parent != NULL) {
4414 int implemented_interfaces_index;
4415 interface_is_explicitly_implemented_by_class = FALSE;
4416 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4417 if (ic == class->interfaces [implemented_interfaces_index]) {
4418 interface_is_explicitly_implemented_by_class = TRUE;
4423 interface_is_explicitly_implemented_by_class = TRUE;
4426 // Loop on all interface methods...
4427 for (im_index = 0; im_index < ic->method.count; im_index++) {
4428 MonoMethod *im = ic->methods [im_index];
4429 int im_slot = ic_offset + im->slot;
4430 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4432 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4435 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4437 // If there is an explicit implementation, just use it right away,
4438 // otherwise look for a matching method
4439 if (override_im == NULL) {
4444 // First look for a suitable method among the class methods
4446 for (l = virt_methods; l; l = l->next) {
4448 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)));
4449 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4450 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4451 vtable [im_slot] = cm;
4452 /* Why do we need this? */
4457 TRACE_INTERFACE_VTABLE (printf ("\n"));
4458 if (class->exception_type) /*Might be set by check_interface_method_override*/
4462 // If the slot is still empty, look in all the inherited virtual methods...
4463 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4464 MonoClass *parent = class->parent;
4465 // Reverse order, so that last added methods are preferred
4466 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4467 MonoMethod *cm = parent->vtable [cm_index];
4469 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));
4470 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4471 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4472 vtable [im_slot] = cm;
4473 /* Why do we need this? */
4479 if (class->exception_type) /*Might be set by check_interface_method_override*/
4481 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4485 g_assert (vtable [im_slot] == override_im);
4490 // If the class is not abstract, check that all its interface slots are full.
4491 // The check is done here and not directly at the end of the loop above because
4492 // it can happen (for injected generic array interfaces) that the same slot is
4493 // processed multiple times (those interfaces have overlapping slots), and it
4494 // will not always be the first pass the one that fills the slot.
4495 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4496 for (i = 0; i < class->interface_offsets_count; i++) {
4500 ic = class->interfaces_packed [i];
4501 ic_offset = mono_class_interface_offset (class, ic);
4503 for (im_index = 0; im_index < ic->method.count; im_index++) {
4504 MonoMethod *im = ic->methods [im_index];
4505 int im_slot = ic_offset + im->slot;
4507 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4510 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4511 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4512 if (vtable [im_slot] == NULL) {
4513 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4520 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4522 for (l = virt_methods; l; l = l->next) {
4525 * If the method is REUSE_SLOT, we must check in the
4526 * base class for a method to override.
4528 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4530 for (k = class->parent; k ; k = k->parent) {
4535 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4536 MonoMethodSignature *cmsig, *m1sig;
4538 cmsig = mono_method_signature (cm);
4539 m1sig = mono_method_signature (m1);
4541 if (!cmsig || !m1sig) {
4542 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4546 if (!strcmp(cm->name, m1->name) &&
4547 mono_metadata_signature_equal (cmsig, m1sig)) {
4549 /* CAS - SecurityAction.InheritanceDemand */
4550 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4551 mono_secman_inheritancedemand_method (cm, m1);
4554 if (mono_security_core_clr_enabled ())
4555 mono_security_core_clr_check_override (class, cm, m1);
4557 slot = mono_method_get_vtable_slot (m1);
4561 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4562 char *body_name = mono_method_full_name (cm, TRUE);
4563 char *decl_name = mono_method_full_name (m1, TRUE);
4564 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));
4570 g_assert (cm->slot < max_vtsize);
4572 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4573 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4574 mono_method_full_name (m1, 1), m1,
4575 mono_method_full_name (cm, 1), cm));
4576 g_hash_table_insert (override_map, m1, cm);
4580 if (k->exception_type)
4590 /*Non final newslot methods must be given a non-interface vtable slot*/
4591 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4595 cm->slot = cur_slot++;
4597 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4598 vtable [cm->slot] = cm;
4601 /* override non interface methods */
4602 for (i = 0; i < onum; i++) {
4603 MonoMethod *decl = overrides [i*2];
4604 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4605 g_assert (decl->slot != -1);
4606 vtable [decl->slot] = overrides [i*2 + 1];
4607 overrides [i * 2 + 1]->slot = decl->slot;
4609 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4610 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4611 mono_method_full_name (decl, 1), decl,
4612 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4613 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4615 if (mono_security_core_clr_enabled ())
4616 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4621 * If a method occupies more than one place in the vtable, and it is
4622 * overriden, then change the other occurances too.
4627 for (i = 0; i < max_vtsize; ++i)
4629 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4631 cm = g_hash_table_lookup (override_map, vtable [i]);
4636 g_hash_table_destroy (override_map);
4637 override_map = NULL;
4640 g_slist_free (virt_methods);
4641 virt_methods = NULL;
4643 /* Ensure that all vtable slots are filled with concrete instance methods */
4644 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4645 for (i = 0; i < cur_slot; ++i) {
4646 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4647 char *type_name = mono_type_get_full_name (class);
4648 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4649 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));
4651 g_free (method_name);
4657 if (class->generic_class) {
4658 MonoClass *gklass = class->generic_class->container_class;
4660 mono_class_init (gklass);
4662 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4664 /* Check that the vtable_size value computed in mono_class_init () is correct */
4665 if (class->vtable_size)
4666 g_assert (cur_slot == class->vtable_size);
4667 class->vtable_size = cur_slot;
4670 /* Try to share the vtable with our parent. */
4671 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4672 mono_memory_barrier ();
4673 class->vtable = class->parent->vtable;
4675 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4676 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4677 mono_memory_barrier ();
4678 class->vtable = tmp;
4681 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4682 if (mono_print_vtable) {
4685 print_implemented_interfaces (class);
4687 for (i = 0; i <= max_iid; i++)
4688 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4691 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4692 class->vtable_size, icount);
4694 for (i = 0; i < cur_slot; ++i) {
4699 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4700 mono_method_full_name (cm, TRUE));
4706 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4707 class->name, max_iid);
4709 for (i = 0; i < class->interface_count; i++) {
4710 ic = class->interfaces [i];
4711 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4712 mono_class_interface_offset (class, ic),
4713 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4716 for (k = class->parent; k ; k = k->parent) {
4717 for (i = 0; i < k->interface_count; i++) {
4718 ic = k->interfaces [i];
4719 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4720 mono_class_interface_offset (class, ic),
4721 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4727 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4732 char *name = mono_type_get_full_name (class);
4733 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4736 g_hash_table_destroy (override_map);
4738 g_slist_free (virt_methods);
4743 * mono_method_get_vtable_slot:
4745 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4746 * LOCKING: Acquires the loader lock.
4748 * FIXME Use proper MonoError machinery here.
4751 mono_method_get_vtable_slot (MonoMethod *method)
4753 if (method->slot == -1) {
4754 mono_class_setup_vtable (method->klass);
4755 if (method->klass->exception_type)
4757 if (method->slot == -1) {
4761 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4762 g_assert (method->klass->generic_class);
4763 gklass = method->klass->generic_class->container_class;
4764 mono_class_setup_methods (method->klass);
4765 g_assert (method->klass->methods);
4766 for (i = 0; i < method->klass->method.count; ++i) {
4767 if (method->klass->methods [i] == method)
4770 g_assert (i < method->klass->method.count);
4771 g_assert (gklass->methods);
4772 method->slot = gklass->methods [i]->slot;
4774 g_assert (method->slot != -1);
4776 return method->slot;
4780 * mono_method_get_vtable_index:
4783 * Returns the index into the runtime vtable to access the method or,
4784 * in the case of a virtual generic method, the virtual generic method
4785 * thunk. Returns -1 on failure.
4787 * FIXME Use proper MonoError machinery here.
4790 mono_method_get_vtable_index (MonoMethod *method)
4792 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4793 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4794 if (imethod->declaring->is_generic)
4795 return mono_method_get_vtable_slot (imethod->declaring);
4797 return mono_method_get_vtable_slot (method);
4800 static MonoMethod *default_ghc = NULL;
4801 static MonoMethod *default_finalize = NULL;
4802 static int finalize_slot = -1;
4803 static int ghc_slot = -1;
4806 initialize_object_slots (MonoClass *class)
4811 if (class == mono_defaults.object_class) {
4812 mono_class_setup_vtable (class);
4813 for (i = 0; i < class->vtable_size; ++i) {
4814 MonoMethod *cm = class->vtable [i];
4816 if (!strcmp (cm->name, "GetHashCode"))
4818 else if (!strcmp (cm->name, "Finalize"))
4822 g_assert (ghc_slot > 0);
4823 default_ghc = class->vtable [ghc_slot];
4825 g_assert (finalize_slot > 0);
4826 default_finalize = class->vtable [finalize_slot];
4831 MonoMethod *array_method;
4833 } GenericArrayMethodInfo;
4835 static int generic_array_method_num = 0;
4836 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4839 generic_array_methods (MonoClass *class)
4841 int i, count_generic = 0;
4842 GList *list = NULL, *tmp;
4843 if (generic_array_method_num)
4844 return generic_array_method_num;
4845 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4846 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4847 for (i = 0; i < class->parent->method.count; i++) {
4848 MonoMethod *m = class->parent->methods [i];
4849 if (!strncmp (m->name, "InternalArray__", 15)) {
4851 list = g_list_prepend (list, m);
4854 list = g_list_reverse (list);
4855 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4857 for (tmp = list; tmp; tmp = tmp->next) {
4858 const char *mname, *iname;
4860 MonoMethod *m = tmp->data;
4861 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4862 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4864 generic_array_method_info [i].array_method = m;
4865 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4866 iname = "System.Collections.Generic.ICollection`1.";
4867 mname = m->name + 27;
4868 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4869 iname = "System.Collections.Generic.IEnumerable`1.";
4870 mname = m->name + 27;
4871 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4872 iname = "System.Collections.Generic.IReadOnlyList`1.";
4873 mname = m->name + strlen (ireadonlylist_prefix);
4874 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4875 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4876 mname = m->name + strlen (ireadonlycollection_prefix);
4877 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4878 iname = "System.Collections.Generic.IList`1.";
4879 mname = m->name + 15;
4881 g_assert_not_reached ();
4884 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4885 strcpy (name, iname);
4886 strcpy (name + strlen (iname), mname);
4887 generic_array_method_info [i].name = name;
4890 /*g_print ("array generic methods: %d\n", count_generic);*/
4892 generic_array_method_num = count_generic;
4894 return generic_array_method_num;
4898 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4900 MonoGenericContext tmp_context;
4903 tmp_context.class_inst = NULL;
4904 tmp_context.method_inst = iface->generic_class->context.class_inst;
4905 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4907 for (i = 0; i < generic_array_method_num; i++) {
4908 MonoMethod *m = generic_array_method_info [i].array_method;
4909 MonoMethod *inflated;
4911 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4912 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4917 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4919 int null_length = strlen ("(null)");
4920 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4921 char *s = mono_image_alloc (image, len);
4924 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4925 g_assert (result == len - 1);
4931 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4933 gpointer exception_data = NULL;
4935 switch (error->exception_type) {
4936 case MONO_EXCEPTION_TYPE_LOAD:
4937 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4940 case MONO_EXCEPTION_MISSING_METHOD:
4941 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4944 case MONO_EXCEPTION_MISSING_FIELD: {
4945 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4946 const char *class_name;
4949 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4951 class_name = error->klass->name;
4953 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4956 g_free ((void*)class_name);
4960 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4963 if (error->ref_only)
4964 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.";
4966 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4968 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4972 case MONO_EXCEPTION_BAD_IMAGE:
4973 exception_data = error->msg;
4977 g_assert_not_reached ();
4980 mono_class_set_failure (class, error->exception_type, exception_data);
4985 * @class: the class to initialize
4987 * Compute the instance_size, class_size and other infos that cannot be
4988 * computed at mono_class_get() time. Also compute vtable_size if possible.
4989 * Returns TRUE on success or FALSE if there was a problem in loading
4990 * the type (incorrect assemblies, missing assemblies, methods, etc).
4992 * LOCKING: Acquires the loader lock.
4995 mono_class_init (MonoClass *class)
4998 MonoCachedClassInfo cached_info;
4999 gboolean has_cached_info;
5003 /* Double-checking locking pattern */
5004 if (class->inited || class->exception_type)
5005 return class->exception_type == MONO_EXCEPTION_NONE;
5007 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5009 /* We do everything inside the lock to prevent races */
5010 mono_loader_lock ();
5012 if (class->inited || class->exception_type) {
5013 mono_loader_unlock ();
5014 /* Somebody might have gotten in before us */
5015 return class->exception_type == MONO_EXCEPTION_NONE;
5018 if (class->init_pending) {
5019 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5023 class->init_pending = 1;
5025 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5026 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5031 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5032 MonoClass *element_class = class->element_class;
5033 if (!element_class->inited)
5034 mono_class_init (element_class);
5035 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5036 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5041 /* CAS - SecurityAction.InheritanceDemand */
5042 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5043 mono_secman_inheritancedemand_class (class, class->parent);
5046 mono_stats.initialized_class_count++;
5048 if (class->generic_class && !class->generic_class->is_dynamic) {
5049 MonoClass *gklass = class->generic_class->container_class;
5051 mono_stats.generic_class_count++;
5053 class->method = gklass->method;
5054 class->field = gklass->field;
5056 mono_class_init (gklass);
5057 // FIXME: Why is this needed ?
5058 if (!gklass->exception_type)
5059 mono_class_setup_methods (gklass);
5060 if (gklass->exception_type) {
5061 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5065 if (MONO_CLASS_IS_INTERFACE (class))
5066 class->interface_id = mono_get_unique_iid (class);
5069 if (class->parent && !class->parent->inited)
5070 mono_class_init (class->parent);
5072 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5074 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5075 class->nested_classes_inited = TRUE;
5078 * Computes the size used by the fields, and their locations
5080 if (has_cached_info) {
5081 class->instance_size = cached_info.instance_size;
5082 class->sizes.class_size = cached_info.class_size;
5083 class->packing_size = cached_info.packing_size;
5084 class->min_align = cached_info.min_align;
5085 class->blittable = cached_info.blittable;
5086 class->has_references = cached_info.has_references;
5087 class->has_static_refs = cached_info.has_static_refs;
5088 class->no_special_static_fields = cached_info.no_special_static_fields;
5091 if (!class->size_inited){
5092 mono_class_setup_fields (class);
5093 if (class->exception_type || mono_loader_get_last_error ())
5097 /* Initialize arrays */
5099 class->method.count = 3 + (class->rank > 1? 2: 1);
5101 if (class->interface_count) {
5102 int count_generic = generic_array_methods (class);
5103 class->method.count += class->interface_count * count_generic;
5107 mono_class_setup_supertypes (class);
5110 initialize_object_slots (class);
5113 * Initialize the rest of the data without creating a generic vtable if possible.
5114 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5115 * also avoid computing a generic vtable.
5117 if (has_cached_info) {
5119 class->vtable_size = cached_info.vtable_size;
5120 class->has_finalize = cached_info.has_finalize;
5121 class->has_finalize_inited = TRUE;
5122 class->ghcimpl = cached_info.ghcimpl;
5123 class->has_cctor = cached_info.has_cctor;
5124 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5125 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5126 * The first slot if for array with.
5128 static int szarray_vtable_size[2] = { 0 };
5130 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5133 if (!szarray_vtable_size [slot]) {
5134 mono_class_setup_vtable (class);
5135 szarray_vtable_size [slot] = class->vtable_size;
5137 class->vtable_size = szarray_vtable_size[slot];
5139 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5140 MonoClass *gklass = class->generic_class->container_class;
5142 /* Generic instance case */
5143 class->ghcimpl = gklass->ghcimpl;
5144 class->has_cctor = gklass->has_cctor;
5146 mono_class_setup_vtable (gklass);
5147 if (gklass->exception_type) {
5148 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5152 class->vtable_size = gklass->vtable_size;
5156 /* ghcimpl is not currently used
5158 if (class->parent) {
5159 MonoMethod *cmethod = class->vtable [ghc_slot];
5160 if (cmethod->is_inflated)
5161 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5162 if (cmethod == default_ghc) {
5168 /* C# doesn't allow interfaces to have cctors */
5169 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5170 MonoMethod *cmethod = NULL;
5172 if (class->type_token) {
5173 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5174 /* The find_method function ignores the 'flags' argument */
5175 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5176 class->has_cctor = 1;
5178 mono_class_setup_methods (class);
5179 if (class->exception_type)
5182 for (i = 0; i < class->method.count; ++i) {
5183 MonoMethod *method = class->methods [i];
5184 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5185 (strcmp (".cctor", method->name) == 0)) {
5186 class->has_cctor = 1;
5194 if (class->parent) {
5195 int first_iface_slot;
5196 /* This will compute class->parent->vtable_size for some classes */
5197 mono_class_init (class->parent);
5198 if (class->parent->exception_type) {
5199 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5202 if (mono_loader_get_last_error ())
5204 if (!class->parent->vtable_size) {
5205 /* FIXME: Get rid of this somehow */
5206 mono_class_setup_vtable (class->parent);
5207 if (class->parent->exception_type) {
5208 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5211 if (mono_loader_get_last_error ())
5214 first_iface_slot = class->parent->vtable_size;
5215 if (mono_class_need_stelemref_method (class))
5217 setup_interface_offsets (class, first_iface_slot, TRUE);
5219 setup_interface_offsets (class, 0, TRUE);
5222 if (mono_security_core_clr_enabled ())
5223 mono_security_core_clr_check_inheritance (class);
5225 if (mono_loader_get_last_error ()) {
5226 if (class->exception_type == MONO_EXCEPTION_NONE) {
5227 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5229 mono_loader_clear_error ();
5232 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5233 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5238 /* Because of the double-checking locking pattern */
5239 mono_memory_barrier ();
5241 class->init_pending = 0;
5243 mono_loader_unlock ();
5245 return class->exception_type == MONO_EXCEPTION_NONE;
5249 * mono_class_has_finalizer:
5251 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5255 mono_class_has_finalizer (MonoClass *klass)
5257 MonoClass *class = klass;
5258 gboolean has_finalize = FALSE;
5260 if (klass->has_finalize_inited)
5261 return klass->has_finalize;
5263 /* Interfaces and valuetypes are not supposed to have finalizers */
5264 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5265 MonoMethod *cmethod = NULL;
5267 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5268 } else if (class->generic_class) {
5269 MonoClass *gklass = class->generic_class->container_class;
5271 has_finalize = mono_class_has_finalizer (gklass);
5272 } else if (class->parent && class->parent->has_finalize) {
5273 has_finalize = TRUE;
5275 if (class->parent) {
5277 * Can't search in metadata for a method named Finalize, because that
5278 * ignores overrides.
5280 mono_class_setup_vtable (class);
5281 if (class->exception_type || mono_loader_get_last_error ())
5284 cmethod = class->vtable [finalize_slot];
5288 g_assert (class->vtable_size > finalize_slot);
5290 if (class->parent) {
5291 if (cmethod->is_inflated)
5292 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5293 if (cmethod != default_finalize)
5294 has_finalize = TRUE;
5300 mono_image_lock (klass->image);
5302 if (!klass->has_finalize_inited) {
5303 klass->has_finalize = has_finalize ? 1 : 0;
5305 mono_memory_barrier ();
5306 klass->has_finalize_inited = TRUE;
5309 mono_image_unlock (klass->image);
5311 return klass->has_finalize;
5315 mono_is_corlib_image (MonoImage *image)
5317 /* FIXME: allow the dynamic case for our compilers and with full trust */
5318 if (image_is_dynamic (image))
5319 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5321 return image == mono_defaults.corlib;
5325 * LOCKING: this assumes the loader lock is held
5328 mono_class_setup_mono_type (MonoClass *class)
5330 const char *name = class->name;
5331 const char *nspace = class->name_space;
5332 gboolean is_corlib = mono_is_corlib_image (class->image);
5334 class->this_arg.byref = 1;
5335 class->this_arg.data.klass = class;
5336 class->this_arg.type = MONO_TYPE_CLASS;
5337 class->byval_arg.data.klass = class;
5338 class->byval_arg.type = MONO_TYPE_CLASS;
5340 if (is_corlib && !strcmp (nspace, "System")) {
5341 if (!strcmp (name, "ValueType")) {
5343 * do not set the valuetype bit for System.ValueType.
5344 * class->valuetype = 1;
5346 class->blittable = TRUE;
5347 } else if (!strcmp (name, "Enum")) {
5349 * do not set the valuetype bit for System.Enum.
5350 * class->valuetype = 1;
5352 class->valuetype = 0;
5353 class->enumtype = 0;
5354 } else if (!strcmp (name, "Object")) {
5355 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5356 } else if (!strcmp (name, "String")) {
5357 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5358 } else if (!strcmp (name, "TypedReference")) {
5359 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5363 if (class->valuetype) {
5364 int t = MONO_TYPE_VALUETYPE;
5366 if (is_corlib && !strcmp (nspace, "System")) {
5369 if (!strcmp (name, "Boolean")) {
5370 t = MONO_TYPE_BOOLEAN;
5371 } else if (!strcmp(name, "Byte")) {
5373 class->blittable = TRUE;
5377 if (!strcmp (name, "Char")) {
5382 if (!strcmp (name, "Double")) {
5384 class->blittable = TRUE;
5388 if (!strcmp (name, "Int32")) {
5390 class->blittable = TRUE;
5391 } else if (!strcmp(name, "Int16")) {
5393 class->blittable = TRUE;
5394 } else if (!strcmp(name, "Int64")) {
5396 class->blittable = TRUE;
5397 } else if (!strcmp(name, "IntPtr")) {
5399 class->blittable = TRUE;
5403 if (!strcmp (name, "Single")) {
5405 class->blittable = TRUE;
5406 } else if (!strcmp(name, "SByte")) {
5408 class->blittable = TRUE;
5412 if (!strcmp (name, "UInt32")) {
5414 class->blittable = TRUE;
5415 } else if (!strcmp(name, "UInt16")) {
5417 class->blittable = TRUE;
5418 } else if (!strcmp(name, "UInt64")) {
5420 class->blittable = TRUE;
5421 } else if (!strcmp(name, "UIntPtr")) {
5423 class->blittable = TRUE;
5427 if (!strcmp (name, "TypedReference")) {
5428 t = MONO_TYPE_TYPEDBYREF;
5429 class->blittable = TRUE;
5433 if (!strcmp (name, "Void")) {
5441 class->this_arg.type = class->byval_arg.type = t;
5444 if (MONO_CLASS_IS_INTERFACE (class))
5445 class->interface_id = mono_get_unique_iid (class);
5451 * COM initialization is delayed until needed.
5452 * However when a [ComImport] attribute is present on a type it will trigger
5453 * the initialization. This is not a problem unless the BCL being executed
5454 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5457 init_com_from_comimport (MonoClass *class)
5459 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5460 if (mono_security_core_clr_enabled ()) {
5461 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5462 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5463 /* but it can not be made available for application (i.e. user code) since all COM calls
5464 * are considered native calls. In this case we fail with a TypeLoadException (just like
5465 * Silverlight 2 does */
5466 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5471 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5473 #endif /*DISABLE_COM*/
5476 * LOCKING: this assumes the loader lock is held
5479 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5481 gboolean system_namespace;
5482 gboolean is_corlib = mono_is_corlib_image (class->image);
5484 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5486 /* if root of the hierarchy */
5487 if (system_namespace && !strcmp (class->name, "Object")) {
5488 class->parent = NULL;
5489 class->instance_size = sizeof (MonoObject);
5492 if (!strcmp (class->name, "<Module>")) {
5493 class->parent = NULL;
5494 class->instance_size = 0;
5498 if (!MONO_CLASS_IS_INTERFACE (class)) {
5499 /* Imported COM Objects always derive from __ComObject. */
5501 if (MONO_CLASS_IS_IMPORT (class)) {
5502 init_com_from_comimport (class);
5503 if (parent == mono_defaults.object_class)
5504 parent = mono_class_get_com_object_class ();
5508 /* set the parent to something useful and safe, but mark the type as broken */
5509 parent = mono_defaults.object_class;
5510 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5513 class->parent = parent;
5515 if (parent->generic_class && !parent->name) {
5517 * If the parent is a generic instance, we may get
5518 * called before it is fully initialized, especially
5519 * before it has its name.
5524 #ifndef DISABLE_REMOTING
5525 class->marshalbyref = parent->marshalbyref;
5526 class->contextbound = parent->contextbound;
5529 class->delegate = parent->delegate;
5531 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5532 mono_class_set_is_com_object (class);
5534 if (system_namespace) {
5535 #ifndef DISABLE_REMOTING
5536 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5537 class->marshalbyref = 1;
5539 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5540 class->contextbound = 1;
5542 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5543 class->delegate = 1;
5546 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5547 (strcmp (class->parent->name_space, "System") == 0)))
5548 class->valuetype = 1;
5549 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5550 class->valuetype = class->enumtype = 1;
5552 /*class->enumtype = class->parent->enumtype; */
5554 /* initialize com types if COM interfaces are present */
5556 if (MONO_CLASS_IS_IMPORT (class))
5557 init_com_from_comimport (class);
5559 class->parent = NULL;
5565 * mono_class_setup_supertypes:
5568 * Build the data structure needed to make fast type checks work.
5569 * This currently sets two fields in @class:
5570 * - idepth: distance between @class and System.Object in the type
5572 * - supertypes: array of classes: each element has a class in the hierarchy
5573 * starting from @class up to System.Object
5575 * LOCKING: This function is atomic, in case of contention we waste memory.
5578 mono_class_setup_supertypes (MonoClass *class)
5581 MonoClass **supertypes;
5583 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5587 if (class->parent && !class->parent->supertypes)
5588 mono_class_setup_supertypes (class->parent);
5590 class->idepth = class->parent->idepth + 1;
5594 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5595 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5597 if (class->parent) {
5598 supertypes [class->idepth - 1] = class;
5599 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5601 supertypes [0] = class;
5604 mono_atomic_store_release (&class->supertypes, supertypes);
5608 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5610 MonoClass *gtd = (MonoClass*)user_data;
5611 /* Only try to fix generic instances of @gtd */
5612 if (gclass->generic_class->container_class != gtd)
5615 /* Check if the generic instance has no parent. */
5616 if (gtd->parent && !gclass->parent)
5617 mono_generic_class_setup_parent (gclass, gtd);
5623 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5625 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5626 mono_error_set_type_load_class (error, class, msg);
5630 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5632 MonoLoaderError *lerror = mono_loader_get_last_error ();
5635 set_failure_from_loader_error (class, lerror);
5636 mono_error_set_from_loader_error (error);
5640 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5641 mono_error_set_type_load_class (error, class, msg);
5646 * mono_class_create_from_typedef:
5647 * @image: image where the token is valid
5648 * @type_token: typedef token
5649 * @error: used to return any error found while creating the type
5651 * Create the MonoClass* representing the specified type token.
5652 * @type_token must be a TypeDef token.
5654 * FIXME: don't return NULL on failure, just the the caller figure it out.
5657 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5659 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5660 MonoClass *class, *parent = NULL;
5661 guint32 cols [MONO_TYPEDEF_SIZE];
5662 guint32 cols_next [MONO_TYPEDEF_SIZE];
5663 guint tidx = mono_metadata_token_index (type_token);
5664 MonoGenericContext *context = NULL;
5665 const char *name, *nspace;
5667 MonoClass **interfaces;
5668 guint32 field_last, method_last;
5669 guint32 nesting_tokeen;
5671 mono_error_init (error);
5673 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5674 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5675 g_assert (!mono_loader_get_last_error ());
5679 mono_loader_lock ();
5681 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5682 mono_loader_unlock ();
5683 g_assert (!mono_loader_get_last_error ());
5687 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5689 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5690 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5692 class = mono_image_alloc0 (image, sizeof (MonoClass));
5695 class->name_space = nspace;
5697 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5699 class->image = image;
5700 class->type_token = type_token;
5701 class->flags = cols [MONO_TYPEDEF_FLAGS];
5703 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5705 classes_size += sizeof (MonoClass);
5708 * Check whether we're a generic type definition.
5710 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5711 if (class->generic_container) {
5712 class->is_generic = 1;
5713 class->generic_container->owner.klass = class;
5714 context = &class->generic_container->context;
5717 if (class->generic_container)
5718 enable_gclass_recording ();
5720 if (cols [MONO_TYPEDEF_EXTENDS]) {
5722 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5724 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5725 /*WARNING: this must satisfy mono_metadata_type_hash*/
5726 class->this_arg.byref = 1;
5727 class->this_arg.data.klass = class;
5728 class->this_arg.type = MONO_TYPE_CLASS;
5729 class->byval_arg.data.klass = class;
5730 class->byval_arg.type = MONO_TYPE_CLASS;
5732 parent = mono_class_get_checked (image, parent_token, error);
5733 if (parent && context) /* Always inflate */
5734 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5736 if (parent == NULL) {
5737 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5738 goto parent_failure;
5741 for (tmp = parent; tmp; tmp = tmp->parent) {
5743 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5744 goto parent_failure;
5746 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5747 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5748 goto parent_failure;
5753 mono_class_setup_parent (class, parent);
5755 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5756 mono_class_setup_mono_type (class);
5758 if (class->generic_container)
5759 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5762 * This might access class->byval_arg for recursion generated by generic constraints,
5763 * so it has to come after setup_mono_type ().
5765 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5766 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5767 if (!mono_error_ok (error)) {
5768 /*FIXME implement a mono_class_set_failure_from_mono_error */
5769 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5770 mono_loader_unlock ();
5771 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5772 g_assert (!mono_loader_get_last_error ());
5777 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5781 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5785 class->cast_class = class->element_class = class;
5787 if (!class->enumtype) {
5788 if (!mono_metadata_interfaces_from_typedef_full (
5789 image, type_token, &interfaces, &icount, FALSE, context)){
5790 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5791 mono_loader_unlock ();
5792 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5796 class->interfaces = interfaces;
5797 class->interface_count = icount;
5798 class->interfaces_inited = 1;
5801 /*g_print ("Load class %s\n", name);*/
5804 * Compute the field and method lists
5806 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5807 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5809 if (tt->rows > tidx){
5810 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5811 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5812 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5814 field_last = image->tables [MONO_TABLE_FIELD].rows;
5815 method_last = image->tables [MONO_TABLE_METHOD].rows;
5818 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5819 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5820 class->field.count = field_last - class->field.first;
5822 class->field.count = 0;
5824 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5825 class->method.count = method_last - class->method.first;
5827 class->method.count = 0;
5829 /* reserve space to store vector pointer in arrays */
5830 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5831 class->instance_size += 2 * sizeof (gpointer);
5832 g_assert (class->field.count == 0);
5835 if (class->enumtype) {
5836 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5837 if (!enum_basetype) {
5838 /*set it to a default value as the whole runtime can't handle this to be null*/
5839 class->cast_class = class->element_class = mono_defaults.int32_class;
5840 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5841 mono_loader_unlock ();
5842 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5843 g_assert (!mono_loader_get_last_error ());
5846 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5850 * If we're a generic type definition, load the constraints.
5851 * We must do this after the class has been constructed to make certain recursive scenarios
5854 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5855 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)));
5856 mono_loader_unlock ();
5857 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5858 g_assert (!mono_loader_get_last_error ());
5862 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5863 if (!strncmp (name, "Vector", 6))
5864 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");
5867 mono_loader_unlock ();
5869 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5870 g_assert (!mono_loader_get_last_error ());
5875 mono_class_setup_mono_type (class);
5876 mono_loader_unlock ();
5877 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5878 g_assert (!mono_loader_get_last_error ());
5882 /** is klass Nullable<T>? */
5884 mono_class_is_nullable (MonoClass *klass)
5886 return klass->generic_class != NULL &&
5887 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5891 /** if klass is T? return T */
5893 mono_class_get_nullable_param (MonoClass *klass)
5895 g_assert (mono_class_is_nullable (klass));
5896 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5900 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5904 MonoGenericClass *gclass = klass->generic_class;
5906 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5907 if (!mono_error_ok (&error)) {
5908 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5909 klass->parent = mono_defaults.object_class;
5910 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5911 mono_error_cleanup (&error);
5915 mono_class_setup_parent (klass, klass->parent);
5917 if (klass->enumtype) {
5918 klass->cast_class = gtd->cast_class;
5919 klass->element_class = gtd->element_class;
5925 * Create the `MonoClass' for an instantiation of a generic type.
5926 * We only do this if we actually need it.
5929 mono_generic_class_get_class (MonoGenericClass *gclass)
5931 MonoClass *klass, *gklass;
5933 if (gclass->cached_class)
5934 return gclass->cached_class;
5936 mono_loader_lock ();
5937 if (gclass->cached_class) {
5938 mono_loader_unlock ();
5939 return gclass->cached_class;
5942 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5944 gklass = gclass->container_class;
5946 if (record_gclass_instantiation > 0)
5947 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5949 if (gklass->nested_in) {
5950 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5951 klass->nested_in = gklass->nested_in;
5954 klass->name = gklass->name;
5955 klass->name_space = gklass->name_space;
5957 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5959 klass->image = gklass->image;
5960 klass->flags = gklass->flags;
5961 klass->type_token = gklass->type_token;
5962 klass->field.count = gklass->field.count;
5964 klass->is_inflated = 1;
5965 klass->generic_class = gclass;
5967 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5968 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5969 klass->this_arg.byref = TRUE;
5970 klass->enumtype = gklass->enumtype;
5971 klass->valuetype = gklass->valuetype;
5973 klass->cast_class = klass->element_class = klass;
5975 if (mono_class_is_nullable (klass))
5976 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5979 * We're not interested in the nested classes of a generic instance.
5980 * We use the generic type definition to look for nested classes.
5983 mono_generic_class_setup_parent (klass, gklass);
5985 if (gclass->is_dynamic) {
5988 mono_class_setup_supertypes (klass);
5990 if (klass->enumtype) {
5992 * For enums, gklass->fields might not been set, but instance_size etc. is
5993 * already set in mono_reflection_create_internal_class (). For non-enums,
5994 * these will be computed normally in mono_class_layout_fields ().
5996 klass->instance_size = gklass->instance_size;
5997 klass->sizes.class_size = gklass->sizes.class_size;
5998 mono_memory_barrier ();
5999 klass->size_inited = 1;
6003 mono_memory_barrier ();
6004 gclass->cached_class = klass;
6006 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6008 inflated_classes ++;
6009 inflated_classes_size += sizeof (MonoClass);
6011 mono_loader_unlock ();
6017 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6019 MonoClass *klass, **ptr;
6021 MonoGenericContainer *container = mono_generic_param_owner (param);
6025 image = mono_defaults.corlib;
6027 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6028 classes_size += sizeof (MonoClass);
6031 klass->name = pinfo->name;
6033 int n = mono_generic_param_num (param);
6034 klass->name = mono_image_alloc0 (image, 16);
6035 sprintf ((char*)klass->name, "%d", n);
6040 MonoMethod *omethod = container->owner.method;
6041 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6043 MonoClass *oklass = container->owner.klass;
6044 klass->name_space = oklass ? oklass->name_space : "";
6047 klass->name_space = "";
6050 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6054 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6058 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6059 klass->parent = pinfo->constraints [0];
6061 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6062 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6064 klass->parent = mono_defaults.object_class;
6067 if (count - pos > 0) {
6068 klass->interface_count = count - pos;
6069 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6070 klass->interfaces_inited = TRUE;
6071 for (i = pos; i < count; i++)
6072 klass->interfaces [i - pos] = pinfo->constraints [i];
6075 klass->image = image;
6077 klass->inited = TRUE;
6078 klass->cast_class = klass->element_class = klass;
6079 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6081 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6082 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6083 klass->this_arg.byref = TRUE;
6085 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6086 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6088 /*Init these fields to sane values*/
6089 klass->min_align = 1;
6090 klass->instance_size = sizeof (gpointer);
6091 mono_memory_barrier ();
6092 klass->size_inited = 1;
6094 mono_class_setup_supertypes (klass);
6096 if (count - pos > 0) {
6097 mono_class_setup_vtable (klass->parent);
6098 if (klass->parent->exception_type)
6099 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6101 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6107 #define FAST_CACHE_SIZE 16
6110 * LOCKING: Takes the image lock depending on @take_lock.
6113 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6115 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6116 MonoImage *image = param->image;
6121 if (n < FAST_CACHE_SIZE) {
6123 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6125 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6127 MonoClass *klass = NULL;
6128 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6131 mono_image_lock (image);
6132 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6134 mono_image_unlock (image);
6141 * LOCKING: Image lock (param->image) must be held
6144 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6146 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6147 MonoImage *image = param->image;
6151 if (n < FAST_CACHE_SIZE) {
6153 /* Requires locking to avoid droping an already published class */
6154 if (!image->mvar_cache_fast)
6155 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6156 image->mvar_cache_fast [n] = klass;
6158 if (!image->var_cache_fast)
6159 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6160 image->var_cache_fast [n] = klass;
6163 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6165 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6167 ht = g_hash_table_new (NULL, NULL);
6168 mono_memory_barrier ();
6170 image->mvar_cache_slow = ht;
6172 image->var_cache_slow = ht;
6175 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6180 * LOCKING: Acquires the image lock (@image).
6183 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6185 MonoGenericContainer *container = mono_generic_param_owner (param);
6186 MonoGenericParamInfo *pinfo = NULL;
6187 MonoClass *klass, *klass2;
6190 pinfo = mono_generic_param_info (param);
6191 klass = pinfo->pklass;
6194 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6199 if (!image && container) {
6201 MonoMethod *method = container->owner.method;
6202 image = (method && method->klass) ? method->klass->image : NULL;
6204 MonoClass *klass = container->owner.klass;
6205 // FIXME: 'klass' should not be null
6206 // But, monodis creates GenericContainers without associating a owner to it
6207 image = klass ? klass->image : NULL;
6211 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6213 mono_memory_barrier ();
6215 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6216 image = mono_defaults.corlib;
6218 mono_image_lock (image);
6220 klass2 = pinfo->pklass;
6222 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6228 pinfo->pklass = klass;
6230 set_anon_gparam_class (param, is_mvar, klass);
6232 mono_image_unlock (image);
6234 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6236 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6238 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6244 mono_ptr_class_get (MonoType *type)
6247 MonoClass *el_class;
6251 el_class = mono_class_from_mono_type (type);
6252 image = el_class->image;
6254 mono_image_lock (image);
6255 if (image->ptr_cache) {
6256 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6257 mono_image_unlock (image);
6261 mono_image_unlock (image);
6263 result = mono_image_alloc0 (image, sizeof (MonoClass));
6265 classes_size += sizeof (MonoClass);
6267 result->parent = NULL; /* no parent for PTR types */
6268 result->name_space = el_class->name_space;
6269 name = g_strdup_printf ("%s*", el_class->name);
6270 result->name = mono_image_strdup (image, name);
6273 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6275 result->image = el_class->image;
6276 result->inited = TRUE;
6277 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6278 /* Can pointers get boxed? */
6279 result->instance_size = sizeof (gpointer);
6280 result->cast_class = result->element_class = el_class;
6281 result->blittable = TRUE;
6283 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6284 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6285 result->this_arg.byref = TRUE;
6287 mono_class_setup_supertypes (result);
6289 mono_image_lock (image);
6290 if (image->ptr_cache) {
6292 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6293 mono_image_unlock (image);
6294 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6298 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6300 g_hash_table_insert (image->ptr_cache, el_class, result);
6301 mono_image_unlock (image);
6303 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6309 mono_fnptr_class_get (MonoMethodSignature *sig)
6312 static GHashTable *ptr_hash = NULL;
6314 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6316 mono_loader_lock ();
6319 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6321 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6322 mono_loader_unlock ();
6325 result = g_new0 (MonoClass, 1);
6327 result->parent = NULL; /* no parent for PTR types */
6328 result->name_space = "System";
6329 result->name = "MonoFNPtrFakeClass";
6331 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6333 result->image = mono_defaults.corlib; /* need to fix... */
6334 result->inited = TRUE;
6335 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6336 /* Can pointers get boxed? */
6337 result->instance_size = sizeof (gpointer);
6338 result->cast_class = result->element_class = result;
6339 result->blittable = TRUE;
6341 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6342 result->this_arg.data.method = result->byval_arg.data.method = sig;
6343 result->this_arg.byref = TRUE;
6344 result->blittable = TRUE;
6346 mono_class_setup_supertypes (result);
6348 g_hash_table_insert (ptr_hash, sig, result);
6350 mono_loader_unlock ();
6352 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6358 mono_class_from_mono_type (MonoType *type)
6360 switch (type->type) {
6361 case MONO_TYPE_OBJECT:
6362 return type->data.klass? type->data.klass: mono_defaults.object_class;
6363 case MONO_TYPE_VOID:
6364 return type->data.klass? type->data.klass: mono_defaults.void_class;
6365 case MONO_TYPE_BOOLEAN:
6366 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6367 case MONO_TYPE_CHAR:
6368 return type->data.klass? type->data.klass: mono_defaults.char_class;
6370 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6372 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6374 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6376 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6378 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6380 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6382 return type->data.klass? type->data.klass: mono_defaults.int_class;
6384 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6386 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6388 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6390 return type->data.klass? type->data.klass: mono_defaults.single_class;
6392 return type->data.klass? type->data.klass: mono_defaults.double_class;
6393 case MONO_TYPE_STRING:
6394 return type->data.klass? type->data.klass: mono_defaults.string_class;
6395 case MONO_TYPE_TYPEDBYREF:
6396 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6397 case MONO_TYPE_ARRAY:
6398 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6400 return mono_ptr_class_get (type->data.type);
6401 case MONO_TYPE_FNPTR:
6402 return mono_fnptr_class_get (type->data.method);
6403 case MONO_TYPE_SZARRAY:
6404 return mono_array_class_get (type->data.klass, 1);
6405 case MONO_TYPE_CLASS:
6406 case MONO_TYPE_VALUETYPE:
6407 return type->data.klass;
6408 case MONO_TYPE_GENERICINST:
6409 return mono_generic_class_get_class (type->data.generic_class);
6411 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6412 case MONO_TYPE_MVAR:
6413 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6415 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6416 g_assert_not_reached ();
6423 * mono_type_retrieve_from_typespec
6424 * @image: context where the image is created
6425 * @type_spec: typespec token
6426 * @context: the generic context used to evaluate generic instantiations in
6429 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6431 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6433 *did_inflate = FALSE;
6438 if (context && (context->class_inst || context->method_inst)) {
6439 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6441 if (!mono_error_ok (error)) {
6442 g_assert (!mono_loader_get_last_error ());
6448 *did_inflate = TRUE;
6455 * mono_class_create_from_typespec
6456 * @image: context where the image is created
6457 * @type_spec: typespec token
6458 * @context: the generic context used to evaluate generic instantiations in
6461 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6464 gboolean inflated = FALSE;
6465 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6466 if (!mono_error_ok (error))
6468 ret = mono_class_from_mono_type (t);
6470 mono_metadata_free_type (t);
6475 * mono_bounded_array_class_get:
6476 * @element_class: element class
6477 * @rank: the dimension of the array class
6478 * @bounded: whenever the array has non-zero bounds
6480 * Returns: a class object describing the array with element type @element_type and
6484 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6488 MonoClass *parent = NULL;
6489 GSList *list, *rootlist = NULL;
6492 gboolean corlib_type = FALSE;
6494 g_assert (rank <= 255);
6497 /* bounded only matters for one-dimensional arrays */
6500 image = eclass->image;
6502 if (rank == 1 && !bounded) {
6504 * This case is very frequent not just during compilation because of calls
6505 * from mono_class_from_mono_type (), mono_array_new (),
6506 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6508 mono_mutex_lock (&image->szarray_cache_lock);
6509 if (!image->szarray_cache)
6510 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6511 class = g_hash_table_lookup (image->szarray_cache, eclass);
6512 mono_mutex_unlock (&image->szarray_cache_lock);
6516 mono_loader_lock ();
6518 mono_loader_lock ();
6520 if (!image->array_cache)
6521 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6523 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6524 for (; list; list = list->next) {
6526 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6527 mono_loader_unlock ();
6534 /* for the building corlib use System.Array from it */
6535 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6536 parent = mono_class_from_name (image, "System", "Array");
6539 parent = mono_defaults.array_class;
6540 if (!parent->inited)
6541 mono_class_init (parent);
6544 class = mono_image_alloc0 (image, sizeof (MonoClass));
6546 class->image = image;
6547 class->name_space = eclass->name_space;
6548 nsize = strlen (eclass->name);
6549 name = g_malloc (nsize + 2 + rank + 1);
6550 memcpy (name, eclass->name, nsize);
6553 memset (name + nsize + 1, ',', rank - 1);
6555 name [nsize + rank] = '*';
6556 name [nsize + rank + bounded] = ']';
6557 name [nsize + rank + bounded + 1] = 0;
6558 class->name = mono_image_strdup (image, name);
6561 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6563 classes_size += sizeof (MonoClass);
6565 class->type_token = 0;
6566 /* all arrays are marked serializable and sealed, bug #42779 */
6567 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6568 class->parent = parent;
6569 class->instance_size = mono_class_instance_size (class->parent);
6571 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6572 /*Arrays of those two types are invalid.*/
6573 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6574 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6575 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6576 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6577 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6579 /* element_size -1 is ok as this is not an instantitable type*/
6580 class->sizes.element_size = -1;
6582 class->sizes.element_size = mono_class_array_element_size (eclass);
6584 mono_class_setup_supertypes (class);
6586 if (eclass->generic_class)
6587 mono_class_init (eclass);
6588 if (!eclass->size_inited)
6589 mono_class_setup_fields (eclass);
6590 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6591 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6593 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6597 if (eclass->enumtype)
6598 class->cast_class = eclass->element_class;
6600 class->cast_class = eclass;
6602 switch (class->cast_class->byval_arg.type) {
6604 class->cast_class = mono_defaults.byte_class;
6607 class->cast_class = mono_defaults.int16_class;
6610 #if SIZEOF_VOID_P == 4
6614 class->cast_class = mono_defaults.int32_class;
6617 #if SIZEOF_VOID_P == 8
6621 class->cast_class = mono_defaults.int64_class;
6625 class->element_class = eclass;
6627 if ((rank > 1) || bounded) {
6628 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6629 class->byval_arg.type = MONO_TYPE_ARRAY;
6630 class->byval_arg.data.array = at;
6631 at->eklass = eclass;
6633 /* FIXME: complete.... */
6635 class->byval_arg.type = MONO_TYPE_SZARRAY;
6636 class->byval_arg.data.klass = eclass;
6638 class->this_arg = class->byval_arg;
6639 class->this_arg.byref = 1;
6644 class->generic_container = eclass->generic_container;
6646 if (rank == 1 && !bounded) {
6647 MonoClass *prev_class;
6649 mono_mutex_lock (&image->szarray_cache_lock);
6650 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6652 /* Someone got in before us */
6655 g_hash_table_insert (image->szarray_cache, eclass, class);
6656 mono_mutex_unlock (&image->szarray_cache_lock);
6658 list = g_slist_append (rootlist, class);
6659 g_hash_table_insert (image->array_cache, eclass, list);
6662 mono_loader_unlock ();
6664 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6670 * mono_array_class_get:
6671 * @element_class: element class
6672 * @rank: the dimension of the array class
6674 * Returns: a class object describing the array with element type @element_type and
6678 mono_array_class_get (MonoClass *eclass, guint32 rank)
6680 return mono_bounded_array_class_get (eclass, rank, FALSE);
6684 * mono_class_instance_size:
6687 * Returns: the size of an object instance
6690 mono_class_instance_size (MonoClass *klass)
6692 if (!klass->size_inited)
6693 mono_class_init (klass);
6695 return klass->instance_size;
6699 * mono_class_min_align:
6702 * Returns: minimm alignment requirements
6705 mono_class_min_align (MonoClass *klass)
6707 if (!klass->size_inited)
6708 mono_class_init (klass);
6710 return klass->min_align;
6714 * mono_class_value_size:
6717 * This function is used for value types, and return the
6718 * space and the alignment to store that kind of value object.
6720 * Returns: the size of a value of kind @klass
6723 mono_class_value_size (MonoClass *klass, guint32 *align)
6727 /* fixme: check disable, because we still have external revereces to
6728 * mscorlib and Dummy Objects
6730 /*g_assert (klass->valuetype);*/
6732 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6735 *align = klass->min_align;
6741 * mono_class_data_size:
6744 * Returns: the size of the static class data
6747 mono_class_data_size (MonoClass *klass)
6750 mono_class_init (klass);
6751 /* This can happen with dynamically created types */
6752 if (!klass->fields_inited)
6753 mono_class_setup_fields_locking (klass);
6755 /* in arrays, sizes.class_size is unioned with element_size
6756 * and arrays have no static fields
6760 return klass->sizes.class_size;
6764 * Auxiliary routine to mono_class_get_field
6766 * Takes a field index instead of a field token.
6768 static MonoClassField *
6769 mono_class_get_field_idx (MonoClass *class, int idx)
6771 mono_class_setup_fields_locking (class);
6772 if (class->exception_type)
6776 if (class->image->uncompressed_metadata) {
6778 * class->field.first points to the FieldPtr table, while idx points into the
6779 * Field table, so we have to do a search.
6781 /*FIXME this is broken for types with multiple fields with the same name.*/
6782 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6785 for (i = 0; i < class->field.count; ++i)
6786 if (mono_field_get_name (&class->fields [i]) == name)
6787 return &class->fields [i];
6788 g_assert_not_reached ();
6790 if (class->field.count) {
6791 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6792 return &class->fields [idx - class->field.first];
6796 class = class->parent;
6802 * mono_class_get_field:
6803 * @class: the class to lookup the field.
6804 * @field_token: the field token
6806 * Returns: A MonoClassField representing the type and offset of
6807 * the field, or a NULL value if the field does not belong to this
6811 mono_class_get_field (MonoClass *class, guint32 field_token)
6813 int idx = mono_metadata_token_index (field_token);
6815 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6817 return mono_class_get_field_idx (class, idx - 1);
6821 * mono_class_get_field_from_name:
6822 * @klass: the class to lookup the field.
6823 * @name: the field name
6825 * Search the class @klass and it's parents for a field with the name @name.
6827 * Returns: the MonoClassField pointer of the named field or NULL
6830 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6832 return mono_class_get_field_from_name_full (klass, name, NULL);
6836 * mono_class_get_field_from_name_full:
6837 * @klass: the class to lookup the field.
6838 * @name: the field name
6839 * @type: the type of the fields. This optional.
6841 * Search the class @klass and it's parents for a field with the name @name and type @type.
6843 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6844 * of its generic type definition.
6846 * Returns: the MonoClassField pointer of the named field or NULL
6849 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6853 mono_class_setup_fields_locking (klass);
6854 if (klass->exception_type)
6858 for (i = 0; i < klass->field.count; ++i) {
6859 MonoClassField *field = &klass->fields [i];
6861 if (strcmp (name, mono_field_get_name (field)) != 0)
6865 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6866 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6871 klass = klass->parent;
6877 * mono_class_get_field_token:
6878 * @field: the field we need the token of
6880 * Get the token of a field. Note that the tokesn is only valid for the image
6881 * the field was loaded from. Don't use this function for fields in dynamic types.
6883 * Returns: the token representing the field in the image it was loaded from.
6886 mono_class_get_field_token (MonoClassField *field)
6888 MonoClass *klass = field->parent;
6891 mono_class_setup_fields_locking (klass);
6896 for (i = 0; i < klass->field.count; ++i) {
6897 if (&klass->fields [i] == field) {
6898 int idx = klass->field.first + i + 1;
6900 if (klass->image->uncompressed_metadata)
6901 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6902 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6905 klass = klass->parent;
6908 g_assert_not_reached ();
6913 mono_field_get_index (MonoClassField *field)
6915 int index = field - field->parent->fields;
6917 g_assert (index >= 0 && index < field->parent->field.count);
6923 * mono_class_get_field_default_value:
6925 * Return the default value of the field as a pointer into the metadata blob.
6928 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6931 guint32 constant_cols [MONO_CONSTANT_SIZE];
6933 MonoClass *klass = field->parent;
6935 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6937 if (!klass->ext || !klass->ext->field_def_values) {
6938 MonoFieldDefaultValue *def_values;
6940 mono_class_alloc_ext (klass);
6942 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6944 mono_image_lock (klass->image);
6945 mono_memory_barrier ();
6946 if (!klass->ext->field_def_values)
6947 klass->ext->field_def_values = def_values;
6948 mono_image_unlock (klass->image);
6951 field_index = mono_field_get_index (field);
6953 if (!klass->ext->field_def_values [field_index].data) {
6954 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6958 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6960 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6961 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6962 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6965 *def_type = klass->ext->field_def_values [field_index].def_type;
6966 return klass->ext->field_def_values [field_index].data;
6970 mono_property_get_index (MonoProperty *prop)
6972 int index = prop - prop->parent->ext->properties;
6974 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6980 * mono_class_get_property_default_value:
6982 * Return the default value of the field as a pointer into the metadata blob.
6985 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6988 guint32 constant_cols [MONO_CONSTANT_SIZE];
6989 MonoClass *klass = property->parent;
6991 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6993 * We don't cache here because it is not used by C# so it's quite rare, but
6994 * we still do the lookup in klass->ext because that is where the data
6995 * is stored for dynamic assemblies.
6998 if (image_is_dynamic (klass->image)) {
6999 int prop_index = mono_property_get_index (property);
7000 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7001 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7002 return klass->ext->prop_def_values [prop_index].data;
7006 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7010 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7011 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7012 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7016 mono_class_get_event_token (MonoEvent *event)
7018 MonoClass *klass = event->parent;
7023 for (i = 0; i < klass->ext->event.count; ++i) {
7024 if (&klass->ext->events [i] == event)
7025 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7028 klass = klass->parent;
7031 g_assert_not_reached ();
7036 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7040 gpointer iter = NULL;
7041 while ((p = mono_class_get_properties (klass, &iter))) {
7042 if (! strcmp (name, p->name))
7045 klass = klass->parent;
7051 mono_class_get_property_token (MonoProperty *prop)
7053 MonoClass *klass = prop->parent;
7057 gpointer iter = NULL;
7058 while ((p = mono_class_get_properties (klass, &iter))) {
7059 if (&klass->ext->properties [i] == prop)
7060 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7064 klass = klass->parent;
7067 g_assert_not_reached ();
7072 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7074 const char *name, *nspace;
7075 if (image_is_dynamic (image))
7076 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7078 switch (type_token & 0xff000000){
7079 case MONO_TOKEN_TYPE_DEF: {
7080 guint32 cols [MONO_TYPEDEF_SIZE];
7081 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7082 guint tidx = mono_metadata_token_index (type_token);
7084 if (tidx > tt->rows)
7085 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7087 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7088 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7089 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7090 if (strlen (nspace) == 0)
7091 return g_strdup_printf ("%s", name);
7093 return g_strdup_printf ("%s.%s", nspace, name);
7096 case MONO_TOKEN_TYPE_REF: {
7098 guint32 cols [MONO_TYPEREF_SIZE];
7099 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7100 guint tidx = mono_metadata_token_index (type_token);
7103 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7105 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7106 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7107 mono_error_cleanup (&error);
7111 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7112 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7113 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7114 if (strlen (nspace) == 0)
7115 return g_strdup_printf ("%s", name);
7117 return g_strdup_printf ("%s.%s", nspace, name);
7120 case MONO_TOKEN_TYPE_SPEC:
7121 return g_strdup_printf ("Typespec 0x%08x", type_token);
7123 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7128 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7130 if (image_is_dynamic (image))
7131 return g_strdup_printf ("DynamicAssembly %s", image->name);
7133 switch (type_token & 0xff000000){
7134 case MONO_TOKEN_TYPE_DEF:
7135 if (image->assembly)
7136 return mono_stringify_assembly_name (&image->assembly->aname);
7137 else if (image->assembly_name)
7138 return g_strdup (image->assembly_name);
7139 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7140 case MONO_TOKEN_TYPE_REF: {
7142 MonoAssemblyName aname;
7143 guint32 cols [MONO_TYPEREF_SIZE];
7144 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7145 guint32 idx = mono_metadata_token_index (type_token);
7148 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7150 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7151 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7152 mono_error_cleanup (&error);
7155 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7157 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7158 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7159 case MONO_RESOLUTION_SCOPE_MODULE:
7161 return g_strdup ("");
7162 case MONO_RESOLUTION_SCOPE_MODULEREF:
7164 return g_strdup ("");
7165 case MONO_RESOLUTION_SCOPE_TYPEREF:
7167 return g_strdup ("");
7168 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7169 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7170 return mono_stringify_assembly_name (&aname);
7172 g_assert_not_reached ();
7176 case MONO_TOKEN_TYPE_SPEC:
7178 return g_strdup ("");
7180 g_assert_not_reached ();
7187 * mono_class_get_full:
7188 * @image: the image where the class resides
7189 * @type_token: the token for the class
7190 * @context: the generic context used to evaluate generic instantiations in
7191 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7193 * Returns: the MonoClass that represents @type_token in @image
7196 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7200 class = mono_class_get_checked (image, type_token, &error);
7202 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7203 class = mono_class_inflate_generic_class_checked (class, context, &error);
7206 mono_loader_set_error_from_mono_error (&error);
7207 mono_error_cleanup (&error); /*FIXME don't swallow this error */
7214 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7218 mono_error_init (error);
7219 class = mono_class_get_checked (image, type_token, error);
7221 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7222 class = mono_class_inflate_generic_class_checked (class, context, error);
7227 * mono_class_get_checked:
7228 * @image: the image where the class resides
7229 * @type_token: the token for the class
7230 * @error: error object to return any error
7232 * Returns: the MonoClass that represents @type_token in @image
7235 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7237 MonoClass *class = NULL;
7239 mono_error_init (error);
7241 if (image_is_dynamic (image)) {
7242 int table = mono_metadata_token_table (type_token);
7244 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7245 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7248 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7252 switch (type_token & 0xff000000){
7253 case MONO_TOKEN_TYPE_DEF:
7254 class = mono_class_create_from_typedef (image, type_token, error);
7256 case MONO_TOKEN_TYPE_REF:
7257 class = mono_class_from_typeref_checked (image, type_token, error);
7259 case MONO_TOKEN_TYPE_SPEC:
7260 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7263 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7267 /* Generic case, should be avoided for when a better error is possible. */
7268 if (!class && mono_error_ok (error)) {
7269 char *name = mono_class_name_from_token (image, type_token);
7270 char *assembly = mono_assembly_name_from_token (image, type_token);
7271 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7279 * mono_type_get_checked:
7280 * @image: the image where the type resides
7281 * @type_token: the token for the type
7282 * @context: the generic context used to evaluate generic instantiations in
7283 * @error: Error handling context
7285 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7287 * Returns: the MonoType that represents @type_token in @image
7290 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7292 MonoType *type = NULL;
7293 gboolean inflated = FALSE;
7295 mono_error_init (error);
7297 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7298 if (image_is_dynamic (image))
7299 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7301 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7302 MonoClass *class = mono_class_get_checked (image, type_token, error);
7305 g_assert (!mono_loader_get_last_error ());
7310 return mono_class_get_type (class);
7313 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7316 g_assert (!mono_loader_get_last_error ());
7321 MonoType *tmp = type;
7322 type = mono_class_get_type (mono_class_from_mono_type (type));
7323 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7324 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7325 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7327 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7329 if (type->type != tmp->type)
7332 mono_metadata_free_type (tmp);
7339 mono_class_get (MonoImage *image, guint32 type_token)
7341 return mono_class_get_full (image, type_token, NULL);
7345 * mono_image_init_name_cache:
7347 * Initializes the class name cache stored in image->name_cache.
7349 * LOCKING: Acquires the corresponding image lock.
7352 mono_image_init_name_cache (MonoImage *image)
7354 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7355 guint32 cols [MONO_TYPEDEF_SIZE];
7358 guint32 i, visib, nspace_index;
7359 GHashTable *name_cache2, *nspace_table;
7361 mono_image_lock (image);
7363 if (image->name_cache) {
7364 mono_image_unlock (image);
7368 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7370 if (image_is_dynamic (image)) {
7371 mono_image_unlock (image);
7375 /* Temporary hash table to avoid lookups in the nspace_table */
7376 name_cache2 = g_hash_table_new (NULL, NULL);
7378 for (i = 1; i <= t->rows; ++i) {
7379 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7380 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7382 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7383 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7385 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7387 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7388 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7390 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7391 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7392 if (!nspace_table) {
7393 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7394 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7395 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7398 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7401 /* Load type names from EXPORTEDTYPES table */
7403 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7404 guint32 cols [MONO_EXP_TYPE_SIZE];
7407 for (i = 0; i < t->rows; ++i) {
7408 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7409 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7410 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7412 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7413 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7414 if (!nspace_table) {
7415 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7416 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7417 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7420 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7424 g_hash_table_destroy (name_cache2);
7425 mono_image_unlock (image);
7428 /*FIXME Only dynamic assemblies should allow this operation.*/
7430 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7431 const char *name, guint32 index)
7433 GHashTable *nspace_table;
7434 GHashTable *name_cache;
7437 mono_image_lock (image);
7439 if (!image->name_cache)
7440 mono_image_init_name_cache (image);
7442 name_cache = image->name_cache;
7443 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7444 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7445 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7448 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7449 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7451 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7453 mono_image_unlock (image);
7462 find_nocase (gpointer key, gpointer value, gpointer user_data)
7464 char *name = (char*)key;
7465 FindUserData *data = (FindUserData*)user_data;
7467 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7468 data->value = value;
7472 * mono_class_from_name_case:
7473 * @image: The MonoImage where the type is looked up in
7474 * @name_space: the type namespace
7475 * @name: the type short name.
7476 * @deprecated: use the _checked variant
7478 * Obtains a MonoClass with a given namespace and a given name which
7479 * is located in the given MonoImage. The namespace and name
7480 * lookups are case insensitive.
7483 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7486 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7487 g_assert (!mono_error_ok (&error));
7492 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7494 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7495 guint32 cols [MONO_TYPEDEF_SIZE];
7500 mono_error_init (error);
7502 if (image_is_dynamic (image)) {
7504 FindUserData user_data;
7506 mono_image_lock (image);
7508 if (!image->name_cache)
7509 mono_image_init_name_cache (image);
7511 user_data.key = name_space;
7512 user_data.value = NULL;
7513 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7515 if (user_data.value) {
7516 GHashTable *nspace_table = (GHashTable*)user_data.value;
7518 user_data.key = name;
7519 user_data.value = NULL;
7521 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7523 if (user_data.value)
7524 token = GPOINTER_TO_UINT (user_data.value);
7527 mono_image_unlock (image);
7530 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7536 /* add a cache if needed */
7537 for (i = 1; i <= t->rows; ++i) {
7538 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7539 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7541 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7542 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7544 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7546 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7547 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7548 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7549 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7555 return_nested_in (MonoClass *class, char *nested)
7558 char *s = strchr (nested, '/');
7559 gpointer iter = NULL;
7566 while ((found = mono_class_get_nested_types (class, &iter))) {
7567 if (strcmp (found->name, nested) == 0) {
7569 return return_nested_in (found, s);
7577 search_modules (MonoImage *image, const char *name_space, const char *name)
7579 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7580 MonoImage *file_image;
7585 * The EXPORTEDTYPES table only contains public types, so have to search the
7587 * Note: image->modules contains the contents of the MODULEREF table, while
7588 * the real module list is in the FILE table.
7590 for (i = 0; i < file_table->rows; i++) {
7591 guint32 cols [MONO_FILE_SIZE];
7592 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7593 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7596 file_image = mono_image_load_file_for_image (image, i + 1);
7598 class = mono_class_from_name (file_image, name_space, name);
7608 * mono_class_from_name:
7609 * @image: The MonoImage where the type is looked up in
7610 * @name_space: the type namespace
7611 * @name: the type short name.
7613 * Obtains a MonoClass with a given namespace and a given name which
7614 * is located in the given MonoImage.
7616 * To reference nested classes, use the "/" character as a separator.
7617 * For example use "Foo/Bar" to reference the class Bar that is nested
7618 * inside Foo, like this: "class Foo { class Bar {} }".
7621 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7623 GHashTable *nspace_table;
7624 MonoImage *loaded_image;
7631 if ((nested = strchr (name, '/'))) {
7632 int pos = nested - name;
7633 int len = strlen (name);
7636 memcpy (buf, name, len + 1);
7638 nested = buf + pos + 1;
7642 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7643 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7644 gboolean res = get_class_from_name (image, name_space, name, &class);
7647 class = search_modules (image, name_space, name);
7649 return class ? return_nested_in (class, nested) : NULL;
7655 mono_image_lock (image);
7657 if (!image->name_cache)
7658 mono_image_init_name_cache (image);
7660 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7663 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7665 mono_image_unlock (image);
7667 if (!token && image_is_dynamic (image) && image->modules) {
7668 /* Search modules as well */
7669 for (i = 0; i < image->module_count; ++i) {
7670 MonoImage *module = image->modules [i];
7672 class = mono_class_from_name (module, name_space, name);
7679 class = search_modules (image, name_space, name);
7687 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7688 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7689 guint32 cols [MONO_EXP_TYPE_SIZE];
7692 idx = mono_metadata_token_index (token);
7694 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7696 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7697 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7698 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7701 class = mono_class_from_name (loaded_image, name_space, name);
7703 return return_nested_in (class, nested);
7705 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7706 guint32 assembly_idx;
7708 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7710 mono_assembly_load_reference (image, assembly_idx - 1);
7711 g_assert (image->references [assembly_idx - 1]);
7712 if (image->references [assembly_idx - 1] == (gpointer)-1)
7715 /* FIXME: Cycle detection */
7716 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7718 g_error ("not yet implemented");
7722 token = MONO_TOKEN_TYPE_DEF | token;
7724 class = mono_class_get (image, token);
7726 return return_nested_in (class, nested);
7731 * mono_class_is_subclass_of:
7732 * @klass: class to probe if it is a subclass of another one
7733 * @klassc: the class we suspect is the base class
7734 * @check_interfaces: whether we should perform interface checks
7736 * This method determines whether @klass is a subclass of @klassc.
7738 * If the @check_interfaces flag is set, then if @klassc is an interface
7739 * this method return true if the @klass implements the interface or
7740 * if @klass is an interface, if one of its base classes is @klass.
7742 * If @check_interfaces is false then, then if @klass is not an interface
7743 * then it returns true if the @klass is a subclass of @klassc.
7745 * if @klass is an interface and @klassc is System.Object, then this function
7750 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7751 gboolean check_interfaces)
7753 /*FIXME test for interfaces with variant generic arguments*/
7755 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7756 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7758 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7761 for (i = 0; i < klass->interface_count; i ++) {
7762 MonoClass *ic = klass->interfaces [i];
7767 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7772 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7775 if (klassc == mono_defaults.object_class)
7782 mono_type_is_generic_argument (MonoType *type)
7784 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7788 mono_class_has_variant_generic_params (MonoClass *klass)
7791 MonoGenericContainer *container;
7793 if (!klass->generic_class)
7796 container = klass->generic_class->container_class->generic_container;
7798 for (i = 0; i < container->type_argc; ++i)
7799 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7806 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7808 if (target == candidate)
7811 if (check_for_reference_conv &&
7812 mono_type_is_generic_argument (&target->byval_arg) &&
7813 mono_type_is_generic_argument (&candidate->byval_arg)) {
7814 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7815 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7817 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7820 if (!mono_class_is_assignable_from (target, candidate))
7826 * @container the generic container from the GTD
7827 * @klass: the class to be assigned to
7828 * @oklass: the source class
7830 * Both klass and oklass must be instances of the same generic interface.
7831 * Return true if @klass can be assigned to a @klass variable
7834 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7837 MonoType **klass_argv, **oklass_argv;
7838 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7839 MonoGenericContainer *container = klass_gtd->generic_container;
7841 if (klass == oklass)
7844 /*Viable candidates are instances of the same generic interface*/
7845 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7848 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7849 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7851 for (j = 0; j < container->type_argc; ++j) {
7852 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7853 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7855 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7859 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7860 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7862 if (param1_class != param2_class) {
7863 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7864 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7866 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7867 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7877 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7879 MonoGenericParam *gparam, *ogparam;
7880 MonoGenericParamInfo *tinfo, *cinfo;
7881 MonoClass **candidate_class;
7882 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7885 if (target == candidate)
7887 if (target->byval_arg.type != candidate->byval_arg.type)
7890 gparam = target->byval_arg.data.generic_param;
7891 ogparam = candidate->byval_arg.data.generic_param;
7892 tinfo = mono_generic_param_info (gparam);
7893 cinfo = mono_generic_param_info (ogparam);
7895 class_constraint_satisfied = FALSE;
7896 valuetype_constraint_satisfied = FALSE;
7898 /*candidate must have a super set of target's special constraints*/
7899 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7900 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7902 if (cinfo->constraints) {
7903 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7904 MonoClass *cc = *candidate_class;
7906 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7907 class_constraint_satisfied = TRUE;
7908 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7909 valuetype_constraint_satisfied = TRUE;
7912 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7913 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7915 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7917 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7919 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7920 valuetype_constraint_satisfied)) {
7925 /*candidate type constraints must be a superset of target's*/
7926 if (tinfo->constraints) {
7927 MonoClass **target_class;
7928 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7929 MonoClass *tc = *target_class;
7932 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7933 * check it's constraints since it satisfy the constraint by itself.
7935 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7938 if (!cinfo->constraints)
7941 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7942 MonoClass *cc = *candidate_class;
7944 if (mono_class_is_assignable_from (tc, cc))
7948 * This happens when we have the following:
7950 * Bar<K> where K : IFace
7951 * Foo<T, U> where T : U where U : IFace
7953 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7956 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7957 if (mono_gparam_is_assignable_from (target, cc))
7961 if (!*candidate_class)
7966 /*candidate itself must have a constraint that satisfy target*/
7967 if (cinfo->constraints) {
7968 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7969 MonoClass *cc = *candidate_class;
7970 if (mono_class_is_assignable_from (target, cc))
7978 * mono_class_is_assignable_from:
7979 * @klass: the class to be assigned to
7980 * @oklass: the source class
7982 * Return: true if an instance of object oklass can be assigned to an
7983 * instance of object @klass
7986 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7988 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7990 mono_class_init (klass);
7992 if (!oklass->inited)
7993 mono_class_init (oklass);
7995 if (klass->exception_type || oklass->exception_type)
7998 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7999 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8001 return mono_gparam_is_assignable_from (klass, oklass);
8004 if (MONO_CLASS_IS_INTERFACE (klass)) {
8005 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8006 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8007 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8011 for (i = 0; constraints [i]; ++i) {
8012 if (mono_class_is_assignable_from (klass, constraints [i]))
8020 /* interface_offsets might not be set for dynamic classes */
8021 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8023 * oklass might be a generic type parameter but they have
8024 * interface_offsets set.
8026 return mono_reflection_call_is_assignable_to (oklass, klass);
8027 if (!oklass->interface_bitmap)
8028 /* Happens with generic instances of not-yet created dynamic types */
8030 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8033 if (mono_class_has_variant_generic_params (klass)) {
8036 mono_class_setup_interfaces (oklass, &error);
8037 if (!mono_error_ok (&error)) {
8038 mono_error_cleanup (&error);
8042 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8043 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8044 MonoClass *iface = oklass->interfaces_packed [i];
8046 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8051 } else if (klass->delegate) {
8052 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8054 }else if (klass->rank) {
8055 MonoClass *eclass, *eoclass;
8057 if (oklass->rank != klass->rank)
8060 /* vectors vs. one dimensional arrays */
8061 if (oklass->byval_arg.type != klass->byval_arg.type)
8064 eclass = klass->cast_class;
8065 eoclass = oklass->cast_class;
8068 * a is b does not imply a[] is b[] when a is a valuetype, and
8069 * b is a reference type.
8072 if (eoclass->valuetype) {
8073 if ((eclass == mono_defaults.enum_class) ||
8074 (eclass == mono_defaults.enum_class->parent) ||
8075 (eclass == mono_defaults.object_class))
8079 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8080 } else if (mono_class_is_nullable (klass)) {
8081 if (mono_class_is_nullable (oklass))
8082 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8084 return mono_class_is_assignable_from (klass->cast_class, oklass);
8085 } else if (klass == mono_defaults.object_class)
8088 return mono_class_has_parent (oklass, klass);
8091 /*Check if @oklass is variant compatible with @klass.*/
8093 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8096 MonoType **klass_argv, **oklass_argv;
8097 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8098 MonoGenericContainer *container = klass_gtd->generic_container;
8100 /*Viable candidates are instances of the same generic interface*/
8101 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8104 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8105 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8107 for (j = 0; j < container->type_argc; ++j) {
8108 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8109 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8111 if (param1_class->valuetype != param2_class->valuetype)
8115 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8116 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8118 if (param1_class != param2_class) {
8119 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8120 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8122 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8123 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8131 /*Check if @candidate implements the interface @target*/
8133 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8137 gboolean is_variant = mono_class_has_variant_generic_params (target);
8139 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8140 if (mono_class_is_variant_compatible_slow (target, candidate))
8145 if (candidate == target)
8148 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8149 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8150 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8152 if (tb && tb->interfaces) {
8153 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8154 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8155 MonoClass *iface_class;
8157 /* we can't realize the type here since it can do pretty much anything. */
8160 iface_class = mono_class_from_mono_type (iface->type);
8161 if (iface_class == target)
8163 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8165 if (mono_class_implement_interface_slow (target, iface_class))
8170 /*setup_interfaces don't mono_class_init anything*/
8171 /*FIXME this doesn't handle primitive type arrays.
8172 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8173 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8175 mono_class_setup_interfaces (candidate, &error);
8176 if (!mono_error_ok (&error)) {
8177 mono_error_cleanup (&error);
8181 for (i = 0; i < candidate->interface_count; ++i) {
8182 if (candidate->interfaces [i] == target)
8185 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8188 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8192 candidate = candidate->parent;
8193 } while (candidate);
8199 * Check if @oklass can be assigned to @klass.
8200 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8203 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8205 if (candidate == target)
8207 if (target == mono_defaults.object_class)
8210 if (mono_class_has_parent (candidate, target))
8213 /*If target is not an interface there is no need to check them.*/
8214 if (MONO_CLASS_IS_INTERFACE (target))
8215 return mono_class_implement_interface_slow (target, candidate);
8217 if (target->delegate && mono_class_has_variant_generic_params (target))
8218 return mono_class_is_variant_compatible (target, candidate, FALSE);
8221 MonoClass *eclass, *eoclass;
8223 if (target->rank != candidate->rank)
8226 /* vectors vs. one dimensional arrays */
8227 if (target->byval_arg.type != candidate->byval_arg.type)
8230 eclass = target->cast_class;
8231 eoclass = candidate->cast_class;
8234 * a is b does not imply a[] is b[] when a is a valuetype, and
8235 * b is a reference type.
8238 if (eoclass->valuetype) {
8239 if ((eclass == mono_defaults.enum_class) ||
8240 (eclass == mono_defaults.enum_class->parent) ||
8241 (eclass == mono_defaults.object_class))
8245 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8247 /*FIXME properly handle nullables */
8248 /*FIXME properly handle (M)VAR */
8253 * mono_class_get_cctor:
8254 * @klass: A MonoClass pointer
8256 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8259 mono_class_get_cctor (MonoClass *klass)
8261 MonoCachedClassInfo cached_info;
8263 if (image_is_dynamic (klass->image)) {
8265 * has_cctor is not set for these classes because mono_class_init () is
8268 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8271 if (!klass->has_cctor)
8274 if (mono_class_get_cached_class_info (klass, &cached_info))
8275 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8277 if (klass->generic_class && !klass->methods)
8278 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8280 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8284 * mono_class_get_finalizer:
8285 * @klass: The MonoClass pointer
8287 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8290 mono_class_get_finalizer (MonoClass *klass)
8292 MonoCachedClassInfo cached_info;
8295 mono_class_init (klass);
8296 if (!mono_class_has_finalizer (klass))
8299 if (mono_class_get_cached_class_info (klass, &cached_info))
8300 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8302 mono_class_setup_vtable (klass);
8303 return klass->vtable [finalize_slot];
8308 * mono_class_needs_cctor_run:
8309 * @klass: the MonoClass pointer
8310 * @caller: a MonoMethod describing the caller
8312 * Determines whenever the class has a static constructor and whenever it
8313 * needs to be called when executing CALLER.
8316 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8320 method = mono_class_get_cctor (klass);
8322 return (method == caller) ? FALSE : TRUE;
8328 * mono_class_array_element_size:
8331 * Returns: the number of bytes an element of type @klass
8332 * uses when stored into an array.
8335 mono_class_array_element_size (MonoClass *klass)
8337 MonoType *type = &klass->byval_arg;
8340 switch (type->type) {
8343 case MONO_TYPE_BOOLEAN:
8347 case MONO_TYPE_CHAR:
8356 case MONO_TYPE_CLASS:
8357 case MONO_TYPE_STRING:
8358 case MONO_TYPE_OBJECT:
8359 case MONO_TYPE_SZARRAY:
8360 case MONO_TYPE_ARRAY:
8362 case MONO_TYPE_MVAR:
8363 return sizeof (gpointer);
8368 case MONO_TYPE_VALUETYPE:
8369 if (type->data.klass->enumtype) {
8370 type = mono_class_enum_basetype (type->data.klass);
8371 klass = klass->element_class;
8374 return mono_class_instance_size (klass) - sizeof (MonoObject);
8375 case MONO_TYPE_GENERICINST:
8376 type = &type->data.generic_class->container_class->byval_arg;
8379 case MONO_TYPE_VOID:
8383 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8389 * mono_array_element_size:
8390 * @ac: pointer to a #MonoArrayClass
8392 * Returns: the size of single array element.
8395 mono_array_element_size (MonoClass *ac)
8397 g_assert (ac->rank);
8398 return ac->sizes.element_size;
8402 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8403 MonoGenericContext *context)
8405 if (image_is_dynamic (image)) {
8406 MonoClass *tmp_handle_class;
8407 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8409 g_assert (tmp_handle_class);
8411 *handle_class = tmp_handle_class;
8413 if (tmp_handle_class == mono_defaults.typehandle_class)
8414 return &((MonoClass*)obj)->byval_arg;
8419 switch (token & 0xff000000) {
8420 case MONO_TOKEN_TYPE_DEF:
8421 case MONO_TOKEN_TYPE_REF:
8422 case MONO_TOKEN_TYPE_SPEC: {
8426 *handle_class = mono_defaults.typehandle_class;
8427 type = mono_type_get_checked (image, token, context, &error);
8429 mono_loader_set_error_from_mono_error (&error);
8430 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8433 mono_class_init (mono_class_from_mono_type (type));
8434 /* We return a MonoType* as handle */
8437 case MONO_TOKEN_FIELD_DEF: {
8440 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8444 *handle_class = mono_defaults.fieldhandle_class;
8445 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8447 mono_loader_set_error_from_mono_error (&error);
8448 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8451 mono_class_init (class);
8452 return mono_class_get_field (class, token);
8454 case MONO_TOKEN_METHOD_DEF:
8455 case MONO_TOKEN_METHOD_SPEC: {
8457 meth = mono_get_method_full (image, token, NULL, context);
8459 *handle_class = mono_defaults.methodhandle_class;
8462 case MONO_TOKEN_MEMBER_REF: {
8463 guint32 cols [MONO_MEMBERREF_SIZE];
8465 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8466 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8467 mono_metadata_decode_blob_size (sig, &sig);
8468 if (*sig == 0x6) { /* it's a field */
8471 MonoClassField *field;
8472 field = mono_field_from_token_checked (image, token, &klass, context, &error);
8474 *handle_class = mono_defaults.fieldhandle_class;
8476 mono_loader_set_error_from_mono_error (&error);
8477 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8482 meth = mono_get_method_full (image, token, NULL, context);
8484 *handle_class = mono_defaults.methodhandle_class;
8489 g_warning ("Unknown token 0x%08x in ldtoken", token);
8496 * This function might need to call runtime functions so it can't be part
8497 * of the metadata library.
8499 static MonoLookupDynamicToken lookup_dynamic = NULL;
8502 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8504 lookup_dynamic = func;
8508 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8510 MonoClass *handle_class;
8512 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8516 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8518 return lookup_dynamic (image, token, valid_token, handle_class, context);
8521 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8524 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8526 get_cached_class_info = func;
8530 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8532 if (!get_cached_class_info)
8535 return get_cached_class_info (klass, res);
8539 mono_install_get_class_from_name (MonoGetClassFromName func)
8541 get_class_from_name = func;
8545 mono_class_get_image (MonoClass *klass)
8547 return klass->image;
8551 * mono_class_get_element_class:
8552 * @klass: the MonoClass to act on
8554 * Returns: the element class of an array or an enumeration.
8557 mono_class_get_element_class (MonoClass *klass)
8559 return klass->element_class;
8563 * mono_class_is_valuetype:
8564 * @klass: the MonoClass to act on
8566 * Returns: true if the MonoClass represents a ValueType.
8569 mono_class_is_valuetype (MonoClass *klass)
8571 return klass->valuetype;
8575 * mono_class_is_enum:
8576 * @klass: the MonoClass to act on
8578 * Returns: true if the MonoClass represents an enumeration.
8581 mono_class_is_enum (MonoClass *klass)
8583 return klass->enumtype;
8587 * mono_class_enum_basetype:
8588 * @klass: the MonoClass to act on
8590 * Returns: the underlying type representation for an enumeration.
8593 mono_class_enum_basetype (MonoClass *klass)
8595 if (klass->element_class == klass)
8596 /* SRE or broken types */
8599 return &klass->element_class->byval_arg;
8603 * mono_class_get_parent
8604 * @klass: the MonoClass to act on
8606 * Returns: the parent class for this class.
8609 mono_class_get_parent (MonoClass *klass)
8611 return klass->parent;
8615 * mono_class_get_nesting_type;
8616 * @klass: the MonoClass to act on
8618 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8621 mono_class_get_nesting_type (MonoClass *klass)
8623 return klass->nested_in;
8627 * mono_class_get_rank:
8628 * @klass: the MonoClass to act on
8630 * Returns: the rank for the array (the number of dimensions).
8633 mono_class_get_rank (MonoClass *klass)
8639 * mono_class_get_flags:
8640 * @klass: the MonoClass to act on
8642 * The type flags from the TypeDef table from the metadata.
8643 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8646 * Returns: the flags from the TypeDef table.
8649 mono_class_get_flags (MonoClass *klass)
8651 return klass->flags;
8655 * mono_class_get_name
8656 * @klass: the MonoClass to act on
8658 * Returns: the name of the class.
8661 mono_class_get_name (MonoClass *klass)
8667 * mono_class_get_namespace:
8668 * @klass: the MonoClass to act on
8670 * Returns: the namespace of the class.
8673 mono_class_get_namespace (MonoClass *klass)
8675 return klass->name_space;
8679 * mono_class_get_type:
8680 * @klass: the MonoClass to act on
8682 * This method returns the internal Type representation for the class.
8684 * Returns: the MonoType from the class.
8687 mono_class_get_type (MonoClass *klass)
8689 return &klass->byval_arg;
8693 * mono_class_get_type_token
8694 * @klass: the MonoClass to act on
8696 * This method returns type token for the class.
8698 * Returns: the type token for the class.
8701 mono_class_get_type_token (MonoClass *klass)
8703 return klass->type_token;
8707 * mono_class_get_byref_type:
8708 * @klass: the MonoClass to act on
8713 mono_class_get_byref_type (MonoClass *klass)
8715 return &klass->this_arg;
8719 * mono_class_num_fields:
8720 * @klass: the MonoClass to act on
8722 * Returns: the number of static and instance fields in the class.
8725 mono_class_num_fields (MonoClass *klass)
8727 return klass->field.count;
8731 * mono_class_num_methods:
8732 * @klass: the MonoClass to act on
8734 * Returns: the number of methods in the class.
8737 mono_class_num_methods (MonoClass *klass)
8739 return klass->method.count;
8743 * mono_class_num_properties
8744 * @klass: the MonoClass to act on
8746 * Returns: the number of properties in the class.
8749 mono_class_num_properties (MonoClass *klass)
8751 mono_class_setup_properties (klass);
8753 return klass->ext->property.count;
8757 * mono_class_num_events:
8758 * @klass: the MonoClass to act on
8760 * Returns: the number of events in the class.
8763 mono_class_num_events (MonoClass *klass)
8765 mono_class_setup_events (klass);
8767 return klass->ext->event.count;
8771 * mono_class_get_fields:
8772 * @klass: the MonoClass to act on
8774 * This routine is an iterator routine for retrieving the fields in a class.
8776 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8777 * iterate over all of the elements. When no more values are
8778 * available, the return value is NULL.
8780 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8783 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8785 MonoClassField* field;
8789 mono_class_setup_fields_locking (klass);
8790 if (klass->exception_type)
8792 /* start from the first */
8793 if (klass->field.count) {
8794 return *iter = &klass->fields [0];
8802 if (field < &klass->fields [klass->field.count]) {
8803 return *iter = field;
8809 * mono_class_get_methods
8810 * @klass: the MonoClass to act on
8812 * This routine is an iterator routine for retrieving the fields in a class.
8814 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8815 * iterate over all of the elements. When no more values are
8816 * available, the return value is NULL.
8818 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8821 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8823 MonoMethod** method;
8827 mono_class_setup_methods (klass);
8830 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8831 * FIXME we should better report this error to the caller
8833 if (!klass->methods)
8835 /* start from the first */
8836 if (klass->method.count) {
8837 *iter = &klass->methods [0];
8838 return klass->methods [0];
8846 if (method < &klass->methods [klass->method.count]) {
8854 * mono_class_get_virtual_methods:
8856 * Iterate over the virtual methods of KLASS.
8858 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8861 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8863 MonoMethod** method;
8866 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8868 mono_class_setup_methods (klass);
8870 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8871 * FIXME we should better report this error to the caller
8873 if (!klass->methods)
8875 /* start from the first */
8876 method = &klass->methods [0];
8881 while (method < &klass->methods [klass->method.count]) {
8882 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8886 if (method < &klass->methods [klass->method.count]) {
8893 /* Search directly in metadata to avoid calling setup_methods () */
8894 MonoMethod *res = NULL;
8900 start_index = GPOINTER_TO_UINT (*iter);
8903 for (i = start_index; i < klass->method.count; ++i) {
8906 /* class->method.first points into the methodptr table */
8907 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8909 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8913 if (i < klass->method.count) {
8914 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8915 /* Add 1 here so the if (*iter) check fails */
8916 *iter = GUINT_TO_POINTER (i + 1);
8925 * mono_class_get_properties:
8926 * @klass: the MonoClass to act on
8928 * This routine is an iterator routine for retrieving the properties in a class.
8930 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8931 * iterate over all of the elements. When no more values are
8932 * available, the return value is NULL.
8934 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8937 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8939 MonoProperty* property;
8943 mono_class_setup_properties (klass);
8944 /* start from the first */
8945 if (klass->ext->property.count) {
8946 return *iter = &klass->ext->properties [0];
8954 if (property < &klass->ext->properties [klass->ext->property.count]) {
8955 return *iter = property;
8961 * mono_class_get_events:
8962 * @klass: the MonoClass to act on
8964 * This routine is an iterator routine for retrieving the properties in a class.
8966 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8967 * iterate over all of the elements. When no more values are
8968 * available, the return value is NULL.
8970 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8973 mono_class_get_events (MonoClass* klass, gpointer *iter)
8979 mono_class_setup_events (klass);
8980 /* start from the first */
8981 if (klass->ext->event.count) {
8982 return *iter = &klass->ext->events [0];
8990 if (event < &klass->ext->events [klass->ext->event.count]) {
8991 return *iter = event;
8997 * mono_class_get_interfaces
8998 * @klass: the MonoClass to act on
9000 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9002 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9003 * iterate over all of the elements. When no more values are
9004 * available, the return value is NULL.
9006 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9009 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9017 mono_class_init (klass);
9018 if (!klass->interfaces_inited) {
9019 mono_class_setup_interfaces (klass, &error);
9020 if (!mono_error_ok (&error)) {
9021 mono_error_cleanup (&error);
9025 /* start from the first */
9026 if (klass->interface_count) {
9027 *iter = &klass->interfaces [0];
9028 return klass->interfaces [0];
9036 if (iface < &klass->interfaces [klass->interface_count]) {
9044 setup_nested_types (MonoClass *klass)
9047 GList *classes, *nested_classes, *l;
9050 if (klass->nested_classes_inited)
9053 if (!klass->type_token)
9054 klass->nested_classes_inited = TRUE;
9056 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9060 guint32 cols [MONO_NESTED_CLASS_SIZE];
9061 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9062 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9063 if (!mono_error_ok (&error)) {
9064 /*FIXME don't swallow the error message*/
9065 mono_error_cleanup (&error);
9067 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9071 classes = g_list_prepend (classes, nclass);
9073 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9076 mono_class_alloc_ext (klass);
9078 nested_classes = NULL;
9079 for (l = classes; l; l = l->next)
9080 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9081 g_list_free (classes);
9083 mono_image_lock (klass->image);
9085 mono_memory_barrier ();
9086 if (!klass->nested_classes_inited) {
9087 klass->ext->nested_classes = nested_classes;
9088 mono_memory_barrier ();
9089 klass->nested_classes_inited = TRUE;
9092 mono_image_unlock (klass->image);
9096 * mono_class_get_nested_types
9097 * @klass: the MonoClass to act on
9099 * This routine is an iterator routine for retrieving the nested types of a class.
9100 * This works only if @klass is non-generic, or a generic type definition.
9102 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9103 * iterate over all of the elements. When no more values are
9104 * available, the return value is NULL.
9106 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9109 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9115 if (!klass->nested_classes_inited)
9116 setup_nested_types (klass);
9119 /* start from the first */
9120 if (klass->ext && klass->ext->nested_classes) {
9121 *iter = klass->ext->nested_classes;
9122 return klass->ext->nested_classes->data;
9124 /* no nested types */
9139 * mono_class_is_delegate
9140 * @klass: the MonoClass to act on
9142 * Returns: true if the MonoClass represents a System.Delegate.
9145 mono_class_is_delegate (MonoClass *klass)
9147 return klass->delegate;
9151 * mono_class_implements_interface
9152 * @klass: The MonoClass to act on
9153 * @interface: The interface to check if @klass implements.
9155 * Returns: true if @klass implements @interface.
9158 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9160 return mono_class_is_assignable_from (iface, klass);
9164 * mono_field_get_name:
9165 * @field: the MonoClassField to act on
9167 * Returns: the name of the field.
9170 mono_field_get_name (MonoClassField *field)
9176 * mono_field_get_type:
9177 * @field: the MonoClassField to act on
9179 * Returns: MonoType of the field.
9182 mono_field_get_type (MonoClassField *field)
9185 MonoType *type = mono_field_get_type_checked (field, &error);
9186 if (!mono_error_ok (&error)) {
9187 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9188 mono_error_cleanup (&error);
9195 * mono_field_get_type_checked:
9196 * @field: the MonoClassField to act on
9197 * @error: used to return any erro found while retrieving @field type
9199 * Returns: MonoType of the field.
9202 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9204 mono_error_init (error);
9206 mono_field_resolve_type (field, error);
9211 * mono_field_get_parent:
9212 * @field: the MonoClassField to act on
9214 * Returns: MonoClass where the field was defined.
9217 mono_field_get_parent (MonoClassField *field)
9219 return field->parent;
9223 * mono_field_get_flags;
9224 * @field: the MonoClassField to act on
9226 * The metadata flags for a field are encoded using the
9227 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9229 * Returns: the flags for the field.
9232 mono_field_get_flags (MonoClassField *field)
9235 return mono_field_resolve_flags (field);
9236 return field->type->attrs;
9240 * mono_field_get_offset;
9241 * @field: the MonoClassField to act on
9243 * Returns: the field offset.
9246 mono_field_get_offset (MonoClassField *field)
9248 return field->offset;
9252 mono_field_get_rva (MonoClassField *field)
9256 MonoClass *klass = field->parent;
9257 MonoFieldDefaultValue *field_def_values;
9259 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9261 if (!klass->ext || !klass->ext->field_def_values) {
9262 mono_class_alloc_ext (klass);
9264 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9266 mono_image_lock (klass->image);
9267 if (!klass->ext->field_def_values)
9268 klass->ext->field_def_values = field_def_values;
9269 mono_image_unlock (klass->image);
9272 field_index = mono_field_get_index (field);
9274 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9275 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9277 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9278 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9281 return klass->ext->field_def_values [field_index].data;
9285 * mono_field_get_data;
9286 * @field: the MonoClassField to act on
9288 * Returns: pointer to the metadata constant value or to the field
9289 * data if it has an RVA flag.
9292 mono_field_get_data (MonoClassField *field)
9294 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9295 MonoTypeEnum def_type;
9297 return mono_class_get_field_default_value (field, &def_type);
9298 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9299 return mono_field_get_rva (field);
9306 * mono_property_get_name:
9307 * @prop: the MonoProperty to act on
9309 * Returns: the name of the property
9312 mono_property_get_name (MonoProperty *prop)
9318 * mono_property_get_set_method
9319 * @prop: the MonoProperty to act on.
9321 * Returns: the setter method of the property (A MonoMethod)
9324 mono_property_get_set_method (MonoProperty *prop)
9330 * mono_property_get_get_method
9331 * @prop: the MonoProperty to act on.
9333 * Returns: the setter method of the property (A MonoMethod)
9336 mono_property_get_get_method (MonoProperty *prop)
9342 * mono_property_get_parent:
9343 * @prop: the MonoProperty to act on.
9345 * Returns: the MonoClass where the property was defined.
9348 mono_property_get_parent (MonoProperty *prop)
9350 return prop->parent;
9354 * mono_property_get_flags:
9355 * @prop: the MonoProperty to act on.
9357 * The metadata flags for a property are encoded using the
9358 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9360 * Returns: the flags for the property.
9363 mono_property_get_flags (MonoProperty *prop)
9369 * mono_event_get_name:
9370 * @event: the MonoEvent to act on
9372 * Returns: the name of the event.
9375 mono_event_get_name (MonoEvent *event)
9381 * mono_event_get_add_method:
9382 * @event: The MonoEvent to act on.
9384 * Returns: the @add' method for the event (a MonoMethod).
9387 mono_event_get_add_method (MonoEvent *event)
9393 * mono_event_get_remove_method:
9394 * @event: The MonoEvent to act on.
9396 * Returns: the @remove method for the event (a MonoMethod).
9399 mono_event_get_remove_method (MonoEvent *event)
9401 return event->remove;
9405 * mono_event_get_raise_method:
9406 * @event: The MonoEvent to act on.
9408 * Returns: the @raise method for the event (a MonoMethod).
9411 mono_event_get_raise_method (MonoEvent *event)
9413 return event->raise;
9417 * mono_event_get_parent:
9418 * @event: the MonoEvent to act on.
9420 * Returns: the MonoClass where the event is defined.
9423 mono_event_get_parent (MonoEvent *event)
9425 return event->parent;
9429 * mono_event_get_flags
9430 * @event: the MonoEvent to act on.
9432 * The metadata flags for an event are encoded using the
9433 * EVENT_* constants. See the tabledefs.h file for details.
9435 * Returns: the flags for the event.
9438 mono_event_get_flags (MonoEvent *event)
9440 return event->attrs;
9444 * mono_class_get_method_from_name:
9445 * @klass: where to look for the method
9446 * @name: name of the method
9447 * @param_count: number of parameters. -1 for any number.
9449 * Obtains a MonoMethod with a given name and number of parameters.
9450 * It only works if there are no multiple signatures for any given method name.
9453 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9455 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9459 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9461 MonoMethod *res = NULL;
9464 /* Search directly in the metadata to avoid calling setup_methods () */
9465 for (i = 0; i < klass->method.count; ++i) {
9466 guint32 cols [MONO_METHOD_SIZE];
9468 MonoMethodSignature *sig;
9470 /* class->method.first points into the methodptr table */
9471 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9473 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9474 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9475 if (param_count == -1) {
9479 sig = mono_method_signature (method);
9480 if (sig && sig->param_count == param_count) {
9491 * mono_class_get_method_from_name_flags:
9492 * @klass: where to look for the method
9493 * @name_space: name of the method
9494 * @param_count: number of parameters. -1 for any number.
9495 * @flags: flags which must be set in the method
9497 * Obtains a MonoMethod with a given name and number of parameters.
9498 * It only works if there are no multiple signatures for any given method name.
9501 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9503 MonoMethod *res = NULL;
9506 mono_class_init (klass);
9508 if (klass->generic_class && !klass->methods) {
9509 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9511 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9515 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9516 mono_class_setup_methods (klass);
9518 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9519 See mono/tests/array_load_exception.il
9520 FIXME we should better report this error to the caller
9522 if (!klass->methods)
9524 for (i = 0; i < klass->method.count; ++i) {
9525 MonoMethod *method = klass->methods [i];
9527 if (method->name[0] == name [0] &&
9528 !strcmp (name, method->name) &&
9529 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9530 ((method->flags & flags) == flags)) {
9537 res = find_method_in_metadata (klass, name, param_count, flags);
9544 * mono_class_set_failure:
9545 * @klass: class in which the failure was detected
9546 * @ex_type: the kind of exception/error to be thrown (later)
9547 * @ex_data: exception data (specific to each type of exception/error)
9549 * Keep a detected failure informations in the class for later processing.
9550 * Note that only the first failure is kept.
9552 * LOCKING: Acquires the loader lock.
9555 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9557 if (klass->exception_type)
9560 mono_loader_lock ();
9561 klass->exception_type = ex_type;
9563 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9564 mono_loader_unlock ();
9570 * mono_class_get_exception_data:
9572 * Return the exception_data property of KLASS.
9574 * LOCKING: Acquires the loader lock.
9577 mono_class_get_exception_data (MonoClass *klass)
9579 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9583 * mono_classes_init:
9585 * Initialize the resources used by this module.
9588 mono_classes_init (void)
9590 mono_mutex_init (&classes_mutex);
9592 mono_counters_register ("Inflated methods size",
9593 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9594 mono_counters_register ("Inflated classes",
9595 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9596 mono_counters_register ("Inflated classes size",
9597 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9598 mono_counters_register ("MonoClass size",
9599 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9600 mono_counters_register ("MonoClassExt size",
9601 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9605 * mono_classes_cleanup:
9607 * Free the resources used by this module.
9610 mono_classes_cleanup (void)
9612 if (global_interface_bitset)
9613 mono_bitset_free (global_interface_bitset);
9614 global_interface_bitset = NULL;
9615 mono_mutex_destroy (&classes_mutex);
9619 * mono_class_get_exception_for_failure:
9620 * @klass: class in which the failure was detected
9622 * Return a constructed MonoException than the caller can then throw
9623 * using mono_raise_exception - or NULL if no failure is present (or
9624 * doesn't result in an exception).
9627 mono_class_get_exception_for_failure (MonoClass *klass)
9629 gpointer exception_data = mono_class_get_exception_data (klass);
9631 switch (klass->exception_type) {
9632 #ifndef DISABLE_SECURITY
9633 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9634 MonoDomain *domain = mono_domain_get ();
9635 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9636 MonoMethod *method = exception_data;
9637 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9638 MonoObject *exc = NULL;
9642 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9643 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9644 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9646 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9647 return (MonoException*) exc;
9650 case MONO_EXCEPTION_TYPE_LOAD: {
9653 char *str = mono_type_get_full_name (klass);
9654 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9655 name = mono_string_new (mono_domain_get (), str);
9657 ex = mono_get_exception_type_load (name, astr);
9661 case MONO_EXCEPTION_MISSING_METHOD: {
9662 char *class_name = exception_data;
9663 char *assembly_name = class_name + strlen (class_name) + 1;
9665 return mono_get_exception_missing_method (class_name, assembly_name);
9667 case MONO_EXCEPTION_MISSING_FIELD: {
9668 char *class_name = exception_data;
9669 char *member_name = class_name + strlen (class_name) + 1;
9671 return mono_get_exception_missing_field (class_name, member_name);
9673 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9674 char *msg_format = exception_data;
9675 char *assembly_name = msg_format + strlen (msg_format) + 1;
9676 char *msg = g_strdup_printf (msg_format, assembly_name);
9679 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9685 case MONO_EXCEPTION_BAD_IMAGE: {
9686 return mono_get_exception_bad_image_format (exception_data);
9689 MonoLoaderError *error;
9692 error = mono_loader_get_last_error ();
9694 ex = mono_loader_error_prepare_exception (error);
9698 /* TODO - handle other class related failures */
9705 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9707 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9708 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9710 if (outer_klass == inner_klass)
9712 inner_klass = inner_klass->nested_in;
9713 } while (inner_klass);
9718 mono_class_get_generic_type_definition (MonoClass *klass)
9720 return klass->generic_class ? klass->generic_class->container_class : klass;
9724 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9726 * Generic instantiations are ignored for all super types of @klass.
9728 * Visibility checks ignoring generic instantiations.
9731 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9734 klass = mono_class_get_generic_type_definition (klass);
9735 parent = mono_class_get_generic_type_definition (parent);
9736 mono_class_setup_supertypes (klass);
9738 for (i = 0; i < klass->idepth; ++i) {
9739 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9745 * Subtype can only access parent members with family protection if the site object
9746 * is subclass of Subtype. For example:
9747 * class A { protected int x; }
9749 * void valid_access () {
9753 * void invalid_access () {
9760 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9762 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9765 if (context_klass == NULL)
9767 /*if access_klass is not member_klass context_klass must be type compat*/
9768 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9774 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9777 if (accessing == accessed)
9779 if (!accessed || !accessing)
9782 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9783 * anywhere so untrusted friends are not safe to access platform's code internals */
9784 if (mono_security_core_clr_enabled ()) {
9785 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9789 mono_assembly_load_friends (accessed);
9790 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9791 MonoAssemblyName *friend = tmp->data;
9792 /* Be conservative with checks */
9795 if (strcmp (accessing->aname.name, friend->name))
9797 if (friend->public_key_token [0]) {
9798 if (!accessing->aname.public_key_token [0])
9800 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9809 * If klass is a generic type or if it is derived from a generic type, return the
9810 * MonoClass of the generic definition
9811 * Returns NULL if not found
9814 get_generic_definition_class (MonoClass *klass)
9817 if (klass->generic_class && klass->generic_class->container_class)
9818 return klass->generic_class->container_class;
9819 klass = klass->parent;
9825 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9828 for (i = 0; i < ginst->type_argc; ++i) {
9829 MonoType *type = ginst->type_argv[i];
9830 switch (type->type) {
9831 case MONO_TYPE_SZARRAY:
9832 if (!can_access_type (access_klass, type->data.klass))
9835 case MONO_TYPE_ARRAY:
9836 if (!can_access_type (access_klass, type->data.array->eklass))
9840 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9843 case MONO_TYPE_CLASS:
9844 case MONO_TYPE_VALUETYPE:
9845 case MONO_TYPE_GENERICINST:
9846 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9854 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9858 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9861 if (access_klass->element_class && !access_klass->enumtype)
9862 access_klass = access_klass->element_class;
9864 if (member_klass->element_class && !member_klass->enumtype)
9865 member_klass = member_klass->element_class;
9867 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9869 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9872 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9875 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9878 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9881 /*Non nested type with nested visibility. We just fail it.*/
9882 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9885 switch (access_level) {
9886 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9887 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9889 case TYPE_ATTRIBUTE_PUBLIC:
9892 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9895 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9896 return is_nesting_type (member_klass, access_klass);
9898 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9899 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9901 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9902 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9904 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9905 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9906 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9908 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9909 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9910 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9915 /* FIXME: check visibility of type, too */
9917 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9919 MonoClass *member_generic_def;
9920 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9923 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9924 access_klass->generic_container) &&
9925 (member_generic_def = get_generic_definition_class (member_klass))) {
9926 MonoClass *access_container;
9928 if (access_klass->generic_container)
9929 access_container = access_klass;
9931 access_container = access_klass->generic_class->container_class;
9933 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9937 /* Partition I 8.5.3.2 */
9938 /* the access level values are the same for fields and methods */
9939 switch (access_level) {
9940 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9941 /* same compilation unit */
9942 return access_klass->image == member_klass->image;
9943 case FIELD_ATTRIBUTE_PRIVATE:
9944 return access_klass == member_klass;
9945 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9946 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9947 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9950 case FIELD_ATTRIBUTE_ASSEMBLY:
9951 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9952 case FIELD_ATTRIBUTE_FAMILY:
9953 if (is_valid_family_access (access_klass, member_klass, context_klass))
9956 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9957 if (is_valid_family_access (access_klass, member_klass, context_klass))
9959 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9960 case FIELD_ATTRIBUTE_PUBLIC:
9967 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9969 /* FIXME: check all overlapping fields */
9970 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9972 MonoClass *nested = method->klass->nested_in;
9974 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9977 nested = nested->nested_in;
9984 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9986 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9988 MonoClass *nested = method->klass->nested_in;
9990 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9993 nested = nested->nested_in;
9998 * with generics calls to explicit interface implementations can be expressed
9999 * directly: the method is private, but we must allow it. This may be opening
10000 * a hole or the generics code should handle this differently.
10001 * Maybe just ensure the interface type is public.
10003 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10009 * mono_method_can_access_method_full:
10010 * @method: The caller method
10011 * @called: The called method
10012 * @context_klass: The static type on stack of the owner @called object used
10014 * This function must be used with instance calls, as they have more strict family accessibility.
10015 * It can be used with static methods, but context_klass should be NULL.
10017 * Returns: TRUE if caller have proper visibility and acessibility to @called
10020 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10022 MonoClass *access_class = method->klass;
10023 MonoClass *member_class = called->klass;
10024 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10026 MonoClass *nested = access_class->nested_in;
10028 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_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;
10052 if (called->is_inflated) {
10053 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10054 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10063 * mono_method_can_access_field_full:
10064 * @method: The caller method
10065 * @field: The accessed field
10066 * @context_klass: The static type on stack of the owner @field object used
10068 * This function must be used with instance fields, as they have more strict family accessibility.
10069 * It can be used with static fields, but context_klass should be NULL.
10071 * Returns: TRUE if caller have proper visibility and acessibility to @field
10074 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10076 MonoClass *access_class = method->klass;
10077 MonoClass *member_class = field->parent;
10078 /* FIXME: check all overlapping fields */
10079 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10081 MonoClass *nested = access_class->nested_in;
10083 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10086 nested = nested->nested_in;
10093 can = can_access_type (access_class, member_class);
10095 MonoClass *nested = access_class->nested_in;
10097 can = can_access_type (nested, member_class);
10100 nested = nested->nested_in;
10110 * mono_class_can_access_class:
10111 * @source_class: The source class
10112 * @target_class: The accessed class
10114 * This function returns is @target_class is visible to @source_class
10116 * Returns: TRUE if source have proper visibility and acessibility to target
10119 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10121 return can_access_type (source_class, target_class);
10125 * mono_type_is_valid_enum_basetype:
10126 * @type: The MonoType to check
10128 * Returns: TRUE if the type can be used as the basetype of an enum
10130 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10131 switch (type->type) {
10134 case MONO_TYPE_BOOLEAN:
10137 case MONO_TYPE_CHAR:
10150 * mono_class_is_valid_enum:
10151 * @klass: An enum class to be validated
10153 * This method verify the required properties an enum should have.
10155 * Returns: TRUE if the informed enum class is valid
10157 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10158 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10159 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10161 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10162 MonoClassField * field;
10163 gpointer iter = NULL;
10164 gboolean found_base_field = FALSE;
10166 g_assert (klass->enumtype);
10167 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10168 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10172 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10175 while ((field = mono_class_get_fields (klass, &iter))) {
10176 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10177 if (found_base_field)
10179 found_base_field = TRUE;
10180 if (!mono_type_is_valid_enum_basetype (field->type))
10185 if (!found_base_field)
10188 if (klass->method.count > 0)
10195 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10197 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10201 * mono_class_setup_interface_id:
10203 * Initializes MonoClass::interface_id if required.
10205 * LOCKING: Acquires the loader lock.
10208 mono_class_setup_interface_id (MonoClass *class)
10210 mono_loader_lock ();
10211 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10212 class->interface_id = mono_get_unique_iid (class);
10213 mono_loader_unlock ();
10217 * mono_class_alloc_ext:
10219 * Allocate klass->ext if not already done.
10222 mono_class_alloc_ext (MonoClass *klass)
10229 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10230 mono_image_lock (klass->image);
10231 mono_memory_barrier ();
10234 class_ext_size += sizeof (MonoClassExt);
10235 mono_image_unlock (klass->image);
10239 * mono_class_setup_interfaces:
10241 * Initialize class->interfaces/interfaces_count.
10242 * LOCKING: Acquires the loader lock.
10243 * This function can fail the type.
10246 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10248 int i, interface_count;
10249 MonoClass **interfaces;
10251 mono_error_init (error);
10253 if (klass->interfaces_inited)
10256 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10257 MonoType *args [1];
10259 /* generic IList, ICollection, IEnumerable */
10260 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10261 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10263 args [0] = &klass->element_class->byval_arg;
10264 interfaces [0] = mono_class_bind_generic_parameters (
10265 mono_defaults.generic_ilist_class, 1, args, FALSE);
10266 if (interface_count > 1)
10267 interfaces [1] = mono_class_bind_generic_parameters (
10268 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10269 } else if (klass->generic_class) {
10270 MonoClass *gklass = klass->generic_class->container_class;
10272 mono_class_setup_interfaces (gklass, error);
10273 if (!mono_error_ok (error)) {
10274 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10278 interface_count = gklass->interface_count;
10279 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10280 for (i = 0; i < interface_count; i++) {
10281 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10282 if (!mono_error_ok (error)) {
10283 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10288 interface_count = 0;
10292 mono_image_lock (klass->image);
10294 if (!klass->interfaces_inited) {
10295 klass->interface_count = interface_count;
10296 klass->interfaces = interfaces;
10298 mono_memory_barrier ();
10300 klass->interfaces_inited = TRUE;
10303 mono_image_unlock (klass->image);
10307 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10309 MonoClass *class = field->parent;
10310 MonoImage *image = class->image;
10311 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10312 int field_idx = field - class->fields;
10314 mono_error_init (error);
10317 MonoClassField *gfield = >d->fields [field_idx];
10318 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10319 if (!mono_error_ok (error)) {
10320 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10321 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10325 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10326 if (!mono_error_ok (error)) {
10327 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10328 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10333 guint32 cols [MONO_FIELD_SIZE];
10334 MonoGenericContainer *container = NULL;
10335 int idx = class->field.first + field_idx;
10337 /*FIXME, in theory we do not lazy load SRE fields*/
10338 g_assert (!image_is_dynamic (image));
10340 if (class->generic_container) {
10341 container = class->generic_container;
10343 container = gtd->generic_container;
10344 g_assert (container);
10347 /* class->field.first and idx points into the fieldptr table */
10348 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10350 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10351 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10352 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10356 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10358 mono_metadata_decode_value (sig, &sig);
10359 /* FIELD signature == 0x06 */
10360 g_assert (*sig == 0x06);
10361 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10363 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10368 mono_field_resolve_flags (MonoClassField *field)
10370 MonoClass *class = field->parent;
10371 MonoImage *image = class->image;
10372 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10373 int field_idx = field - class->fields;
10377 MonoClassField *gfield = >d->fields [field_idx];
10378 return mono_field_get_flags (gfield);
10380 int idx = class->field.first + field_idx;
10382 /*FIXME, in theory we do not lazy load SRE fields*/
10383 g_assert (!image_is_dynamic (image));
10385 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10390 * mono_class_setup_basic_field_info:
10391 * @class: The class to initialize
10393 * Initializes the class->fields array of fields.
10394 * Aquires the loader lock.
10397 mono_class_setup_basic_field_info_locking (MonoClass *class)
10399 mono_loader_lock ();
10400 mono_class_setup_basic_field_info (class);
10401 mono_loader_unlock ();
10405 * mono_class_get_fields_lazy:
10406 * @klass: the MonoClass to act on
10408 * This routine is an iterator routine for retrieving the fields in a class.
10409 * Only minimal information about fields are loaded. Accessors must be used
10410 * for all MonoClassField returned.
10412 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10413 * iterate over all of the elements. When no more values are
10414 * available, the return value is NULL.
10416 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10419 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10421 MonoClassField* field;
10425 mono_class_setup_basic_field_info_locking (klass);
10426 if (!klass->fields)
10428 /* start from the first */
10429 if (klass->field.count) {
10430 return *iter = &klass->fields [0];
10438 if (field < &klass->fields [klass->field.count]) {
10439 return *iter = field;
10445 mono_class_full_name (MonoClass *klass)
10447 return mono_type_full_name (&klass->byval_arg);