2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* Low level lock which protects data structures in this module */
56 static mono_mutex_t classes_mutex;
58 /* Function supplied by the runtime to find classes by name using information from the AOT file */
59 static MonoGetClassFromName get_class_from_name = NULL;
61 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
62 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
63 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
64 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
65 static int generic_array_methods (MonoClass *class);
66 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
68 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
69 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
70 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
71 static guint32 mono_field_resolve_flags (MonoClassField *field);
72 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
73 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
76 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
80 We use gclass recording to allow recursive system f types to be referenced by a parent.
82 Given the following type hierarchy:
84 class TextBox : TextBoxBase<TextBox> {}
85 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
86 class TextInput<T> : Input<T> where T: TextInput<T> {}
89 The runtime tries to load TextBoxBase<>.
90 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
91 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
92 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
94 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
95 at this point, iow, both are registered in the type map and both and a NULL parent. This means
96 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
98 To fix that what we do is to record all generic instantes created while resolving the parent of
99 any generic type definition and, after resolved, correct the parent field if needed.
102 static int record_gclass_instantiation;
103 static GSList *gclass_recorded_list;
104 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
109 mono_locks_acquire (&classes_mutex, ClassesLock);
113 classes_unlock (void)
115 mono_locks_release (&classes_mutex, ClassesLock);
119 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
122 enable_gclass_recording (void)
124 ++record_gclass_instantiation;
128 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
131 disable_gclass_recording (gclass_record_func func, void *user_data)
133 GSList **head = &gclass_recorded_list;
135 g_assert (record_gclass_instantiation > 0);
136 --record_gclass_instantiation;
139 GSList *node = *head;
140 if (func ((MonoClass*)node->data, user_data)) {
142 g_slist_free_1 (node);
148 /* We automatically discard all recorded gclasses when disabled. */
149 if (!record_gclass_instantiation && gclass_recorded_list) {
150 g_slist_free (gclass_recorded_list);
151 gclass_recorded_list = NULL;
156 * mono_class_from_typeref:
157 * @image: a MonoImage
158 * @type_token: a TypeRef token
160 * Creates the MonoClass* structure representing the type defined by
161 * the typeref token valid inside @image.
162 * Returns: the MonoClass* representing the typeref token, NULL ifcould
166 mono_class_from_typeref (MonoImage *image, guint32 type_token)
169 guint32 cols [MONO_TYPEREF_SIZE];
170 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
172 const char *name, *nspace;
176 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, &error)) {
177 mono_trace_warning (MONO_TRACE_TYPE, "Failed to resolve typeref from %s due to '%s'", image->name, mono_error_get_message (&error));
181 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
183 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
184 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
186 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
187 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
188 case MONO_RESOLTION_SCOPE_MODULE:
190 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
191 This is not the observed behavior of existing implementations.
192 The defacto behavior is that it's just a typedef in disguise.
194 /* a typedef in disguise */
195 return mono_class_from_name (image, nspace, name);
196 case MONO_RESOLTION_SCOPE_MODULEREF:
197 module = mono_image_load_module (image, idx);
199 return mono_class_from_name (module, nspace, name);
201 char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
204 human_name = mono_stringify_assembly_name (&image->assembly->aname);
205 mono_loader_set_error_type_load (msg, human_name);
211 case MONO_RESOLTION_SCOPE_TYPEREF: {
212 MonoClass *enclosing;
215 if (idx == mono_metadata_token_index (type_token)) {
216 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token));
220 enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
224 if (enclosing->nested_classes_inited && enclosing->ext) {
225 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
226 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
228 if (strcmp (res->name, name) == 0)
232 /* Don't call mono_class_init as we might've been called by it recursively */
233 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
235 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
236 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
237 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
239 if (strcmp (nname, name) == 0) {
240 MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
241 if (!mono_error_ok (&error)) {
242 mono_loader_set_error_from_mono_error (&error);
243 mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
249 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
252 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
255 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
259 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
260 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
264 if (!image->references || !image->references [idx - 1])
265 mono_assembly_load_reference (image, idx - 1);
266 g_assert (image->references [idx - 1]);
268 /* If the assembly did not load, register this as a type load exception */
269 if (image->references [idx - 1] == REFERENCE_MISSING){
270 MonoAssemblyName aname;
273 mono_assembly_get_assemblyref (image, idx - 1, &aname);
274 human_name = mono_stringify_assembly_name (&aname);
275 mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
281 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
286 mono_image_memdup (MonoImage *image, void *data, guint size)
288 void *res = mono_image_alloc (image, size);
289 memcpy (res, data, size);
293 /* Copy everything mono_metadata_free_array free. */
295 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
298 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
300 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
302 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
304 a = g_memdup (a, sizeof (MonoArrayType));
306 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
308 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
313 /* Copy everything mono_metadata_free_method_signature free. */
315 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
319 sig = mono_metadata_signature_dup_full (image, sig);
321 sig->ret = mono_metadata_type_dup (image, sig->ret);
322 for (i = 0; i < sig->param_count; ++i)
323 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
329 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
331 MonoAssembly *ta = klass->image->assembly;
334 name = mono_stringify_assembly_name (&ta->aname);
335 g_string_append_printf (str, ", %s", name);
340 mono_type_name_check_byref (MonoType *type, GString *str)
343 g_string_append_c (str, '&');
347 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
348 MonoTypeNameFormat format)
352 switch (type->type) {
353 case MONO_TYPE_ARRAY: {
354 int i, rank = type->data.array->rank;
355 MonoTypeNameFormat nested_format;
357 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
358 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
360 mono_type_get_name_recurse (
361 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
362 g_string_append_c (str, '[');
364 g_string_append_c (str, '*');
365 for (i = 1; i < rank; i++)
366 g_string_append_c (str, ',');
367 g_string_append_c (str, ']');
369 mono_type_name_check_byref (type, str);
371 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
372 _mono_type_get_assembly_name (type->data.array->eklass, str);
375 case MONO_TYPE_SZARRAY: {
376 MonoTypeNameFormat nested_format;
378 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
379 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
381 mono_type_get_name_recurse (
382 &type->data.klass->byval_arg, str, FALSE, nested_format);
383 g_string_append (str, "[]");
385 mono_type_name_check_byref (type, str);
387 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
388 _mono_type_get_assembly_name (type->data.klass, str);
391 case MONO_TYPE_PTR: {
392 MonoTypeNameFormat nested_format;
394 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
395 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
397 mono_type_get_name_recurse (
398 type->data.type, str, FALSE, nested_format);
399 g_string_append_c (str, '*');
401 mono_type_name_check_byref (type, str);
403 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
404 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
409 if (!mono_generic_param_info (type->data.generic_param))
410 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
412 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
414 mono_type_name_check_byref (type, str);
418 klass = mono_class_from_mono_type (type);
419 if (klass->nested_in) {
420 mono_type_get_name_recurse (
421 &klass->nested_in->byval_arg, str, TRUE, format);
422 if (format == MONO_TYPE_NAME_FORMAT_IL)
423 g_string_append_c (str, '.');
425 g_string_append_c (str, '+');
426 } else if (*klass->name_space) {
427 g_string_append (str, klass->name_space);
428 g_string_append_c (str, '.');
430 if (format == MONO_TYPE_NAME_FORMAT_IL) {
431 char *s = strchr (klass->name, '`');
432 int len = s ? s - klass->name : strlen (klass->name);
434 g_string_append_len (str, klass->name, len);
436 g_string_append (str, klass->name);
439 if (klass->generic_class) {
440 MonoGenericClass *gclass = klass->generic_class;
441 MonoGenericInst *inst = gclass->context.class_inst;
442 MonoTypeNameFormat nested_format;
445 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
446 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
448 if (format == MONO_TYPE_NAME_FORMAT_IL)
449 g_string_append_c (str, '<');
451 g_string_append_c (str, '[');
452 for (i = 0; i < inst->type_argc; i++) {
453 MonoType *t = inst->type_argv [i];
456 g_string_append_c (str, ',');
457 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
458 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
459 g_string_append_c (str, '[');
460 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
461 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
462 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
463 g_string_append_c (str, ']');
465 if (format == MONO_TYPE_NAME_FORMAT_IL)
466 g_string_append_c (str, '>');
468 g_string_append_c (str, ']');
469 } else if (klass->generic_container &&
470 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
471 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
474 if (format == MONO_TYPE_NAME_FORMAT_IL)
475 g_string_append_c (str, '<');
477 g_string_append_c (str, '[');
478 for (i = 0; i < klass->generic_container->type_argc; i++) {
480 g_string_append_c (str, ',');
481 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
483 if (format == MONO_TYPE_NAME_FORMAT_IL)
484 g_string_append_c (str, '>');
486 g_string_append_c (str, ']');
489 mono_type_name_check_byref (type, str);
491 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
492 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
493 _mono_type_get_assembly_name (klass, str);
499 * mono_type_get_name_full:
501 * @format: the format for the return string.
504 * Returns: the string representation in a number of formats:
506 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
507 * returned in the formatrequired by System.Reflection, this is the
508 * inverse of mono_reflection_parse_type ().
510 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
511 * be used by the IL assembler.
513 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
515 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
518 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
522 result = g_string_new ("");
524 mono_type_get_name_recurse (type, result, FALSE, format);
526 return g_string_free (result, FALSE);
530 * mono_type_get_full_name:
533 * Returns: the string representation for type as required by System.Reflection.
534 * The inverse of mono_reflection_parse_type ().
537 mono_type_get_full_name (MonoClass *class)
539 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
543 * mono_type_get_name:
546 * Returns: the string representation for type as it would be represented in IL code.
549 mono_type_get_name (MonoType *type)
551 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
555 * mono_type_get_underlying_type:
558 * Returns: the MonoType for the underlying integer type if @type
559 * is an enum and byref is false, otherwise the type itself.
562 mono_type_get_underlying_type (MonoType *type)
564 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
565 return mono_class_enum_basetype (type->data.klass);
566 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
567 return mono_class_enum_basetype (type->data.generic_class->container_class);
572 * mono_class_is_open_constructed_type:
575 * Returns TRUE if type represents a generics open constructed type.
576 * IOW, not all type parameters required for the instantiation have
577 * been provided or it's a generic type definition.
579 * An open constructed type means it's a non realizable type. Not to
580 * be mixed up with an abstract type - we can't cast or dispatch to
581 * an open type, for example.
584 mono_class_is_open_constructed_type (MonoType *t)
590 case MONO_TYPE_SZARRAY:
591 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
592 case MONO_TYPE_ARRAY:
593 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
595 return mono_class_is_open_constructed_type (t->data.type);
596 case MONO_TYPE_GENERICINST:
597 return t->data.generic_class->context.class_inst->is_open;
598 case MONO_TYPE_CLASS:
599 case MONO_TYPE_VALUETYPE:
600 return t->data.klass->generic_container != NULL;
607 This is a simple function to catch the most common bad instances of generic types.
608 Specially those that might lead to further failures in the runtime.
611 is_valid_generic_argument (MonoType *type)
613 switch (type->type) {
615 //case MONO_TYPE_TYPEDBYREF:
622 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
624 mono_error_init (error);
626 switch (type->type) {
627 case MONO_TYPE_MVAR: {
629 int num = mono_type_get_generic_param_num (type);
630 MonoGenericInst *inst = context->method_inst;
631 if (!inst || !inst->type_argv)
633 if (num >= inst->type_argc) {
634 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
635 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
636 num, info ? info->name : "", inst->type_argc);
640 if (!is_valid_generic_argument (inst->type_argv [num])) {
641 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
642 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
643 num, info ? info->name : "", inst->type_argv [num]->type);
647 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
648 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
649 * ->byref and ->attrs from @type are propagated to the returned type.
651 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
652 nt->byref = type->byref;
653 nt->attrs = type->attrs;
656 case MONO_TYPE_VAR: {
658 int num = mono_type_get_generic_param_num (type);
659 MonoGenericInst *inst = context->class_inst;
662 if (num >= inst->type_argc) {
663 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
664 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
665 num, info ? info->name : "", inst->type_argc);
668 if (!is_valid_generic_argument (inst->type_argv [num])) {
669 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
670 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
671 num, info ? info->name : "", inst->type_argv [num]->type);
674 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
675 nt->byref = type->byref;
676 nt->attrs = type->attrs;
679 case MONO_TYPE_SZARRAY: {
680 MonoClass *eclass = type->data.klass;
681 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
682 if (!inflated || !mono_error_ok (error))
684 nt = mono_metadata_type_dup (image, type);
685 nt->data.klass = mono_class_from_mono_type (inflated);
686 mono_metadata_free_type (inflated);
689 case MONO_TYPE_ARRAY: {
690 MonoClass *eclass = type->data.array->eklass;
691 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
692 if (!inflated || !mono_error_ok (error))
694 nt = mono_metadata_type_dup (image, type);
695 nt->data.array->eklass = mono_class_from_mono_type (inflated);
696 mono_metadata_free_type (inflated);
699 case MONO_TYPE_GENERICINST: {
700 MonoGenericClass *gclass = type->data.generic_class;
701 MonoGenericInst *inst;
703 if (!gclass->context.class_inst->is_open)
706 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
707 if (!mono_error_ok (error))
709 if (inst != gclass->context.class_inst)
710 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
712 if (gclass == type->data.generic_class)
715 nt = mono_metadata_type_dup (image, type);
716 nt->data.generic_class = gclass;
719 case MONO_TYPE_CLASS:
720 case MONO_TYPE_VALUETYPE: {
721 MonoClass *klass = type->data.klass;
722 MonoGenericContainer *container = klass->generic_container;
723 MonoGenericInst *inst;
724 MonoGenericClass *gclass = NULL;
730 /* We can't use context->class_inst directly, since it can have more elements */
731 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
732 if (!mono_error_ok (error))
734 if (inst == container->context.class_inst)
737 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
739 nt = mono_metadata_type_dup (image, type);
740 nt->type = MONO_TYPE_GENERICINST;
741 nt->data.generic_class = gclass;
751 mono_generic_class_get_context (MonoGenericClass *gclass)
753 return &gclass->context;
757 mono_class_get_context (MonoClass *class)
759 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
763 * mono_class_get_generic_container:
765 * Return the generic container of KLASS which should be a generic type definition.
767 MonoGenericContainer*
768 mono_class_get_generic_container (MonoClass *klass)
770 g_assert (klass->is_generic);
772 return klass->generic_container;
776 * mono_class_get_generic_class:
778 * Return the MonoGenericClass of KLASS, which should be a generic instance.
781 mono_class_get_generic_class (MonoClass *klass)
783 g_assert (klass->is_inflated);
785 return klass->generic_class;
789 * mono_class_inflate_generic_type_with_mempool:
790 * @mempool: a mempool
792 * @context: a generics context
793 * @error: error context
795 * The same as mono_class_inflate_generic_type, but allocates the MonoType
796 * from mempool if it is non-NULL. If it is NULL, the MonoType is
797 * allocated on the heap and is owned by the caller.
798 * The returned type can potentially be the same as TYPE, so it should not be
799 * modified by the caller, and it should be freed using mono_metadata_free_type ().
802 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
804 MonoType *inflated = NULL;
805 mono_error_init (error);
808 inflated = inflate_generic_type (image, type, context, error);
809 if (!mono_error_ok (error))
813 MonoType *shared = mono_metadata_get_shared_type (type);
818 return mono_metadata_type_dup (image, type);
822 mono_stats.inflated_type_count++;
827 * mono_class_inflate_generic_type:
829 * @context: a generics context
831 * If @type is a generic type and @context is not NULL, instantiate it using the
832 * generics context @context.
834 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
835 * on the heap and is owned by the caller. Returns NULL on error.
837 * @deprecated Please use mono_class_inflate_generic_type_checked instead
840 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
844 result = mono_class_inflate_generic_type_checked (type, context, &error);
846 if (!mono_error_ok (&error)) {
847 mono_error_cleanup (&error);
854 * mono_class_inflate_generic_type:
856 * @context: a generics context
857 * @error: error context to use
859 * If @type is a generic type and @context is not NULL, instantiate it using the
860 * generics context @context.
862 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
863 * on the heap and is owned by the caller.
866 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
868 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
872 * mono_class_inflate_generic_type_no_copy:
874 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
878 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
880 MonoType *inflated = NULL;
882 mono_error_init (error);
884 inflated = inflate_generic_type (image, type, context, error);
885 if (!mono_error_ok (error))
892 mono_stats.inflated_type_count++;
897 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
902 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
903 if (!mono_error_ok (error))
906 res = mono_class_from_mono_type (inflated);
907 mono_metadata_free_type (inflated);
912 * mono_class_inflate_generic_class:
914 * Inflate the class GKLASS with CONTEXT.
917 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
922 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
923 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
930 static MonoGenericContext
931 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
933 MonoGenericInst *class_inst = NULL;
934 MonoGenericInst *method_inst = NULL;
935 MonoGenericContext res = { NULL, NULL };
937 mono_error_init (error);
939 if (context->class_inst) {
940 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
941 if (!mono_error_ok (error))
945 if (context->method_inst) {
946 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
947 if (!mono_error_ok (error))
951 res.class_inst = class_inst;
952 res.method_inst = method_inst;
958 * mono_class_inflate_generic_method:
959 * @method: a generic method
960 * @context: a generics context
962 * Instantiate the generic method @method using the generics context @context.
964 * Returns: the new instantiated method
967 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
969 return mono_class_inflate_generic_method_full (method, NULL, context);
973 * mono_class_inflate_generic_method_full:
975 * Instantiate method @method with the generic context @context.
976 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
977 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
980 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
983 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
984 if (!mono_error_ok (&error))
985 /*FIXME do proper error handling - on this case, kill this function. */
986 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
992 * mono_class_inflate_generic_method_full_checked:
993 * Same as mono_class_inflate_generic_method_full but return failure using @error.
996 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
999 MonoMethodInflated *iresult, *cached;
1000 MonoMethodSignature *sig;
1001 MonoGenericContext tmp_context;
1002 gboolean is_mb_open = FALSE;
1004 mono_error_init (error);
1006 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1007 while (method->is_inflated) {
1008 MonoGenericContext *method_context = mono_method_get_context (method);
1009 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1011 tmp_context = inflate_generic_context (method_context, context, error);
1012 if (!mono_error_ok (error))
1014 context = &tmp_context;
1016 if (mono_metadata_generic_context_equal (method_context, context))
1019 method = imethod->declaring;
1023 * A method only needs to be inflated if the context has argument for which it is
1026 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1027 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1030 if (!((method->is_generic && context->method_inst) ||
1031 (method->klass->generic_container && context->class_inst)))
1035 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1036 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1037 * This is opposite to the way non-SRE MethodInfos behave.
1039 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1041 * void Example<T> () {
1045 * In Example, the method token must be encoded as: "void Example<!!0>()"
1047 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1048 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1050 * On the other hand, inflating a non-SRE generic method with its own arguments should
1051 * return itself. For example:
1053 * MethodInfo m = ... //m is a generic method definition
1054 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1057 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1058 * what happens with regular methods.
1060 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1061 * everything should behave like a regular type or method.
1064 is_mb_open = method->is_generic &&
1065 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1066 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1068 iresult = g_new0 (MonoMethodInflated, 1);
1069 iresult->context = *context;
1070 iresult->declaring = method;
1071 iresult->method.method.is_mb_open = is_mb_open;
1073 if (!context->method_inst && method->is_generic)
1074 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1076 if (!context->class_inst) {
1077 g_assert (!iresult->declaring->klass->generic_class);
1078 if (iresult->declaring->klass->generic_container)
1079 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1080 else if (iresult->declaring->klass->generic_class)
1081 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1084 mono_loader_lock ();
1085 cached = mono_method_inflated_lookup (iresult, FALSE);
1087 mono_loader_unlock ();
1089 return (MonoMethod*)cached;
1092 mono_stats.inflated_method_count++;
1094 inflated_methods_size += sizeof (MonoMethodInflated);
1096 sig = mono_method_signature (method);
1098 char *name = mono_type_get_full_name (method->klass);
1099 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1105 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1107 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1110 result = (MonoMethod *) iresult;
1111 result->is_inflated = TRUE;
1112 result->is_generic = FALSE;
1113 result->sre_method = FALSE;
1114 result->signature = NULL;
1115 result->is_mb_open = is_mb_open;
1117 if (!context->method_inst) {
1118 /* Set the generic_container of the result to the generic_container of method */
1119 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1121 if (generic_container) {
1122 result->is_generic = 1;
1123 mono_method_set_generic_container (result, generic_container);
1127 if (!klass_hint || !klass_hint->generic_class ||
1128 klass_hint->generic_class->container_class != method->klass ||
1129 klass_hint->generic_class->context.class_inst != context->class_inst)
1132 if (method->klass->generic_container)
1133 result->klass = klass_hint;
1135 if (!result->klass) {
1136 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1137 if (!mono_error_ok (error))
1140 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1142 mono_metadata_free_type (inflated);
1146 * FIXME: This should hold, but it doesn't:
1148 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1149 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1150 * g_assert (result->is_generic);
1153 * Fixing this here causes other things to break, hence a very
1154 * ugly hack in mini-trampolines.c - see
1155 * is_generic_method_definition().
1158 mono_method_inflated_lookup (iresult, TRUE);
1159 mono_loader_unlock ();
1163 mono_loader_unlock ();
1169 * mono_get_inflated_method:
1171 * Obsolete. We keep it around since it's mentioned in the public API.
1174 mono_get_inflated_method (MonoMethod *method)
1180 * mono_method_get_context_general:
1182 * @uninflated: handle uninflated methods?
1184 * Returns the generic context of a method or NULL if it doesn't have
1185 * one. For an inflated method that's the context stored in the
1186 * method. Otherwise it's in the method's generic container or in the
1187 * generic container of the method's class.
1190 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1192 if (method->is_inflated) {
1193 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1194 return &imethod->context;
1198 if (method->is_generic)
1199 return &(mono_method_get_generic_container (method)->context);
1200 if (method->klass->generic_container)
1201 return &method->klass->generic_container->context;
1206 * mono_method_get_context:
1209 * Returns the generic context for method if it's inflated, otherwise
1213 mono_method_get_context (MonoMethod *method)
1215 return mono_method_get_context_general (method, FALSE);
1219 * mono_method_get_generic_container:
1221 * Returns the generic container of METHOD, which should be a generic method definition.
1222 * Returns NULL if METHOD is not a generic method definition.
1223 * LOCKING: Acquires the loader lock.
1225 MonoGenericContainer*
1226 mono_method_get_generic_container (MonoMethod *method)
1228 MonoGenericContainer *container;
1230 if (!method->is_generic)
1233 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1234 g_assert (container);
1240 * mono_method_set_generic_container:
1242 * Sets the generic container of METHOD to CONTAINER.
1243 * LOCKING: Acquires the loader lock.
1246 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1248 g_assert (method->is_generic);
1250 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1254 * mono_class_find_enum_basetype:
1255 * @class: The enum class
1257 * Determine the basetype of an enum by iterating through its fields. We do this
1258 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1261 mono_class_find_enum_basetype (MonoClass *class)
1263 MonoGenericContainer *container = NULL;
1264 MonoImage *m = class->image;
1265 const int top = class->field.count;
1268 g_assert (class->enumtype);
1270 if (class->generic_container)
1271 container = class->generic_container;
1272 else if (class->generic_class) {
1273 MonoClass *gklass = class->generic_class->container_class;
1275 container = gklass->generic_container;
1276 g_assert (container);
1280 * Fetch all the field information.
1282 for (i = 0; i < top; i++){
1284 guint32 cols [MONO_FIELD_SIZE];
1285 int idx = class->field.first + i;
1288 /* class->field.first and idx points into the fieldptr table */
1289 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1291 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1294 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1297 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1298 mono_metadata_decode_value (sig, &sig);
1299 /* FIELD signature == 0x06 */
1303 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1306 if (class->generic_class) {
1307 //FIXME do we leak here?
1308 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1309 ftype->attrs = cols [MONO_FIELD_FLAGS];
1319 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1322 mono_type_has_exceptions (MonoType *type)
1324 switch (type->type) {
1325 case MONO_TYPE_CLASS:
1326 case MONO_TYPE_VALUETYPE:
1327 case MONO_TYPE_SZARRAY:
1328 return type->data.klass->exception_type;
1329 case MONO_TYPE_ARRAY:
1330 return type->data.array->eklass->exception_type;
1331 case MONO_TYPE_GENERICINST:
1332 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1340 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1344 mono_class_alloc (MonoClass *class, int size)
1346 if (class->generic_class)
1347 return mono_image_set_alloc (class->generic_class->owner, size);
1349 return mono_image_alloc (class->image, size);
1353 mono_class_alloc0 (MonoClass *class, int size)
1357 res = mono_class_alloc (class, size);
1358 memset (res, 0, size);
1362 #define mono_class_new0(class,struct_type, n_structs) \
1363 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1366 * mono_class_setup_basic_field_info:
1367 * @class: The class to initialize
1369 * Initializes the class->fields.
1370 * LOCKING: Assumes the loader lock is held.
1373 mono_class_setup_basic_field_info (MonoClass *class)
1375 MonoClassField *field;
1383 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1384 image = class->image;
1385 top = class->field.count;
1387 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1389 * This happens when a generic instance of an unfinished generic typebuilder
1390 * is used as an element type for creating an array type. We can't initialize
1391 * the fields of this class using the fields of gklass, since gklass is not
1392 * finished yet, fields could be added to it later.
1398 mono_class_setup_basic_field_info (gtd);
1400 top = gtd->field.count;
1401 class->field.first = gtd->field.first;
1402 class->field.count = gtd->field.count;
1405 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1408 * Fetch all the field information.
1410 for (i = 0; i < top; i++){
1411 field = &class->fields [i];
1412 field->parent = class;
1415 field->name = mono_field_get_name (>d->fields [i]);
1417 int idx = class->field.first + i;
1418 /* class->field.first and idx points into the fieldptr table */
1419 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1420 /* The name is needed for fieldrefs */
1421 field->name = mono_metadata_string_heap (image, name_idx);
1427 * mono_class_setup_fields:
1428 * @class: The class to initialize
1430 * Initializes the class->fields.
1431 * LOCKING: Assumes the loader lock is held.
1434 mono_class_setup_fields (MonoClass *class)
1437 MonoImage *m = class->image;
1439 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1440 int i, blittable = TRUE;
1441 guint32 real_size = 0;
1442 guint32 packing_size = 0;
1443 gboolean explicit_size;
1444 MonoClassField *field;
1445 MonoGenericContainer *container = NULL;
1446 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1449 * FIXME: We have a race condition here. It's possible that this function returns
1450 * to its caller with `instance_size` set to `0` instead of the actual size. This
1451 * is not a problem when the function is called recursively on the same class,
1452 * because the size will be initialized by the outer invocation. What follows is a
1453 * description of how it can occur in other cases, too. There it is a problem,
1454 * because it can lead to the GC being asked to allocate an object of size `0`,
1455 * which SGen chokes on. The race condition is triggered infrequently by
1456 * `tests/sgen-suspend.cs`.
1458 * This function is called for a class whenever one of its subclasses is inited.
1459 * For example, it's called for every subclass of Object. What it does is this:
1461 * if (class->setup_fields_called)
1464 * class->instance_size = 0;
1466 * class->setup_fields_called = 1;
1467 * ... critical point
1468 * class->instance_size = actual_instance_size;
1470 * The last two steps are sometimes reversed, but that only changes the way in which
1471 * the race condition works.
1473 * Assume thread A goes through this function and makes it to the critical point.
1474 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1475 * immediately, but `instance_size` is incorrect.
1477 * The other case looks like this:
1479 * if (class->setup_fields_called)
1481 * ... critical point X
1482 * class->instance_size = 0;
1483 * ... critical point Y
1484 * class->instance_size = actual_instance_size;
1486 * class->setup_fields_called = 1;
1488 * Assume thread A goes through the function and makes it to critical point X. Now
1489 * thread B runs through the whole of the function, returning, assuming
1490 * `instance_size` is set. At that point thread A gets to run and makes it to
1491 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1494 if (class->setup_fields_called)
1497 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1499 * This happens when a generic instance of an unfinished generic typebuilder
1500 * is used as an element type for creating an array type. We can't initialize
1501 * the fields of this class using the fields of gklass, since gklass is not
1502 * finished yet, fields could be added to it later.
1507 mono_class_setup_basic_field_info (class);
1508 top = class->field.count;
1511 mono_class_setup_fields (gtd);
1512 if (gtd->exception_type) {
1513 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1518 class->instance_size = 0;
1520 class->sizes.class_size = 0;
1522 if (class->parent) {
1523 /* For generic instances, class->parent might not have been initialized */
1524 mono_class_init (class->parent);
1525 if (!class->parent->size_inited) {
1526 mono_class_setup_fields (class->parent);
1527 if (class->parent->exception_type) {
1528 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1532 class->instance_size += class->parent->instance_size;
1533 class->min_align = class->parent->min_align;
1534 /* we use |= since it may have been set already */
1535 class->has_references |= class->parent->has_references;
1536 blittable = class->parent->blittable;
1538 class->instance_size = sizeof (MonoObject);
1539 class->min_align = 1;
1542 /* We can't really enable 16 bytes alignment until the GC supports it.
1543 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1544 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1545 Bug #506144 is an example of this issue.
1547 if (class->simd_type)
1548 class->min_align = 16;
1550 /* Get the real size */
1551 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1553 if (explicit_size) {
1554 if ((packing_size & 0xfffffff0) != 0) {
1555 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1556 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1559 class->packing_size = packing_size;
1560 real_size += class->instance_size;
1564 if (explicit_size && real_size) {
1565 class->instance_size = MAX (real_size, class->instance_size);
1567 class->blittable = blittable;
1568 mono_memory_barrier ();
1569 class->size_inited = 1;
1570 class->fields_inited = 1;
1571 class->setup_fields_called = 1;
1575 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1578 /* Prevent infinite loops if the class references itself */
1579 class->setup_fields_called = 1;
1581 if (class->generic_container) {
1582 container = class->generic_container;
1584 container = gtd->generic_container;
1585 g_assert (container);
1589 * Fetch all the field information.
1591 for (i = 0; i < top; i++){
1592 int idx = class->field.first + i;
1593 field = &class->fields [i];
1595 field->parent = class;
1598 mono_field_resolve_type (field, &error);
1599 if (!mono_error_ok (&error)) {
1600 /*mono_field_resolve_type already failed class*/
1601 mono_error_cleanup (&error);
1605 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1606 g_assert (field->type);
1609 if (mono_field_is_deleted (field))
1612 MonoClassField *gfield = >d->fields [i];
1613 field->offset = gfield->offset;
1615 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1617 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1618 field->offset = offset;
1620 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1621 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1624 if (field->offset < -1) { /*-1 is used to encode special static fields */
1625 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1631 /* Only do these checks if we still think this type is blittable */
1632 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1633 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1636 MonoClass *field_class = mono_class_from_mono_type (field->type);
1638 mono_class_setup_fields (field_class);
1639 if (field_class->exception_type) {
1640 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1644 if (!field_class || !field_class->blittable)
1649 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1650 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1651 blittable = class->element_class->blittable;
1654 if (mono_type_has_exceptions (field->type)) {
1655 char *class_name = mono_type_get_full_name (class);
1656 char *type_name = mono_type_full_name (field->type);
1658 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1659 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1660 g_free (class_name);
1664 /* The def_value of fields is compute lazily during vtable creation */
1667 if (class == mono_defaults.string_class)
1670 class->blittable = blittable;
1672 if (class->enumtype && !mono_class_enum_basetype (class)) {
1673 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1676 if (explicit_size && real_size) {
1677 class->instance_size = MAX (real_size, class->instance_size);
1680 if (class->exception_type)
1682 mono_class_layout_fields (class);
1684 /*valuetypes can't be neither bigger than 1Mb or empty. */
1685 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1686 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1688 mono_memory_barrier ();
1689 class->fields_inited = 1;
1693 * mono_class_setup_fields_locking:
1694 * @class: The class to initialize
1696 * Initializes the class->fields array of fields.
1697 * Aquires the loader lock.
1700 mono_class_setup_fields_locking (MonoClass *class)
1702 /* This can be checked without locks */
1703 if (class->fields_inited)
1705 mono_loader_lock ();
1706 mono_class_setup_fields (class);
1707 mono_loader_unlock ();
1711 * mono_class_has_references:
1713 * Returns whenever @klass->has_references is set, initializing it if needed.
1714 * Aquires the loader lock.
1717 mono_class_has_references (MonoClass *klass)
1719 if (klass->init_pending) {
1720 /* Be conservative */
1723 mono_class_init (klass);
1725 return klass->has_references;
1730 * mono_type_get_basic_type_from_generic:
1733 * Returns a closed type corresponding to the possibly open type
1737 mono_type_get_basic_type_from_generic (MonoType *type)
1739 /* When we do generic sharing we let type variables stand for reference types. */
1740 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1741 return &mono_defaults.object_class->byval_arg;
1746 * mono_class_layout_fields:
1749 * Compute the placement of fields inside an object or struct, according to
1750 * the layout rules and set the following fields in @class:
1751 * - has_references (if the class contains instance references firled or structs that contain references)
1752 * - has_static_refs (same, but for static fields)
1753 * - instance_size (size of the object in memory)
1754 * - class_size (size needed for the static fields)
1755 * - size_inited (flag set when the instance_size is set)
1757 * LOCKING: this is supposed to be called with the loader lock held.
1760 mono_class_layout_fields (MonoClass *class)
1763 const int top = class->field.count;
1764 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1765 guint32 pass, passes, real_size;
1766 gboolean gc_aware_layout = FALSE;
1767 gboolean has_static_fields = FALSE;
1768 MonoClassField *field;
1771 * When we do generic sharing we need to have layout
1772 * information for open generic classes (either with a generic
1773 * context containing type variables or with a generic
1774 * container), so we don't return in that case anymore.
1778 * Enable GC aware auto layout: in this mode, reference
1779 * fields are grouped together inside objects, increasing collector
1781 * Requires that all classes whose layout is known to native code be annotated
1782 * with [StructLayout (LayoutKind.Sequential)]
1783 * Value types have gc_aware_layout disabled by default, as per
1784 * what the default is for other runtimes.
1786 /* corlib is missing [StructLayout] directives in many places */
1787 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1788 if (!class->valuetype)
1789 gc_aware_layout = TRUE;
1792 /* Compute klass->has_references */
1794 * Process non-static fields first, since static fields might recursively
1795 * refer to the class itself.
1797 for (i = 0; i < top; i++) {
1800 field = &class->fields [i];
1802 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1803 ftype = mono_type_get_underlying_type (field->type);
1804 ftype = mono_type_get_basic_type_from_generic (ftype);
1805 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1806 class->has_references = TRUE;
1810 for (i = 0; i < top; i++) {
1813 field = &class->fields [i];
1815 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1816 ftype = mono_type_get_underlying_type (field->type);
1817 ftype = mono_type_get_basic_type_from_generic (ftype);
1818 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1819 class->has_static_refs = TRUE;
1823 for (i = 0; i < top; i++) {
1826 field = &class->fields [i];
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 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1832 class->has_static_refs = TRUE;
1834 class->has_references = TRUE;
1839 * Compute field layout and total size (not considering static fields)
1843 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1844 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1846 if (gc_aware_layout)
1851 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1854 if (class->parent) {
1855 mono_class_setup_fields (class->parent);
1856 if (class->parent->exception_type) {
1857 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1860 real_size = class->parent->instance_size;
1862 real_size = sizeof (MonoObject);
1865 for (pass = 0; pass < passes; ++pass) {
1866 for (i = 0; i < top; i++){
1871 field = &class->fields [i];
1873 if (mono_field_is_deleted (field))
1875 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1878 ftype = mono_type_get_underlying_type (field->type);
1879 ftype = mono_type_get_basic_type_from_generic (ftype);
1880 if (gc_aware_layout) {
1881 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1890 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1891 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1892 /* This field is a hack inserted by MCS to empty structures */
1896 size = mono_type_size (field->type, &align);
1898 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1899 align = class->packing_size ? MIN (class->packing_size, align): align;
1900 /* if the field has managed references, we need to force-align it
1903 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1904 align = MAX (align, sizeof (gpointer));
1906 class->min_align = MAX (align, class->min_align);
1907 field->offset = real_size;
1909 field->offset += align - 1;
1910 field->offset &= ~(align - 1);
1912 /*TypeBuilders produce all sort of weird things*/
1913 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1914 real_size = field->offset + size;
1917 class->instance_size = MAX (real_size, class->instance_size);
1919 if (class->instance_size & (class->min_align - 1)) {
1920 class->instance_size += class->min_align - 1;
1921 class->instance_size &= ~(class->min_align - 1);
1925 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1927 for (i = 0; i < top; i++) {
1932 field = &class->fields [i];
1935 * There must be info about all the fields in a type if it
1936 * uses explicit layout.
1939 if (mono_field_is_deleted (field))
1941 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1944 size = mono_type_size (field->type, &align);
1945 align = class->packing_size ? MIN (class->packing_size, align): align;
1946 class->min_align = MAX (align, class->min_align);
1949 * When we get here, field->offset is already set by the
1950 * loader (for either runtime fields or fields loaded from metadata).
1951 * The offset is from the start of the object: this works for both
1952 * classes and valuetypes.
1954 field->offset += sizeof (MonoObject);
1955 ftype = mono_type_get_underlying_type (field->type);
1956 ftype = mono_type_get_basic_type_from_generic (ftype);
1957 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1958 if (field->offset % sizeof (gpointer)) {
1959 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1966 real_size = MAX (real_size, size + field->offset);
1968 class->instance_size = MAX (real_size, class->instance_size);
1969 if (class->instance_size & (class->min_align - 1)) {
1970 class->instance_size += class->min_align - 1;
1971 class->instance_size &= ~(class->min_align - 1);
1976 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1978 * For small structs, set min_align to at least the struct size to improve
1979 * performance, and since the JIT memset/memcpy code assumes this and generates
1980 * unaligned accesses otherwise. See #78990 for a testcase.
1982 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1983 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1986 mono_memory_barrier ();
1987 class->size_inited = 1;
1990 * Compute static field layout and size
1992 for (i = 0; i < top; i++){
1996 field = &class->fields [i];
1998 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2000 if (mono_field_is_deleted (field))
2003 if (mono_type_has_exceptions (field->type)) {
2004 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2008 has_static_fields = TRUE;
2010 size = mono_type_size (field->type, &align);
2011 field->offset = class->sizes.class_size;
2012 /*align is always non-zero here*/
2013 field->offset += align - 1;
2014 field->offset &= ~(align - 1);
2015 class->sizes.class_size = field->offset + size;
2018 if (has_static_fields && class->sizes.class_size == 0)
2019 /* Simplify code which depends on class_size != 0 if the class has static fields */
2020 class->sizes.class_size = 8;
2024 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2028 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2029 method->klass = class;
2030 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2031 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2032 method->signature = sig;
2033 method->name = name;
2036 if (name [0] == '.') {
2037 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2039 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2045 * mono_class_setup_methods:
2048 * Initializes the 'methods' array in CLASS.
2049 * Calling this method should be avoided if possible since it allocates a lot
2050 * of long-living MonoMethod structures.
2051 * Methods belonging to an interface are assigned a sequential slot starting
2054 * On failure this function sets class->exception_type
2057 mono_class_setup_methods (MonoClass *class)
2060 MonoMethod **methods;
2065 if (class->generic_class) {
2067 MonoClass *gklass = class->generic_class->container_class;
2069 mono_class_init (gklass);
2070 if (!gklass->exception_type)
2071 mono_class_setup_methods (gklass);
2072 if (gklass->exception_type) {
2073 /* FIXME make exception_data less opaque so it's possible to dup it here */
2074 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2078 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2079 count = gklass->method.count;
2080 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2082 for (i = 0; i < count; i++) {
2083 methods [i] = mono_class_inflate_generic_method_full_checked (
2084 gklass->methods [i], class, mono_class_get_context (class), &error);
2085 if (!mono_error_ok (&error)) {
2086 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2087 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)));
2090 mono_error_cleanup (&error);
2094 } else if (class->rank) {
2096 MonoMethod *amethod;
2097 MonoMethodSignature *sig;
2098 int count_generic = 0, first_generic = 0;
2101 count = 3 + (class->rank > 1? 2: 1);
2103 mono_class_setup_interfaces (class, &error);
2104 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2106 if (class->interface_count) {
2107 count_generic = generic_array_methods (class);
2108 first_generic = count;
2109 count += class->interface_count * count_generic;
2112 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2114 sig = mono_metadata_signature_alloc (class->image, class->rank);
2115 sig->ret = &mono_defaults.void_class->byval_arg;
2116 sig->pinvoke = TRUE;
2117 sig->hasthis = TRUE;
2118 for (i = 0; i < class->rank; ++i)
2119 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2121 amethod = create_array_method (class, ".ctor", sig);
2122 methods [method_num++] = amethod;
2123 if (class->rank > 1) {
2124 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2125 sig->ret = &mono_defaults.void_class->byval_arg;
2126 sig->pinvoke = TRUE;
2127 sig->hasthis = TRUE;
2128 for (i = 0; i < class->rank * 2; ++i)
2129 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2131 amethod = create_array_method (class, ".ctor", sig);
2132 methods [method_num++] = amethod;
2134 /* element Get (idx11, [idx2, ...]) */
2135 sig = mono_metadata_signature_alloc (class->image, class->rank);
2136 sig->ret = &class->element_class->byval_arg;
2137 sig->pinvoke = TRUE;
2138 sig->hasthis = TRUE;
2139 for (i = 0; i < class->rank; ++i)
2140 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2141 amethod = create_array_method (class, "Get", sig);
2142 methods [method_num++] = amethod;
2143 /* element& Address (idx11, [idx2, ...]) */
2144 sig = mono_metadata_signature_alloc (class->image, class->rank);
2145 sig->ret = &class->element_class->this_arg;
2146 sig->pinvoke = TRUE;
2147 sig->hasthis = TRUE;
2148 for (i = 0; i < class->rank; ++i)
2149 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2150 amethod = create_array_method (class, "Address", sig);
2151 methods [method_num++] = amethod;
2152 /* void Set (idx11, [idx2, ...], element) */
2153 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2154 sig->ret = &mono_defaults.void_class->byval_arg;
2155 sig->pinvoke = TRUE;
2156 sig->hasthis = TRUE;
2157 for (i = 0; i < class->rank; ++i)
2158 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2159 sig->params [i] = &class->element_class->byval_arg;
2160 amethod = create_array_method (class, "Set", sig);
2161 methods [method_num++] = amethod;
2163 for (i = 0; i < class->interface_count; i++)
2164 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2166 count = class->method.count;
2167 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2168 for (i = 0; i < count; ++i) {
2169 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2170 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2174 if (MONO_CLASS_IS_INTERFACE (class)) {
2176 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2177 for (i = 0; i < count; ++i) {
2178 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2179 methods [i]->slot = slot++;
2183 mono_image_lock (class->image);
2185 if (!class->methods) {
2186 class->method.count = count;
2188 /* Needed because of the double-checking locking pattern */
2189 mono_memory_barrier ();
2191 class->methods = methods;
2194 mono_image_unlock (class->image);
2198 * mono_class_get_method_by_index:
2200 * Returns class->methods [index], initializing class->methods if neccesary.
2202 * LOCKING: Acquires the loader lock.
2205 mono_class_get_method_by_index (MonoClass *class, int index)
2207 /* Avoid calling setup_methods () if possible */
2208 if (class->generic_class && !class->methods) {
2209 MonoClass *gklass = class->generic_class->container_class;
2212 m = mono_class_inflate_generic_method_full (
2213 gklass->methods [index], class, mono_class_get_context (class));
2215 * If setup_methods () is called later for this class, no duplicates are created,
2216 * since inflate_generic_method guarantees that only one instance of a method
2217 * is created for each context.
2220 mono_class_setup_methods (class);
2221 g_assert (m == class->methods [index]);
2225 mono_class_setup_methods (class);
2226 if (class->exception_type) /*FIXME do proper error handling*/
2228 g_assert (index >= 0 && index < class->method.count);
2229 return class->methods [index];
2234 * mono_class_get_inflated_method:
2236 * Given an inflated class CLASS and a method METHOD which should be a method of
2237 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2240 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2242 MonoClass *gklass = class->generic_class->container_class;
2245 g_assert (method->klass == gklass);
2247 mono_class_setup_methods (gklass);
2248 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2250 for (i = 0; i < gklass->method.count; ++i) {
2251 if (gklass->methods [i] == method) {
2253 return class->methods [i];
2255 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2263 * mono_class_get_vtable_entry:
2265 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2266 * LOCKING: Acquires the loader lock.
2269 mono_class_get_vtable_entry (MonoClass *class, int offset)
2273 if (class->rank == 1) {
2275 * szarrays do not overwrite any methods of Array, so we can avoid
2276 * initializing their vtables in some cases.
2278 mono_class_setup_vtable (class->parent);
2279 if (offset < class->parent->vtable_size)
2280 return class->parent->vtable [offset];
2283 if (class->generic_class) {
2284 MonoClass *gklass = class->generic_class->container_class;
2285 mono_class_setup_vtable (gklass);
2286 m = gklass->vtable [offset];
2288 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2290 mono_class_setup_vtable (class);
2291 if (class->exception_type)
2293 m = class->vtable [offset];
2300 * mono_class_get_vtable_size:
2302 * Return the vtable size for KLASS.
2305 mono_class_get_vtable_size (MonoClass *klass)
2307 mono_class_setup_vtable (klass);
2309 return klass->vtable_size;
2313 * mono_class_setup_properties:
2315 * Initialize class->ext.property and class->ext.properties.
2317 * This method can fail the class.
2320 mono_class_setup_properties (MonoClass *class)
2322 guint startm, endm, i, j;
2323 guint32 cols [MONO_PROPERTY_SIZE];
2324 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2325 MonoProperty *properties;
2329 if (class->ext && class->ext->properties)
2332 if (class->generic_class) {
2333 MonoClass *gklass = class->generic_class->container_class;
2335 mono_class_init (gklass);
2336 mono_class_setup_properties (gklass);
2337 if (gklass->exception_type) {
2338 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2342 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2344 for (i = 0; i < gklass->ext->property.count; i++) {
2345 MonoProperty *prop = &properties [i];
2347 *prop = gklass->ext->properties [i];
2350 prop->get = mono_class_inflate_generic_method_full (
2351 prop->get, class, mono_class_get_context (class));
2353 prop->set = mono_class_inflate_generic_method_full (
2354 prop->set, class, mono_class_get_context (class));
2356 prop->parent = class;
2359 first = gklass->ext->property.first;
2360 count = gklass->ext->property.count;
2362 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2363 count = last - first;
2366 mono_class_setup_methods (class);
2367 if (class->exception_type)
2371 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2372 for (i = first; i < last; ++i) {
2373 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2374 properties [i - first].parent = class;
2375 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2376 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2378 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2379 for (j = startm; j < endm; ++j) {
2382 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2384 if (class->image->uncompressed_metadata)
2385 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2386 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2388 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2390 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2391 case METHOD_SEMANTIC_SETTER:
2392 properties [i - first].set = method;
2394 case METHOD_SEMANTIC_GETTER:
2395 properties [i - first].get = method;
2404 mono_class_alloc_ext (class);
2406 mono_image_lock (class->image);
2408 if (class->ext->properties) {
2409 /* We leak 'properties' which was allocated from the image mempool */
2410 mono_image_unlock (class->image);
2414 class->ext->property.first = first;
2415 class->ext->property.count = count;
2417 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2418 mono_memory_barrier ();
2420 /* Leave this assignment as the last op in the function */
2421 class->ext->properties = properties;
2423 mono_image_unlock (class->image);
2427 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2429 MonoMethod **om, **retval;
2432 for (om = methods, count = 0; *om; ++om, ++count)
2435 retval = g_new0 (MonoMethod*, count + 1);
2437 for (om = methods, count = 0; *om; ++om, ++count)
2438 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2443 /*This method can fail the class.*/
2445 mono_class_setup_events (MonoClass *class)
2448 guint startm, endm, i, j;
2449 guint32 cols [MONO_EVENT_SIZE];
2450 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2454 if (class->ext && class->ext->events)
2457 if (class->generic_class) {
2458 MonoClass *gklass = class->generic_class->container_class;
2459 MonoGenericContext *context;
2461 mono_class_setup_events (gklass);
2462 if (gklass->exception_type) {
2463 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2467 first = gklass->ext->event.first;
2468 count = gklass->ext->event.count;
2470 events = mono_class_new0 (class, MonoEvent, count);
2473 context = mono_class_get_context (class);
2475 for (i = 0; i < count; i++) {
2476 MonoEvent *event = &events [i];
2477 MonoEvent *gevent = &gklass->ext->events [i];
2479 event->parent = class;
2480 event->name = gevent->name;
2481 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2482 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2483 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2484 #ifndef MONO_SMALL_CONFIG
2485 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2487 event->attrs = gevent->attrs;
2490 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2491 count = last - first;
2494 mono_class_setup_methods (class);
2495 if (class->exception_type) {
2496 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2501 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2502 for (i = first; i < last; ++i) {
2503 MonoEvent *event = &events [i - first];
2505 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2506 event->parent = class;
2507 event->attrs = cols [MONO_EVENT_FLAGS];
2508 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2510 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2511 for (j = startm; j < endm; ++j) {
2514 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2516 if (class->image->uncompressed_metadata)
2517 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2518 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2520 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2522 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2523 case METHOD_SEMANTIC_ADD_ON:
2524 event->add = method;
2526 case METHOD_SEMANTIC_REMOVE_ON:
2527 event->remove = method;
2529 case METHOD_SEMANTIC_FIRE:
2530 event->raise = method;
2532 case METHOD_SEMANTIC_OTHER: {
2533 #ifndef MONO_SMALL_CONFIG
2536 if (event->other == NULL) {
2537 event->other = g_new0 (MonoMethod*, 2);
2539 while (event->other [n])
2541 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2543 event->other [n] = method;
2544 /* NULL terminated */
2545 event->other [n + 1] = NULL;
2556 mono_class_alloc_ext (class);
2558 mono_image_lock (class->image);
2560 if (class->ext->events) {
2561 mono_image_unlock (class->image);
2565 class->ext->event.first = first;
2566 class->ext->event.count = count;
2568 /* Flush any pending writes as we do double checked locking on class->ext.events */
2569 mono_memory_barrier ();
2571 /* Leave this assignment as the last op in the function */
2572 class->ext->events = events;
2574 mono_image_unlock (class->image);
2578 * Global pool of interface IDs, represented as a bitset.
2579 * LOCKING: Protected by the classes lock.
2581 static MonoBitSet *global_interface_bitset = NULL;
2584 * mono_unload_interface_ids:
2585 * @bitset: bit set of interface IDs
2587 * When an image is unloaded, the interface IDs associated with
2588 * the image are put back in the global pool of IDs so the numbers
2592 mono_unload_interface_ids (MonoBitSet *bitset)
2595 mono_bitset_sub (global_interface_bitset, bitset);
2600 mono_unload_interface_id (MonoClass *class)
2602 if (global_interface_bitset && class->interface_id) {
2604 mono_bitset_clear (global_interface_bitset, class->interface_id);
2610 * mono_get_unique_iid:
2613 * Assign a unique integer ID to the interface represented by @class.
2614 * The ID will positive and as small as possible.
2615 * LOCKING: Acquires the classes lock.
2616 * Returns: the new ID.
2619 mono_get_unique_iid (MonoClass *class)
2623 g_assert (MONO_CLASS_IS_INTERFACE (class));
2627 if (!global_interface_bitset) {
2628 global_interface_bitset = mono_bitset_new (128, 0);
2631 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2633 int old_size = mono_bitset_size (global_interface_bitset);
2634 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2635 mono_bitset_free (global_interface_bitset);
2636 global_interface_bitset = new_set;
2639 mono_bitset_set (global_interface_bitset, iid);
2640 /* set the bit also in the per-image set */
2641 if (!class->generic_class) {
2642 if (class->image->interface_bitset) {
2643 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2644 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2645 mono_bitset_free (class->image->interface_bitset);
2646 class->image->interface_bitset = new_set;
2649 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2651 mono_bitset_set (class->image->interface_bitset, iid);
2656 #ifndef MONO_SMALL_CONFIG
2657 if (mono_print_vtable) {
2659 char *type_name = mono_type_full_name (&class->byval_arg);
2660 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2661 generic_id = class->generic_class->context.class_inst->id;
2662 g_assert (generic_id != 0);
2666 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2671 g_assert (iid <= 65535);
2676 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2681 mono_class_setup_interfaces (klass, error);
2682 if (!mono_error_ok (error))
2685 for (i = 0; i < klass->interface_count; i++) {
2686 ic = klass->interfaces [i];
2689 *res = g_ptr_array_new ();
2690 g_ptr_array_add (*res, ic);
2691 mono_class_init (ic);
2692 if (ic->exception_type) {
2693 mono_error_set_type_load_class (error, ic, "Error Loading class");
2697 collect_implemented_interfaces_aux (ic, res, error);
2698 if (!mono_error_ok (error))
2704 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2706 GPtrArray *res = NULL;
2708 collect_implemented_interfaces_aux (klass, &res, error);
2709 if (!mono_error_ok (error)) {
2711 g_ptr_array_free (res, TRUE);
2718 compare_interface_ids (const void *p_key, const void *p_element) {
2719 const MonoClass *key = p_key;
2720 const MonoClass *element = *(MonoClass**) p_element;
2722 return (key->interface_id - element->interface_id);
2725 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2727 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2728 MonoClass **result = mono_binary_search (
2730 klass->interfaces_packed,
2731 klass->interface_offsets_count,
2732 sizeof (MonoClass *),
2733 compare_interface_ids);
2735 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2742 * mono_class_interface_offset_with_variance:
2744 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2745 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2747 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2749 * FIXME figure out MS disambiguation rules and fix this function.
2752 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2753 int i = mono_class_interface_offset (klass, itf);
2754 *non_exact_match = FALSE;
2758 if (!mono_class_has_variant_generic_params (itf))
2761 for (i = 0; i < klass->interface_offsets_count; i++) {
2762 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2763 *non_exact_match = TRUE;
2764 return klass->interface_offsets_packed [i];
2772 print_implemented_interfaces (MonoClass *klass) {
2775 GPtrArray *ifaces = NULL;
2777 int ancestor_level = 0;
2779 name = mono_type_get_full_name (klass);
2780 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2783 for (i = 0; i < klass->interface_offsets_count; i++)
2784 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2785 klass->interfaces_packed [i]->interface_id,
2786 klass->interface_offsets_packed [i],
2787 klass->interfaces_packed [i]->method.count,
2788 klass->interfaces_packed [i]->name_space,
2789 klass->interfaces_packed [i]->name );
2790 printf ("Interface flags: ");
2791 for (i = 0; i <= klass->max_interface_id; i++)
2792 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2793 printf ("(%d,T)", i);
2795 printf ("(%d,F)", i);
2797 printf ("Dump interface flags:");
2798 #ifdef COMPRESSED_INTERFACE_BITMAP
2800 const uint8_t* p = klass->interface_bitmap;
2801 i = klass->max_interface_id;
2803 printf (" %d x 00 %02X", p [0], p [1]);
2809 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2810 printf (" %02X", klass->interface_bitmap [i]);
2813 while (klass != NULL) {
2814 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2815 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2816 if (!mono_error_ok (&error)) {
2817 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2818 mono_error_cleanup (&error);
2819 } else if (ifaces) {
2820 for (i = 0; i < ifaces->len; i++) {
2821 MonoClass *ic = g_ptr_array_index (ifaces, i);
2822 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2823 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2825 mono_class_interface_offset (klass, ic),
2830 g_ptr_array_free (ifaces, TRUE);
2833 klass = klass->parent;
2838 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2841 args [0] = &arg0->byval_arg;
2843 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2847 array_class_get_if_rank (MonoClass *class, guint rank)
2849 return rank ? mono_array_class_get (class, rank) : class;
2853 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2855 valuetype_types [0] = eclass;
2856 if (eclass == mono_defaults.int16_class)
2857 valuetype_types [1] = mono_defaults.uint16_class;
2858 else if (eclass == mono_defaults.uint16_class)
2859 valuetype_types [1] = mono_defaults.int16_class;
2860 else if (eclass == mono_defaults.int32_class)
2861 valuetype_types [1] = mono_defaults.uint32_class;
2862 else if (eclass == mono_defaults.uint32_class)
2863 valuetype_types [1] = mono_defaults.int32_class;
2864 else if (eclass == mono_defaults.int64_class)
2865 valuetype_types [1] = mono_defaults.uint64_class;
2866 else if (eclass == mono_defaults.uint64_class)
2867 valuetype_types [1] = mono_defaults.int64_class;
2868 else if (eclass == mono_defaults.byte_class)
2869 valuetype_types [1] = mono_defaults.sbyte_class;
2870 else if (eclass == mono_defaults.sbyte_class)
2871 valuetype_types [1] = mono_defaults.byte_class;
2872 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2873 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2876 /* this won't be needed once bug #325495 is completely fixed
2877 * though we'll need something similar to know which interfaces to allow
2878 * in arrays when they'll be lazyly created
2880 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2881 * MS returns diferrent types based on which instance is called. For example:
2882 * object obj = new byte[10][];
2883 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2884 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2887 * Fixing this should kill quite some code, save some bits and improve compatibility.
2890 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2892 MonoClass *eclass = class->element_class;
2893 static MonoClass* generic_icollection_class = NULL;
2894 static MonoClass* generic_ienumerable_class = NULL;
2895 static MonoClass* generic_ienumerator_class = NULL;
2896 static MonoClass* generic_ireadonlylist_class = NULL;
2897 static MonoClass* generic_ireadonlycollection_class = NULL;
2898 MonoClass *valuetype_types[2] = { NULL, NULL };
2899 MonoClass **interfaces = NULL;
2900 int i, nifaces, interface_count, real_count, original_rank;
2902 gboolean internal_enumerator;
2903 gboolean eclass_is_valuetype;
2905 if (!mono_defaults.generic_ilist_class) {
2909 internal_enumerator = FALSE;
2910 eclass_is_valuetype = FALSE;
2911 original_rank = eclass->rank;
2912 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2913 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2915 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2917 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2918 original_rank = eclass->rank;
2920 eclass = eclass->element_class;
2921 internal_enumerator = TRUE;
2922 *is_enumerator = TRUE;
2930 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2931 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2933 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2935 if (!generic_icollection_class) {
2936 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2937 "System.Collections.Generic", "ICollection`1");
2938 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2939 "System.Collections.Generic", "IEnumerable`1");
2940 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2941 "System.Collections.Generic", "IEnumerator`1");
2942 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2943 "System.Collections.Generic", "IReadOnlyList`1");
2944 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2945 "System.Collections.Generic", "IReadOnlyCollection`1");
2948 mono_class_init (eclass);
2951 * Arrays in 2.0 need to implement a number of generic interfaces
2952 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2953 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2954 * We collect the types needed to build the
2955 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2956 * the generic interfaces needed to implement.
2958 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2959 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2961 if (eclass->valuetype) {
2962 nifaces = generic_ireadonlylist_class ? 5 : 3;
2963 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2965 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2966 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2967 if (internal_enumerator) {
2969 if (valuetype_types [1])
2973 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2974 interfaces [0] = valuetype_types [0];
2975 if (valuetype_types [1])
2976 interfaces [nifaces] = valuetype_types [1];
2978 eclass_is_valuetype = TRUE;
2981 int idepth = eclass->idepth;
2982 if (!internal_enumerator)
2984 nifaces = generic_ireadonlylist_class ? 2 : 3;
2986 // FIXME: This doesn't seem to work/required for generic params
2987 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
2988 mono_class_setup_interface_offsets (eclass);
2990 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2991 /* we add object for interfaces and the supertypes for the other
2992 * types. The last of the supertypes is the element class itself which we
2993 * already created the explicit interfaces for (so we include it for IEnumerator
2994 * and exclude it for arrays).
2996 if (MONO_CLASS_IS_INTERFACE (eclass))
2999 interface_count += idepth;
3000 if (eclass->rank && eclass->element_class->valuetype) {
3001 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3002 if (valuetype_types [1])
3005 /* IList, ICollection, IEnumerable, IReadOnlyList */
3006 interface_count *= nifaces;
3007 real_count = interface_count;
3008 if (internal_enumerator) {
3009 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3010 if (valuetype_types [1])
3013 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3014 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3015 interfaces [0] = mono_defaults.object_class;
3019 for (i = 0; i < idepth; i++) {
3020 mono_class_init (eclass->supertypes [i]);
3021 interfaces [j] = eclass->supertypes [i];
3025 if (all_interfaces) {
3026 for (i = 0; i < eclass->interface_offsets_count; i++) {
3027 interfaces [j] = eclass->interfaces_packed [i];
3031 for (i = 0; i < eclass->interface_count; i++) {
3032 interfaces [j] = eclass->interfaces [i];
3036 if (valuetype_types [1]) {
3037 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3042 /* instantiate the generic interfaces */
3043 for (i = 0; i < interface_count; i += nifaces) {
3044 MonoClass *iface = interfaces [i];
3046 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3047 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3049 if (eclass->valuetype) {
3050 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3051 if (generic_ireadonlylist_class) {
3052 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3053 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3056 if (!generic_ireadonlylist_class)
3057 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3060 if (internal_enumerator) {
3062 /* instantiate IEnumerator<iface> */
3063 for (i = 0; i < interface_count; i++) {
3064 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3066 j = interface_count;
3067 if (!eclass_is_valuetype) {
3068 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3069 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3072 for (i = 0; i < eclass->idepth; i++) {
3073 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3077 for (i = 0; i < eclass->interface_offsets_count; i++) {
3078 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3082 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3084 if (valuetype_types [1])
3085 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3089 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3090 for (i = 0; i < real_count; ++i) {
3091 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3092 g_print ("%s implements %s\n", type_name, name);
3103 find_array_interface (MonoClass *klass, const char *name)
3106 for (i = 0; i < klass->interface_count; ++i) {
3107 if (strcmp (klass->interfaces [i]->name, name) == 0)
3114 * Return the number of virtual methods.
3115 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3116 * Return -1 on failure.
3117 * FIXME It would be nice if this information could be cached somewhere.
3120 count_virtual_methods (MonoClass *class)
3124 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3126 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3127 mono_class_setup_methods (class);
3128 if (class->exception_type)
3131 for (i = 0; i < class->method.count; ++i) {
3132 flags = class->methods [i]->flags;
3133 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3137 for (i = 0; i < class->method.count; ++i) {
3138 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3140 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3148 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3156 m = (l + num_ifaces) / 2;
3157 if (interfaces_full [m] == ic)
3159 if (l == num_ifaces)
3161 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3170 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3172 int i = find_interface (num_ifaces, interfaces_full, ic);
3174 return interface_offsets_full [i];
3179 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3181 int i = find_interface (num_ifaces, interfaces_full, ic);
3185 interface_offsets_full [i] = offset;
3188 for (i = 0; i < num_ifaces; ++i) {
3189 if (interfaces_full [i]) {
3191 if (interfaces_full [i]->interface_id < ic->interface_id)
3194 while (end < num_ifaces && interfaces_full [end]) end++;
3195 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3196 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3198 interfaces_full [i] = ic;
3199 interface_offsets_full [i] = offset;
3205 #ifdef COMPRESSED_INTERFACE_BITMAP
3208 * Compressed interface bitmap design.
3210 * Interface bitmaps take a large amount of memory, because their size is
3211 * linear with the maximum interface id assigned in the process (each interface
3212 * is assigned a unique id as it is loaded). The number of interface classes
3213 * is high because of the many implicit interfaces implemented by arrays (we'll
3214 * need to lazy-load them in the future).
3215 * Most classes implement a very small number of interfaces, so the bitmap is
3216 * sparse. This bitmap needs to be checked by interface casts, so access to the
3217 * needed bit must be fast and doable with few jit instructions.
3219 * The current compression format is as follows:
3220 * *) it is a sequence of one or more two-byte elements
3221 * *) the first byte in the element is the count of empty bitmap bytes
3222 * at the current bitmap position
3223 * *) the second byte in the element is an actual bitmap byte at the current
3226 * As an example, the following compressed bitmap bytes:
3227 * 0x07 0x01 0x00 0x7
3228 * correspond to the following bitmap:
3229 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3231 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3232 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3233 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3237 * mono_compress_bitmap:
3238 * @dest: destination buffer
3239 * @bitmap: bitmap buffer
3240 * @size: size of @bitmap in bytes
3242 * This is a mono internal function.
3243 * The @bitmap data is compressed into a format that is small but
3244 * still searchable in few instructions by the JIT and runtime.
3245 * The compressed data is stored in the buffer pointed to by the
3246 * @dest array. Passing a #NULL value for @dest allows to just compute
3247 * the size of the buffer.
3248 * This compression algorithm assumes the bits set in the bitmap are
3249 * few and far between, like in interface bitmaps.
3250 * Returns: the size of the compressed bitmap in bytes.
3253 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3257 const uint8_t *end = bitmap + size;
3258 while (bitmap < end) {
3259 if (*bitmap || numz == 255) {
3283 * mono_class_interface_match:
3284 * @bitmap: a compressed bitmap buffer
3285 * @id: the index to check in the bitmap
3287 * This is a mono internal function.
3288 * Checks if a bit is set in a compressed interface bitmap. @id must
3289 * be already checked for being smaller than the maximum id encoded in the
3292 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3296 mono_class_interface_match (const uint8_t *bitmap, int id)
3299 id -= bitmap [0] * 8;
3303 return bitmap [1] & (1 << id);
3312 * LOCKING: this is supposed to be called with the loader lock held.
3313 * Return -1 on failure and set exception_type
3316 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3320 int i, j, max_iid, num_ifaces;
3321 MonoClass **interfaces_full = NULL;
3322 int *interface_offsets_full = NULL;
3324 GPtrArray **ifaces_array = NULL;
3325 int interface_offsets_count;
3326 MonoClass **array_interfaces = NULL;
3327 int num_array_interfaces;
3328 int is_enumerator = FALSE;
3330 mono_class_setup_supertypes (class);
3332 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3333 * implicit interfaces have the property that they are assigned the same slot in the
3334 * vtables for compatible interfaces
3336 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3338 /* compute maximum number of slots and maximum interface id */
3340 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3341 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3342 for (j = 0; j < class->idepth; j++) {
3343 k = class->supertypes [j];
3344 num_ifaces += k->interface_count;
3345 for (i = 0; i < k->interface_count; i++) {
3346 ic = k->interfaces [i];
3349 mono_class_init (ic);
3351 if (max_iid < ic->interface_id)
3352 max_iid = ic->interface_id;
3354 ifaces = mono_class_get_implemented_interfaces (k, &error);
3355 if (!mono_error_ok (&error)) {
3356 char *name = mono_type_get_full_name (k);
3357 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)));
3359 mono_error_cleanup (&error);
3364 num_ifaces += ifaces->len;
3365 for (i = 0; i < ifaces->len; ++i) {
3366 ic = g_ptr_array_index (ifaces, i);
3367 if (max_iid < ic->interface_id)
3368 max_iid = ic->interface_id;
3370 ifaces_array [j] = ifaces;
3374 for (i = 0; i < num_array_interfaces; ++i) {
3375 ic = array_interfaces [i];
3376 mono_class_init (ic);
3377 if (max_iid < ic->interface_id)
3378 max_iid = ic->interface_id;
3381 if (MONO_CLASS_IS_INTERFACE (class)) {
3383 if (max_iid < class->interface_id)
3384 max_iid = class->interface_id;
3386 class->max_interface_id = max_iid;
3387 /* compute vtable offset for interfaces */
3388 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3389 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3391 for (i = 0; i < num_ifaces; i++) {
3392 interface_offsets_full [i] = -1;
3395 /* skip the current class */
3396 for (j = 0; j < class->idepth - 1; j++) {
3397 k = class->supertypes [j];
3398 ifaces = ifaces_array [j];
3401 for (i = 0; i < ifaces->len; ++i) {
3403 ic = g_ptr_array_index (ifaces, i);
3405 /*Force the sharing of interface offsets between parent and subtypes.*/
3406 io = mono_class_interface_offset (k, ic);
3408 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3413 g_assert (class == class->supertypes [class->idepth - 1]);
3414 ifaces = ifaces_array [class->idepth - 1];
3416 for (i = 0; i < ifaces->len; ++i) {
3418 ic = g_ptr_array_index (ifaces, i);
3419 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3421 count = count_virtual_methods (ic);
3423 char *name = mono_type_get_full_name (ic);
3424 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3433 if (MONO_CLASS_IS_INTERFACE (class))
3434 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3436 if (num_array_interfaces) {
3437 if (is_enumerator) {
3438 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3439 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3440 g_assert (ienumerator_offset >= 0);
3441 for (i = 0; i < num_array_interfaces; ++i) {
3442 ic = array_interfaces [i];
3443 if (strcmp (ic->name, "IEnumerator`1") == 0)
3444 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3446 g_assert_not_reached ();
3447 /*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);*/
3450 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3451 int ilist_iface_idx = find_array_interface (class, "IList`1");
3452 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3453 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3454 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3455 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3456 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3457 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3458 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3459 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3460 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3461 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3462 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3463 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3464 for (i = 0; i < num_array_interfaces; ++i) {
3466 ic = array_interfaces [i];
3467 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3468 offset = ilist_offset;
3469 else if (strcmp (ic->name, "ICollection`1") == 0)
3470 offset = icollection_offset;
3471 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3472 offset = ienumerable_offset;
3473 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3474 offset = ireadonlylist_offset;
3475 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3476 offset = ireadonlycollection_offset;
3478 g_assert_not_reached ();
3479 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3480 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3485 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3486 if (interface_offsets_full [i] != -1) {
3487 interface_offsets_count ++;
3492 * We might get called multiple times:
3493 * - mono_class_init ()
3494 * - mono_class_setup_vtable ().
3495 * - mono_class_setup_interface_offsets ().
3496 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3497 * means we have to overwrite those when called from other places (#4440).
3499 if (class->interfaces_packed && !overwrite) {
3500 g_assert (class->interface_offsets_count == interface_offsets_count);
3504 class->interface_offsets_count = interface_offsets_count;
3505 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3506 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3507 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3508 #ifdef COMPRESSED_INTERFACE_BITMAP
3509 bitmap = g_malloc0 (bsize);
3511 bitmap = mono_class_alloc0 (class, bsize);
3513 for (i = 0; i < interface_offsets_count; i++) {
3514 int id = interfaces_full [i]->interface_id;
3515 bitmap [id >> 3] |= (1 << (id & 7));
3516 class->interfaces_packed [i] = interfaces_full [i];
3517 class->interface_offsets_packed [i] = interface_offsets_full [i];
3518 /*if (num_array_interfaces)
3519 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]);*/
3521 #ifdef COMPRESSED_INTERFACE_BITMAP
3522 i = mono_compress_bitmap (NULL, bitmap, bsize);
3523 class->interface_bitmap = mono_class_alloc0 (class, i);
3524 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3527 class->interface_bitmap = bitmap;
3532 g_free (interfaces_full);
3533 g_free (interface_offsets_full);
3534 g_free (array_interfaces);
3535 for (i = 0; i < class->idepth; i++) {
3536 ifaces = ifaces_array [i];
3538 g_ptr_array_free (ifaces, TRUE);
3540 g_free (ifaces_array);
3542 //printf ("JUST DONE: ");
3543 //print_implemented_interfaces (class);
3549 * Setup interface offsets for interfaces.
3551 * - class->max_interface_id
3552 * - class->interface_offsets_count
3553 * - class->interfaces_packed
3554 * - class->interface_offsets_packed
3555 * - class->interface_bitmap
3557 * This function can fail @class.
3560 mono_class_setup_interface_offsets (MonoClass *class)
3562 mono_loader_lock ();
3564 setup_interface_offsets (class, 0, FALSE);
3566 mono_loader_unlock ();
3569 /*Checks if @klass has @parent as one of it's parents type gtd
3573 * Bar<T> : Foo<Bar<Bar<T>>>
3577 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3579 klass = mono_class_get_generic_type_definition (klass);
3580 parent = mono_class_get_generic_type_definition (parent);
3581 mono_class_setup_supertypes (klass);
3582 mono_class_setup_supertypes (parent);
3584 return klass->idepth >= parent->idepth &&
3585 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3589 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3591 MonoGenericInst *ginst;
3593 if (!class->generic_class) {
3594 mono_class_setup_vtable_full (class, in_setup);
3595 return class->exception_type == 0;
3598 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3599 if (class->generic_class->container_class->exception_type) {
3600 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3604 ginst = class->generic_class->context.class_inst;
3605 for (i = 0; i < ginst->type_argc; ++i) {
3607 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3609 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3610 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3611 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3613 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3614 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3622 * mono_class_setup_vtable:
3624 * Creates the generic vtable of CLASS.
3625 * Initializes the following fields in MonoClass:
3628 * Plus all the fields initialized by setup_interface_offsets ().
3629 * If there is an error during vtable construction, class->exception_type is set.
3631 * LOCKING: Acquires the loader lock.
3634 mono_class_setup_vtable (MonoClass *class)
3636 mono_class_setup_vtable_full (class, NULL);
3640 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3642 MonoMethod **overrides;
3643 MonoGenericContext *context;
3651 if (MONO_CLASS_IS_INTERFACE (class)) {
3652 /* This sets method->slot for all methods if this is an interface */
3653 mono_class_setup_methods (class);
3657 if (class->exception_type)
3660 if (g_list_find (in_setup, class))
3663 mono_loader_lock ();
3665 if (class->vtable) {
3666 mono_loader_unlock ();
3670 mono_stats.generic_vtable_count ++;
3671 in_setup = g_list_prepend (in_setup, class);
3673 if (class->generic_class) {
3674 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3675 mono_loader_unlock ();
3676 g_list_remove (in_setup, class);
3680 context = mono_class_get_context (class);
3681 type_token = class->generic_class->container_class->type_token;
3683 context = (MonoGenericContext *) class->generic_container;
3684 type_token = class->type_token;
3687 if (image_is_dynamic (class->image)) {
3688 /* Generic instances can have zero method overrides without causing any harm.
3689 * This is true since we don't do layout all over again for them, we simply inflate
3690 * the layout of the parent.
3692 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3694 /* The following call fails if there are missing methods in the type */
3695 /* FIXME it's probably a good idea to avoid this for generic instances. */
3696 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3700 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3702 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3706 mono_loader_unlock ();
3707 g_list_remove (in_setup, class);
3712 #define DEBUG_INTERFACE_VTABLE_CODE 0
3713 #define TRACE_INTERFACE_VTABLE_CODE 0
3714 #define VERIFY_INTERFACE_VTABLE_CODE 0
3715 #define VTABLE_SELECTOR (1)
3717 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3718 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3719 if (!(VTABLE_SELECTOR)) break; \
3723 #define DEBUG_INTERFACE_VTABLE(stmt)
3726 #if TRACE_INTERFACE_VTABLE_CODE
3727 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3728 if (!(VTABLE_SELECTOR)) break; \
3732 #define TRACE_INTERFACE_VTABLE(stmt)
3735 #if VERIFY_INTERFACE_VTABLE_CODE
3736 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3737 if (!(VTABLE_SELECTOR)) break; \
3741 #define VERIFY_INTERFACE_VTABLE(stmt)
3745 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3747 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3751 GString *res = g_string_new ("");
3753 g_string_append_c (res, '(');
3754 for (i = 0; i < sig->param_count; ++i) {
3756 g_string_append_c (res, ',');
3757 mono_type_get_desc (res, sig->params [i], include_namespace);
3759 g_string_append (res, ")=>");
3760 if (sig->ret != NULL) {
3761 mono_type_get_desc (res, sig->ret, include_namespace);
3763 g_string_append (res, "NULL");
3766 g_string_free (res, FALSE);
3770 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3771 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3772 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3773 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3781 is_wcf_hack_disabled (void)
3783 static gboolean disabled;
3784 static gboolean inited = FALSE;
3786 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3793 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) {
3794 MonoMethodSignature *cmsig, *imsig;
3795 if (strcmp (im->name, cm->name) == 0) {
3796 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3797 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3800 if (! slot_is_empty) {
3801 if (require_newslot) {
3802 if (! interface_is_explicitly_implemented_by_class) {
3803 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3806 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3807 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3811 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3814 cmsig = mono_method_signature (cm);
3815 imsig = mono_method_signature (im);
3816 if (!cmsig || !imsig) {
3817 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3821 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3822 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3823 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3824 TRACE_INTERFACE_VTABLE (printf ("]"));
3827 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3828 /* CAS - SecurityAction.InheritanceDemand on interface */
3829 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3830 mono_secman_inheritancedemand_method (cm, im);
3833 if (mono_security_core_clr_enabled ())
3834 mono_security_core_clr_check_override (class, cm, im);
3836 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3837 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3838 char *body_name = mono_method_full_name (cm, TRUE);
3839 char *decl_name = mono_method_full_name (im, TRUE);
3840 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));
3848 MonoClass *ic = im->klass;
3849 const char *ic_name_space = ic->name_space;
3850 const char *ic_name = ic->name;
3853 if (! require_newslot) {
3854 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3857 if (cm->klass->rank == 0) {
3858 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3861 cmsig = mono_method_signature (cm);
3862 imsig = mono_method_signature (im);
3863 if (!cmsig || !imsig) {
3864 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3868 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3869 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3870 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3871 TRACE_INTERFACE_VTABLE (printf ("]"));
3874 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3875 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3878 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3879 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3882 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))) {
3883 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3887 subname = strstr (cm->name, ic_name_space);
3888 if (subname != cm->name) {
3889 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3892 subname += strlen (ic_name_space);
3893 if (subname [0] != '.') {
3894 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3898 if (strstr (subname, ic_name) != subname) {
3899 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3902 subname += strlen (ic_name);
3903 if (subname [0] != '.') {
3904 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3908 if (strcmp (subname, im->name) != 0) {
3909 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3913 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3914 /* CAS - SecurityAction.InheritanceDemand on interface */
3915 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3916 mono_secman_inheritancedemand_method (cm, im);
3919 if (mono_security_core_clr_enabled ())
3920 mono_security_core_clr_check_override (class, cm, im);
3922 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3923 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3924 char *body_name = mono_method_full_name (cm, TRUE);
3925 char *decl_name = mono_method_full_name (im, TRUE);
3926 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));
3936 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3938 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3939 MonoMethod *method = key;
3940 MonoMethod *override = value;
3941 MonoClass *method_class = mono_method_get_class (method);
3942 MonoClass *override_class = mono_method_get_class (override);
3944 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3945 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3946 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3949 print_overrides (GHashTable *override_map, const char *message) {
3951 printf ("Override map \"%s\" START:\n", message);
3952 g_hash_table_foreach (override_map, foreach_override, NULL);
3953 printf ("Override map \"%s\" END.\n", message);
3955 printf ("Override map \"%s\" EMPTY.\n", message);
3959 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3960 char *full_name = mono_type_full_name (&class->byval_arg);
3964 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3966 if (print_interfaces) {
3967 print_implemented_interfaces (class);
3968 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3971 if (class->parent) {
3972 parent_size = class->parent->vtable_size;
3976 for (i = 0; i < size; ++i) {
3977 MonoMethod *cm = vtable [i];
3978 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3979 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3981 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3989 #if VERIFY_INTERFACE_VTABLE_CODE
3991 mono_method_try_get_vtable_index (MonoMethod *method)
3993 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3994 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3995 if (imethod->declaring->is_generic)
3996 return imethod->declaring->slot;
3998 return method->slot;
4002 mono_class_verify_vtable (MonoClass *class)
4005 char *full_name = mono_type_full_name (&class->byval_arg);
4007 printf ("*** Verifying VTable of class '%s' \n", full_name);
4011 if (!class->methods)
4014 for (i = 0; i < class->method.count; ++i) {
4015 MonoMethod *cm = class->methods [i];
4018 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4022 full_name = mono_method_full_name (cm, TRUE);
4024 slot = mono_method_try_get_vtable_index (cm);
4026 if (slot >= class->vtable_size) {
4027 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4031 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4032 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4033 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4034 g_free (other_name);
4037 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4044 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4046 char *method_signature;
4049 for (index = 0; index < onum; ++index) {
4050 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4051 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4053 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4054 type_name = mono_type_full_name (&class->byval_arg);
4055 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4056 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4057 g_free (method_signature);
4059 mono_class_setup_methods (class);
4060 if (class->exception_type) {
4061 char *name = mono_type_get_full_name (class);
4062 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4066 for (index = 0; index < class->method.count; ++index) {
4067 MonoMethod *cm = class->methods [index];
4068 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4070 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4071 g_free (method_signature);
4076 mono_method_get_method_definition (MonoMethod *method)
4078 while (method->is_inflated)
4079 method = ((MonoMethodInflated*)method)->declaring;
4084 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4088 for (i = 0; i < onum; ++i) {
4089 MonoMethod *decl = overrides [i * 2];
4090 MonoMethod *body = overrides [i * 2 + 1];
4092 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4093 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4097 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4098 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4099 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4101 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4105 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4106 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4107 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4109 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4113 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4114 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4118 body = mono_method_get_method_definition (body);
4119 decl = mono_method_get_method_definition (decl);
4121 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4122 char *body_name = mono_method_full_name (body, TRUE);
4123 char *decl_name = mono_method_full_name (decl, TRUE);
4124 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));
4134 mono_class_need_stelemref_method (MonoClass *class)
4136 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4140 * LOCKING: this is supposed to be called with the loader lock held.
4143 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4147 MonoMethod **vtable;
4148 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4149 GPtrArray *ifaces = NULL;
4150 GHashTable *override_map = NULL;
4151 gboolean security_enabled = mono_security_enabled ();
4153 gpointer class_iter;
4154 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4155 int first_non_interface_slot;
4157 GSList *virt_methods = NULL, *l;
4158 int stelemref_slot = 0;
4163 if (overrides && !verify_class_overrides (class, overrides, onum))
4166 ifaces = mono_class_get_implemented_interfaces (class, &error);
4167 if (!mono_error_ok (&error)) {
4168 char *name = mono_type_get_full_name (class);
4169 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)));
4171 mono_error_cleanup (&error);
4173 } else if (ifaces) {
4174 for (i = 0; i < ifaces->len; i++) {
4175 MonoClass *ic = g_ptr_array_index (ifaces, i);
4176 max_vtsize += ic->method.count;
4178 g_ptr_array_free (ifaces, TRUE);
4182 if (class->parent) {
4183 mono_class_init (class->parent);
4184 mono_class_setup_vtable_full (class->parent, in_setup);
4186 if (class->parent->exception_type) {
4187 char *name = mono_type_get_full_name (class->parent);
4188 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4193 max_vtsize += class->parent->vtable_size;
4194 cur_slot = class->parent->vtable_size;
4197 max_vtsize += class->method.count;
4199 /*Array have a slot for stelemref*/
4200 if (mono_class_need_stelemref_method (class)) {
4201 stelemref_slot = cur_slot;
4206 vtable = alloca (sizeof (gpointer) * max_vtsize);
4207 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4209 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4211 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4212 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4215 max_iid = class->max_interface_id;
4216 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4218 /* Optimized version for generic instances */
4219 if (class->generic_class) {
4221 MonoClass *gklass = class->generic_class->container_class;
4224 mono_class_setup_vtable_full (gklass, in_setup);
4225 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4226 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4230 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4231 class->vtable_size = gklass->vtable_size;
4232 for (i = 0; i < gklass->vtable_size; ++i)
4233 if (gklass->vtable [i]) {
4234 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4235 if (!mono_error_ok (&error)) {
4236 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4237 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4239 mono_error_cleanup (&error);
4243 tmp [i]->slot = gklass->vtable [i]->slot;
4245 mono_memory_barrier ();
4246 class->vtable = tmp;
4248 /* Have to set method->slot for abstract virtual methods */
4249 if (class->methods && gklass->methods) {
4250 for (i = 0; i < class->method.count; ++i)
4251 if (class->methods [i]->slot == -1)
4252 class->methods [i]->slot = gklass->methods [i]->slot;
4258 if (class->parent && class->parent->vtable_size) {
4259 MonoClass *parent = class->parent;
4262 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4264 // Also inherit parent interface vtables, just as a starting point.
4265 // This is needed otherwise bug-77127.exe fails when the property methods
4266 // have different names in the iterface and the class, because for child
4267 // classes the ".override" information is not used anymore.
4268 for (i = 0; i < parent->interface_offsets_count; i++) {
4269 MonoClass *parent_interface = parent->interfaces_packed [i];
4270 int interface_offset = mono_class_interface_offset (class, parent_interface);
4271 /*FIXME this is now dead code as this condition will never hold true.
4272 Since interface offsets are inherited then the offset of an interface implemented
4273 by a parent will never be the out of it's vtable boundary.
4275 if (interface_offset >= parent->vtable_size) {
4276 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4279 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4280 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4281 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4282 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4283 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4284 parent_interface_offset + j, parent_interface_offset, j,
4285 interface_offset + j, interface_offset, j));
4292 /*Array have a slot for stelemref*/
4293 if (mono_class_need_stelemref_method (class)) {
4294 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4296 method->slot = stelemref_slot;
4298 g_assert (method->slot == stelemref_slot);
4300 vtable [stelemref_slot] = method;
4303 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4304 /* override interface methods */
4305 for (i = 0; i < onum; i++) {
4306 MonoMethod *decl = overrides [i*2];
4307 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4309 dslot = mono_method_get_vtable_slot (decl);
4311 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4315 dslot += mono_class_interface_offset (class, decl->klass);
4316 vtable [dslot] = overrides [i*2 + 1];
4317 vtable [dslot]->slot = dslot;
4319 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4321 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4323 if (mono_security_core_clr_enabled ())
4324 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4327 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4328 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4331 * Create a list of virtual methods to avoid calling
4332 * mono_class_get_virtual_methods () which is slow because of the metadata
4336 gpointer iter = NULL;
4339 virt_methods = NULL;
4340 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4341 virt_methods = g_slist_prepend (virt_methods, cm);
4343 if (class->exception_type)
4347 // Loop on all implemented interfaces...
4348 for (i = 0; i < class->interface_offsets_count; i++) {
4349 MonoClass *parent = class->parent;
4351 gboolean interface_is_explicitly_implemented_by_class;
4354 ic = class->interfaces_packed [i];
4355 ic_offset = mono_class_interface_offset (class, ic);
4357 mono_class_setup_methods (ic);
4358 if (ic->exception_type)
4361 // Check if this interface is explicitly implemented (instead of just inherited)
4362 if (parent != NULL) {
4363 int implemented_interfaces_index;
4364 interface_is_explicitly_implemented_by_class = FALSE;
4365 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4366 if (ic == class->interfaces [implemented_interfaces_index]) {
4367 interface_is_explicitly_implemented_by_class = TRUE;
4372 interface_is_explicitly_implemented_by_class = TRUE;
4375 // Loop on all interface methods...
4376 for (im_index = 0; im_index < ic->method.count; im_index++) {
4377 MonoMethod *im = ic->methods [im_index];
4378 int im_slot = ic_offset + im->slot;
4379 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4381 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4384 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4386 // If there is an explicit implementation, just use it right away,
4387 // otherwise look for a matching method
4388 if (override_im == NULL) {
4393 // First look for a suitable method among the class methods
4395 for (l = virt_methods; l; l = l->next) {
4397 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)));
4398 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4399 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4400 vtable [im_slot] = cm;
4401 /* Why do we need this? */
4406 TRACE_INTERFACE_VTABLE (printf ("\n"));
4407 if (class->exception_type) /*Might be set by check_interface_method_override*/
4411 // If the slot is still empty, look in all the inherited virtual methods...
4412 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4413 MonoClass *parent = class->parent;
4414 // Reverse order, so that last added methods are preferred
4415 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4416 MonoMethod *cm = parent->vtable [cm_index];
4418 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));
4419 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4420 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4421 vtable [im_slot] = cm;
4422 /* Why do we need this? */
4428 if (class->exception_type) /*Might be set by check_interface_method_override*/
4430 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4434 g_assert (vtable [im_slot] == override_im);
4439 // If the class is not abstract, check that all its interface slots are full.
4440 // The check is done here and not directly at the end of the loop above because
4441 // it can happen (for injected generic array interfaces) that the same slot is
4442 // processed multiple times (those interfaces have overlapping slots), and it
4443 // will not always be the first pass the one that fills the slot.
4444 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4445 for (i = 0; i < class->interface_offsets_count; i++) {
4449 ic = class->interfaces_packed [i];
4450 ic_offset = mono_class_interface_offset (class, ic);
4452 for (im_index = 0; im_index < ic->method.count; im_index++) {
4453 MonoMethod *im = ic->methods [im_index];
4454 int im_slot = ic_offset + im->slot;
4456 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4459 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4460 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4461 if (vtable [im_slot] == NULL) {
4462 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4469 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4471 for (l = virt_methods; l; l = l->next) {
4474 * If the method is REUSE_SLOT, we must check in the
4475 * base class for a method to override.
4477 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4479 for (k = class->parent; k ; k = k->parent) {
4484 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4485 MonoMethodSignature *cmsig, *m1sig;
4487 cmsig = mono_method_signature (cm);
4488 m1sig = mono_method_signature (m1);
4490 if (!cmsig || !m1sig) {
4491 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4495 if (!strcmp(cm->name, m1->name) &&
4496 mono_metadata_signature_equal (cmsig, m1sig)) {
4498 /* CAS - SecurityAction.InheritanceDemand */
4499 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4500 mono_secman_inheritancedemand_method (cm, m1);
4503 if (mono_security_core_clr_enabled ())
4504 mono_security_core_clr_check_override (class, cm, m1);
4506 slot = mono_method_get_vtable_slot (m1);
4510 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4511 char *body_name = mono_method_full_name (cm, TRUE);
4512 char *decl_name = mono_method_full_name (m1, TRUE);
4513 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));
4519 g_assert (cm->slot < max_vtsize);
4521 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4522 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4523 mono_method_full_name (m1, 1), m1,
4524 mono_method_full_name (cm, 1), cm));
4525 g_hash_table_insert (override_map, m1, cm);
4529 if (k->exception_type)
4539 /*Non final newslot methods must be given a non-interface vtable slot*/
4540 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4544 cm->slot = cur_slot++;
4546 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4547 vtable [cm->slot] = cm;
4550 /* override non interface methods */
4551 for (i = 0; i < onum; i++) {
4552 MonoMethod *decl = overrides [i*2];
4553 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4554 g_assert (decl->slot != -1);
4555 vtable [decl->slot] = overrides [i*2 + 1];
4556 overrides [i * 2 + 1]->slot = decl->slot;
4558 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4559 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4560 mono_method_full_name (decl, 1), decl,
4561 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4562 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4564 if (mono_security_core_clr_enabled ())
4565 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4570 * If a method occupies more than one place in the vtable, and it is
4571 * overriden, then change the other occurances too.
4576 for (i = 0; i < max_vtsize; ++i)
4578 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4580 cm = g_hash_table_lookup (override_map, vtable [i]);
4585 g_hash_table_destroy (override_map);
4586 override_map = NULL;
4589 g_slist_free (virt_methods);
4590 virt_methods = NULL;
4592 /* Ensure that all vtable slots are filled with concrete instance methods */
4593 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4594 for (i = 0; i < cur_slot; ++i) {
4595 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4596 char *type_name = mono_type_get_full_name (class);
4597 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4598 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));
4600 g_free (method_name);
4606 if (class->generic_class) {
4607 MonoClass *gklass = class->generic_class->container_class;
4609 mono_class_init (gklass);
4611 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4613 /* Check that the vtable_size value computed in mono_class_init () is correct */
4614 if (class->vtable_size)
4615 g_assert (cur_slot == class->vtable_size);
4616 class->vtable_size = cur_slot;
4619 /* Try to share the vtable with our parent. */
4620 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4621 mono_memory_barrier ();
4622 class->vtable = class->parent->vtable;
4624 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4625 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4626 mono_memory_barrier ();
4627 class->vtable = tmp;
4630 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4631 if (mono_print_vtable) {
4634 print_implemented_interfaces (class);
4636 for (i = 0; i <= max_iid; i++)
4637 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4640 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4641 class->vtable_size, icount);
4643 for (i = 0; i < cur_slot; ++i) {
4648 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4649 mono_method_full_name (cm, TRUE));
4655 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4656 class->name, max_iid);
4658 for (i = 0; i < class->interface_count; i++) {
4659 ic = class->interfaces [i];
4660 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4661 mono_class_interface_offset (class, ic),
4662 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4665 for (k = class->parent; k ; k = k->parent) {
4666 for (i = 0; i < k->interface_count; i++) {
4667 ic = k->interfaces [i];
4668 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4669 mono_class_interface_offset (class, ic),
4670 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4676 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4681 char *name = mono_type_get_full_name (class);
4682 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4685 g_hash_table_destroy (override_map);
4687 g_slist_free (virt_methods);
4692 * mono_method_get_vtable_slot:
4694 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4695 * LOCKING: Acquires the loader lock.
4697 * FIXME Use proper MonoError machinery here.
4700 mono_method_get_vtable_slot (MonoMethod *method)
4702 if (method->slot == -1) {
4703 mono_class_setup_vtable (method->klass);
4704 if (method->klass->exception_type)
4706 if (method->slot == -1) {
4710 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4711 g_assert (method->klass->generic_class);
4712 gklass = method->klass->generic_class->container_class;
4713 mono_class_setup_methods (method->klass);
4714 g_assert (method->klass->methods);
4715 for (i = 0; i < method->klass->method.count; ++i) {
4716 if (method->klass->methods [i] == method)
4719 g_assert (i < method->klass->method.count);
4720 g_assert (gklass->methods);
4721 method->slot = gklass->methods [i]->slot;
4723 g_assert (method->slot != -1);
4725 return method->slot;
4729 * mono_method_get_vtable_index:
4732 * Returns the index into the runtime vtable to access the method or,
4733 * in the case of a virtual generic method, the virtual generic method
4734 * thunk. Returns -1 on failure.
4736 * FIXME Use proper MonoError machinery here.
4739 mono_method_get_vtable_index (MonoMethod *method)
4741 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4742 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4743 if (imethod->declaring->is_generic)
4744 return mono_method_get_vtable_slot (imethod->declaring);
4746 return mono_method_get_vtable_slot (method);
4749 static MonoMethod *default_ghc = NULL;
4750 static MonoMethod *default_finalize = NULL;
4751 static int finalize_slot = -1;
4752 static int ghc_slot = -1;
4755 initialize_object_slots (MonoClass *class)
4760 if (class == mono_defaults.object_class) {
4761 mono_class_setup_vtable (class);
4762 for (i = 0; i < class->vtable_size; ++i) {
4763 MonoMethod *cm = class->vtable [i];
4765 if (!strcmp (cm->name, "GetHashCode"))
4767 else if (!strcmp (cm->name, "Finalize"))
4771 g_assert (ghc_slot > 0);
4772 default_ghc = class->vtable [ghc_slot];
4774 g_assert (finalize_slot > 0);
4775 default_finalize = class->vtable [finalize_slot];
4780 MonoMethod *array_method;
4782 } GenericArrayMethodInfo;
4784 static int generic_array_method_num = 0;
4785 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4788 generic_array_methods (MonoClass *class)
4790 int i, count_generic = 0;
4791 GList *list = NULL, *tmp;
4792 if (generic_array_method_num)
4793 return generic_array_method_num;
4794 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4795 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4796 for (i = 0; i < class->parent->method.count; i++) {
4797 MonoMethod *m = class->parent->methods [i];
4798 if (!strncmp (m->name, "InternalArray__", 15)) {
4800 list = g_list_prepend (list, m);
4803 list = g_list_reverse (list);
4804 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4806 for (tmp = list; tmp; tmp = tmp->next) {
4807 const char *mname, *iname;
4809 MonoMethod *m = tmp->data;
4810 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4811 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4813 generic_array_method_info [i].array_method = m;
4814 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4815 iname = "System.Collections.Generic.ICollection`1.";
4816 mname = m->name + 27;
4817 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4818 iname = "System.Collections.Generic.IEnumerable`1.";
4819 mname = m->name + 27;
4820 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4821 iname = "System.Collections.Generic.IReadOnlyList`1.";
4822 mname = m->name + strlen (ireadonlylist_prefix);
4823 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4824 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4825 mname = m->name + strlen (ireadonlycollection_prefix);
4826 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4827 iname = "System.Collections.Generic.IList`1.";
4828 mname = m->name + 15;
4830 g_assert_not_reached ();
4833 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4834 strcpy (name, iname);
4835 strcpy (name + strlen (iname), mname);
4836 generic_array_method_info [i].name = name;
4839 /*g_print ("array generic methods: %d\n", count_generic);*/
4841 generic_array_method_num = count_generic;
4843 return generic_array_method_num;
4847 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4849 MonoGenericContext tmp_context;
4852 tmp_context.class_inst = NULL;
4853 tmp_context.method_inst = iface->generic_class->context.class_inst;
4854 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4856 for (i = 0; i < generic_array_method_num; i++) {
4857 MonoMethod *m = generic_array_method_info [i].array_method;
4858 MonoMethod *inflated;
4860 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4861 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4866 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4868 int null_length = strlen ("(null)");
4869 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4870 char *s = mono_image_alloc (image, len);
4873 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4874 g_assert (result == len - 1);
4880 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4882 gpointer exception_data = NULL;
4884 switch (error->exception_type) {
4885 case MONO_EXCEPTION_TYPE_LOAD:
4886 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4889 case MONO_EXCEPTION_MISSING_METHOD:
4890 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4893 case MONO_EXCEPTION_MISSING_FIELD: {
4894 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4895 const char *class_name;
4898 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4900 class_name = error->klass->name;
4902 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4905 g_free ((void*)class_name);
4909 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4912 if (error->ref_only)
4913 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.";
4915 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4917 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4921 case MONO_EXCEPTION_BAD_IMAGE:
4922 exception_data = error->msg;
4926 g_assert_not_reached ();
4929 mono_class_set_failure (class, error->exception_type, exception_data);
4934 * @class: the class to initialize
4936 * Compute the instance_size, class_size and other infos that cannot be
4937 * computed at mono_class_get() time. Also compute vtable_size if possible.
4938 * Returns TRUE on success or FALSE if there was a problem in loading
4939 * the type (incorrect assemblies, missing assemblies, methods, etc).
4941 * LOCKING: Acquires the loader lock.
4944 mono_class_init (MonoClass *class)
4947 MonoCachedClassInfo cached_info;
4948 gboolean has_cached_info;
4952 /* Double-checking locking pattern */
4953 if (class->inited || class->exception_type)
4954 return class->exception_type == MONO_EXCEPTION_NONE;
4956 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4958 /* We do everything inside the lock to prevent races */
4959 mono_loader_lock ();
4961 if (class->inited || class->exception_type) {
4962 mono_loader_unlock ();
4963 /* Somebody might have gotten in before us */
4964 return class->exception_type == MONO_EXCEPTION_NONE;
4967 if (class->init_pending) {
4968 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4972 class->init_pending = 1;
4974 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4975 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4980 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4981 MonoClass *element_class = class->element_class;
4982 if (!element_class->inited)
4983 mono_class_init (element_class);
4984 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4985 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4990 /* CAS - SecurityAction.InheritanceDemand */
4991 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4992 mono_secman_inheritancedemand_class (class, class->parent);
4995 mono_stats.initialized_class_count++;
4997 if (class->generic_class && !class->generic_class->is_dynamic) {
4998 MonoClass *gklass = class->generic_class->container_class;
5000 mono_stats.generic_class_count++;
5002 class->method = gklass->method;
5003 class->field = gklass->field;
5005 mono_class_init (gklass);
5006 // FIXME: Why is this needed ?
5007 if (!gklass->exception_type)
5008 mono_class_setup_methods (gklass);
5009 if (gklass->exception_type) {
5010 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5014 if (MONO_CLASS_IS_INTERFACE (class))
5015 class->interface_id = mono_get_unique_iid (class);
5018 if (class->parent && !class->parent->inited)
5019 mono_class_init (class->parent);
5021 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5023 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5024 class->nested_classes_inited = TRUE;
5027 * Computes the size used by the fields, and their locations
5029 if (has_cached_info) {
5030 class->instance_size = cached_info.instance_size;
5031 class->sizes.class_size = cached_info.class_size;
5032 class->packing_size = cached_info.packing_size;
5033 class->min_align = cached_info.min_align;
5034 class->blittable = cached_info.blittable;
5035 class->has_references = cached_info.has_references;
5036 class->has_static_refs = cached_info.has_static_refs;
5037 class->no_special_static_fields = cached_info.no_special_static_fields;
5040 if (!class->size_inited){
5041 mono_class_setup_fields (class);
5042 if (class->exception_type || mono_loader_get_last_error ())
5046 /* Initialize arrays */
5048 class->method.count = 3 + (class->rank > 1? 2: 1);
5050 if (class->interface_count) {
5051 int count_generic = generic_array_methods (class);
5052 class->method.count += class->interface_count * count_generic;
5056 mono_class_setup_supertypes (class);
5059 initialize_object_slots (class);
5062 * Initialize the rest of the data without creating a generic vtable if possible.
5063 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5064 * also avoid computing a generic vtable.
5066 if (has_cached_info) {
5068 class->vtable_size = cached_info.vtable_size;
5069 class->has_finalize = cached_info.has_finalize;
5070 class->has_finalize_inited = TRUE;
5071 class->ghcimpl = cached_info.ghcimpl;
5072 class->has_cctor = cached_info.has_cctor;
5073 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5074 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5075 * The first slot if for array with.
5077 static int szarray_vtable_size[2] = { 0 };
5079 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5082 if (!szarray_vtable_size [slot]) {
5083 mono_class_setup_vtable (class);
5084 szarray_vtable_size [slot] = class->vtable_size;
5086 class->vtable_size = szarray_vtable_size[slot];
5088 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5089 MonoClass *gklass = class->generic_class->container_class;
5091 /* Generic instance case */
5092 class->ghcimpl = gklass->ghcimpl;
5093 class->has_cctor = gklass->has_cctor;
5095 mono_class_setup_vtable (gklass);
5096 if (gklass->exception_type) {
5097 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5101 class->vtable_size = gklass->vtable_size;
5105 /* ghcimpl is not currently used
5107 if (class->parent) {
5108 MonoMethod *cmethod = class->vtable [ghc_slot];
5109 if (cmethod->is_inflated)
5110 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5111 if (cmethod == default_ghc) {
5117 /* C# doesn't allow interfaces to have cctors */
5118 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5119 MonoMethod *cmethod = NULL;
5121 if (class->type_token) {
5122 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5123 /* The find_method function ignores the 'flags' argument */
5124 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5125 class->has_cctor = 1;
5127 mono_class_setup_methods (class);
5128 if (class->exception_type)
5131 for (i = 0; i < class->method.count; ++i) {
5132 MonoMethod *method = class->methods [i];
5133 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5134 (strcmp (".cctor", method->name) == 0)) {
5135 class->has_cctor = 1;
5143 if (class->parent) {
5144 int first_iface_slot;
5145 /* This will compute class->parent->vtable_size for some classes */
5146 mono_class_init (class->parent);
5147 if (class->parent->exception_type) {
5148 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5151 if (mono_loader_get_last_error ())
5153 if (!class->parent->vtable_size) {
5154 /* FIXME: Get rid of this somehow */
5155 mono_class_setup_vtable (class->parent);
5156 if (class->parent->exception_type) {
5157 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5160 if (mono_loader_get_last_error ())
5163 first_iface_slot = class->parent->vtable_size;
5164 if (mono_class_need_stelemref_method (class))
5166 setup_interface_offsets (class, first_iface_slot, TRUE);
5168 setup_interface_offsets (class, 0, TRUE);
5171 if (mono_security_core_clr_enabled ())
5172 mono_security_core_clr_check_inheritance (class);
5174 if (mono_loader_get_last_error ()) {
5175 if (class->exception_type == MONO_EXCEPTION_NONE) {
5176 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5178 mono_loader_clear_error ();
5181 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5182 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5187 /* Because of the double-checking locking pattern */
5188 mono_memory_barrier ();
5190 class->init_pending = 0;
5192 mono_loader_unlock ();
5194 if (mono_debugger_class_init_func)
5195 mono_debugger_class_init_func (class);
5197 return class->exception_type == MONO_EXCEPTION_NONE;
5201 * mono_class_has_finalizer:
5203 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5207 mono_class_has_finalizer (MonoClass *klass)
5209 MonoClass *class = klass;
5210 gboolean has_finalize = FALSE;
5212 if (klass->has_finalize_inited)
5213 return klass->has_finalize;
5215 /* Interfaces and valuetypes are not supposed to have finalizers */
5216 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5217 MonoMethod *cmethod = NULL;
5219 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5220 } else if (class->generic_class) {
5221 MonoClass *gklass = class->generic_class->container_class;
5223 has_finalize = mono_class_has_finalizer (gklass);
5224 } else if (class->parent && class->parent->has_finalize) {
5225 has_finalize = TRUE;
5227 if (class->parent) {
5229 * Can't search in metadata for a method named Finalize, because that
5230 * ignores overrides.
5232 mono_class_setup_vtable (class);
5233 if (class->exception_type || mono_loader_get_last_error ())
5236 cmethod = class->vtable [finalize_slot];
5240 g_assert (class->vtable_size > finalize_slot);
5242 if (class->parent) {
5243 if (cmethod->is_inflated)
5244 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5245 if (cmethod != default_finalize)
5246 has_finalize = TRUE;
5252 mono_image_lock (klass->image);
5254 if (!klass->has_finalize_inited) {
5255 klass->has_finalize = has_finalize ? 1 : 0;
5257 mono_memory_barrier ();
5258 klass->has_finalize_inited = TRUE;
5261 mono_image_unlock (klass->image);
5263 return klass->has_finalize;
5267 mono_is_corlib_image (MonoImage *image)
5269 /* FIXME: allow the dynamic case for our compilers and with full trust */
5270 if (image_is_dynamic (image))
5271 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5273 return image == mono_defaults.corlib;
5277 * LOCKING: this assumes the loader lock is held
5280 mono_class_setup_mono_type (MonoClass *class)
5282 const char *name = class->name;
5283 const char *nspace = class->name_space;
5284 gboolean is_corlib = mono_is_corlib_image (class->image);
5286 class->this_arg.byref = 1;
5287 class->this_arg.data.klass = class;
5288 class->this_arg.type = MONO_TYPE_CLASS;
5289 class->byval_arg.data.klass = class;
5290 class->byval_arg.type = MONO_TYPE_CLASS;
5292 if (is_corlib && !strcmp (nspace, "System")) {
5293 if (!strcmp (name, "ValueType")) {
5295 * do not set the valuetype bit for System.ValueType.
5296 * class->valuetype = 1;
5298 class->blittable = TRUE;
5299 } else if (!strcmp (name, "Enum")) {
5301 * do not set the valuetype bit for System.Enum.
5302 * class->valuetype = 1;
5304 class->valuetype = 0;
5305 class->enumtype = 0;
5306 } else if (!strcmp (name, "Object")) {
5307 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5308 } else if (!strcmp (name, "String")) {
5309 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5310 } else if (!strcmp (name, "TypedReference")) {
5311 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5315 if (class->valuetype) {
5316 int t = MONO_TYPE_VALUETYPE;
5318 if (is_corlib && !strcmp (nspace, "System")) {
5321 if (!strcmp (name, "Boolean")) {
5322 t = MONO_TYPE_BOOLEAN;
5323 } else if (!strcmp(name, "Byte")) {
5325 class->blittable = TRUE;
5329 if (!strcmp (name, "Char")) {
5334 if (!strcmp (name, "Double")) {
5336 class->blittable = TRUE;
5340 if (!strcmp (name, "Int32")) {
5342 class->blittable = TRUE;
5343 } else if (!strcmp(name, "Int16")) {
5345 class->blittable = TRUE;
5346 } else if (!strcmp(name, "Int64")) {
5348 class->blittable = TRUE;
5349 } else if (!strcmp(name, "IntPtr")) {
5351 class->blittable = TRUE;
5355 if (!strcmp (name, "Single")) {
5357 class->blittable = TRUE;
5358 } else if (!strcmp(name, "SByte")) {
5360 class->blittable = TRUE;
5364 if (!strcmp (name, "UInt32")) {
5366 class->blittable = TRUE;
5367 } else if (!strcmp(name, "UInt16")) {
5369 class->blittable = TRUE;
5370 } else if (!strcmp(name, "UInt64")) {
5372 class->blittable = TRUE;
5373 } else if (!strcmp(name, "UIntPtr")) {
5375 class->blittable = TRUE;
5379 if (!strcmp (name, "TypedReference")) {
5380 t = MONO_TYPE_TYPEDBYREF;
5381 class->blittable = TRUE;
5385 if (!strcmp (name, "Void")) {
5393 class->this_arg.type = class->byval_arg.type = t;
5396 if (MONO_CLASS_IS_INTERFACE (class))
5397 class->interface_id = mono_get_unique_iid (class);
5403 * COM initialization is delayed until needed.
5404 * However when a [ComImport] attribute is present on a type it will trigger
5405 * the initialization. This is not a problem unless the BCL being executed
5406 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5409 init_com_from_comimport (MonoClass *class)
5411 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5412 if (mono_security_core_clr_enabled ()) {
5413 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5414 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5415 /* but it can not be made available for application (i.e. user code) since all COM calls
5416 * are considered native calls. In this case we fail with a TypeLoadException (just like
5417 * Silverlight 2 does */
5418 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5423 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5425 #endif /*DISABLE_COM*/
5428 * LOCKING: this assumes the loader lock is held
5431 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5433 gboolean system_namespace;
5434 gboolean is_corlib = mono_is_corlib_image (class->image);
5436 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5438 /* if root of the hierarchy */
5439 if (system_namespace && !strcmp (class->name, "Object")) {
5440 class->parent = NULL;
5441 class->instance_size = sizeof (MonoObject);
5444 if (!strcmp (class->name, "<Module>")) {
5445 class->parent = NULL;
5446 class->instance_size = 0;
5450 if (!MONO_CLASS_IS_INTERFACE (class)) {
5451 /* Imported COM Objects always derive from __ComObject. */
5453 if (MONO_CLASS_IS_IMPORT (class)) {
5454 init_com_from_comimport (class);
5455 if (parent == mono_defaults.object_class)
5456 parent = mono_class_get_com_object_class ();
5460 /* set the parent to something useful and safe, but mark the type as broken */
5461 parent = mono_defaults.object_class;
5462 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5465 class->parent = parent;
5467 if (parent->generic_class && !parent->name) {
5469 * If the parent is a generic instance, we may get
5470 * called before it is fully initialized, especially
5471 * before it has its name.
5476 #ifndef DISABLE_REMOTING
5477 class->marshalbyref = parent->marshalbyref;
5478 class->contextbound = parent->contextbound;
5481 class->delegate = parent->delegate;
5483 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5484 mono_class_set_is_com_object (class);
5486 if (system_namespace) {
5487 #ifndef DISABLE_REMOTING
5488 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5489 class->marshalbyref = 1;
5491 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5492 class->contextbound = 1;
5494 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5495 class->delegate = 1;
5498 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5499 (strcmp (class->parent->name_space, "System") == 0)))
5500 class->valuetype = 1;
5501 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5502 class->valuetype = class->enumtype = 1;
5504 /*class->enumtype = class->parent->enumtype; */
5506 /* initialize com types if COM interfaces are present */
5508 if (MONO_CLASS_IS_IMPORT (class))
5509 init_com_from_comimport (class);
5511 class->parent = NULL;
5517 * mono_class_setup_supertypes:
5520 * Build the data structure needed to make fast type checks work.
5521 * This currently sets two fields in @class:
5522 * - idepth: distance between @class and System.Object in the type
5524 * - supertypes: array of classes: each element has a class in the hierarchy
5525 * starting from @class up to System.Object
5527 * LOCKING: This function is atomic, in case of contention we waste memory.
5530 mono_class_setup_supertypes (MonoClass *class)
5533 MonoClass **supertypes;
5535 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5539 if (class->parent && !class->parent->supertypes)
5540 mono_class_setup_supertypes (class->parent);
5542 class->idepth = class->parent->idepth + 1;
5546 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5547 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5549 if (class->parent) {
5550 supertypes [class->idepth - 1] = class;
5551 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5553 supertypes [0] = class;
5556 mono_atomic_store_release (&class->supertypes, supertypes);
5560 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5562 MonoClass *gtd = (MonoClass*)user_data;
5563 /* Only try to fix generic instances of @gtd */
5564 if (gclass->generic_class->container_class != gtd)
5567 /* Check if the generic instance has no parent. */
5568 if (gtd->parent && !gclass->parent)
5569 mono_generic_class_setup_parent (gclass, gtd);
5575 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5577 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5578 mono_error_set_type_load_class (error, class, msg);
5582 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5584 MonoLoaderError *lerror = mono_loader_get_last_error ();
5587 set_failure_from_loader_error (class, lerror);
5588 mono_error_set_from_loader_error (error);
5592 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5593 mono_error_set_type_load_class (error, class, msg);
5598 * mono_class_create_from_typedef:
5599 * @image: image where the token is valid
5600 * @type_token: typedef token
5601 * @error: used to return any error found while creating the type
5603 * Create the MonoClass* representing the specified type token.
5604 * @type_token must be a TypeDef token.
5606 * FIXME: don't return NULL on failure, just the the caller figure it out.
5609 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5611 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5612 MonoClass *class, *parent = NULL;
5613 guint32 cols [MONO_TYPEDEF_SIZE];
5614 guint32 cols_next [MONO_TYPEDEF_SIZE];
5615 guint tidx = mono_metadata_token_index (type_token);
5616 MonoGenericContext *context = NULL;
5617 const char *name, *nspace;
5619 MonoClass **interfaces;
5620 guint32 field_last, method_last;
5621 guint32 nesting_tokeen;
5623 mono_error_init (error);
5625 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5626 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5627 g_assert (!mono_loader_get_last_error ());
5631 mono_loader_lock ();
5633 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5634 mono_loader_unlock ();
5635 g_assert (!mono_loader_get_last_error ());
5639 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5641 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5642 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5644 class = mono_image_alloc0 (image, sizeof (MonoClass));
5647 class->name_space = nspace;
5649 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5651 class->image = image;
5652 class->type_token = type_token;
5653 class->flags = cols [MONO_TYPEDEF_FLAGS];
5655 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5657 classes_size += sizeof (MonoClass);
5660 * Check whether we're a generic type definition.
5662 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5663 if (class->generic_container) {
5664 class->is_generic = 1;
5665 class->generic_container->owner.klass = class;
5666 context = &class->generic_container->context;
5669 if (class->generic_container)
5670 enable_gclass_recording ();
5672 if (cols [MONO_TYPEDEF_EXTENDS]) {
5674 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5676 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5677 /*WARNING: this must satisfy mono_metadata_type_hash*/
5678 class->this_arg.byref = 1;
5679 class->this_arg.data.klass = class;
5680 class->this_arg.type = MONO_TYPE_CLASS;
5681 class->byval_arg.data.klass = class;
5682 class->byval_arg.type = MONO_TYPE_CLASS;
5684 parent = mono_class_get_full (image, parent_token, context);
5686 if (parent == NULL) {
5687 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5688 goto parent_failure;
5691 for (tmp = parent; tmp; tmp = tmp->parent) {
5693 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5694 goto parent_failure;
5696 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5697 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5698 goto parent_failure;
5703 mono_class_setup_parent (class, parent);
5705 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5706 mono_class_setup_mono_type (class);
5708 if (class->generic_container)
5709 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5712 * This might access class->byval_arg for recursion generated by generic constraints,
5713 * so it has to come after setup_mono_type ().
5715 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5716 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5717 if (!mono_error_ok (error)) {
5718 /*FIXME implement a mono_class_set_failure_from_mono_error */
5719 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5720 mono_loader_unlock ();
5721 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5722 g_assert (!mono_loader_get_last_error ());
5727 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5731 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5735 class->cast_class = class->element_class = class;
5737 if (!class->enumtype) {
5738 if (!mono_metadata_interfaces_from_typedef_full (
5739 image, type_token, &interfaces, &icount, FALSE, context)){
5740 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5741 mono_loader_unlock ();
5742 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5746 class->interfaces = interfaces;
5747 class->interface_count = icount;
5748 class->interfaces_inited = 1;
5751 /*g_print ("Load class %s\n", name);*/
5754 * Compute the field and method lists
5756 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5757 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5759 if (tt->rows > tidx){
5760 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5761 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5762 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5764 field_last = image->tables [MONO_TABLE_FIELD].rows;
5765 method_last = image->tables [MONO_TABLE_METHOD].rows;
5768 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5769 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5770 class->field.count = field_last - class->field.first;
5772 class->field.count = 0;
5774 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5775 class->method.count = method_last - class->method.first;
5777 class->method.count = 0;
5779 /* reserve space to store vector pointer in arrays */
5780 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5781 class->instance_size += 2 * sizeof (gpointer);
5782 g_assert (class->field.count == 0);
5785 if (class->enumtype) {
5786 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5787 if (!enum_basetype) {
5788 /*set it to a default value as the whole runtime can't handle this to be null*/
5789 class->cast_class = class->element_class = mono_defaults.int32_class;
5790 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5791 mono_loader_unlock ();
5792 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5793 g_assert (!mono_loader_get_last_error ());
5796 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5800 * If we're a generic type definition, load the constraints.
5801 * We must do this after the class has been constructed to make certain recursive scenarios
5804 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5805 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5806 mono_loader_unlock ();
5807 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5808 g_assert (!mono_loader_get_last_error ());
5812 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5813 if (!strncmp (name, "Vector", 6))
5814 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");
5817 mono_loader_unlock ();
5819 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5820 g_assert (!mono_loader_get_last_error ());
5825 mono_class_setup_mono_type (class);
5826 mono_loader_unlock ();
5827 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5828 g_assert (!mono_loader_get_last_error ());
5832 /** is klass Nullable<T>? */
5834 mono_class_is_nullable (MonoClass *klass)
5836 return klass->generic_class != NULL &&
5837 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5841 /** if klass is T? return T */
5843 mono_class_get_nullable_param (MonoClass *klass)
5845 g_assert (mono_class_is_nullable (klass));
5846 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5850 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5854 MonoGenericClass *gclass = klass->generic_class;
5856 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5857 if (!mono_error_ok (&error)) {
5858 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5859 klass->parent = mono_defaults.object_class;
5860 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5861 mono_error_cleanup (&error);
5865 mono_class_setup_parent (klass, klass->parent);
5867 if (klass->enumtype) {
5868 klass->cast_class = gtd->cast_class;
5869 klass->element_class = gtd->element_class;
5875 * Create the `MonoClass' for an instantiation of a generic type.
5876 * We only do this if we actually need it.
5879 mono_generic_class_get_class (MonoGenericClass *gclass)
5881 MonoClass *klass, *gklass;
5883 if (gclass->cached_class)
5884 return gclass->cached_class;
5886 mono_loader_lock ();
5887 if (gclass->cached_class) {
5888 mono_loader_unlock ();
5889 return gclass->cached_class;
5892 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5894 gklass = gclass->container_class;
5896 if (record_gclass_instantiation > 0)
5897 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5899 if (gklass->nested_in) {
5900 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5901 klass->nested_in = gklass->nested_in;
5904 klass->name = gklass->name;
5905 klass->name_space = gklass->name_space;
5907 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5909 klass->image = gklass->image;
5910 klass->flags = gklass->flags;
5911 klass->type_token = gklass->type_token;
5912 klass->field.count = gklass->field.count;
5914 klass->is_inflated = 1;
5915 klass->generic_class = gclass;
5917 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5918 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5919 klass->this_arg.byref = TRUE;
5920 klass->enumtype = gklass->enumtype;
5921 klass->valuetype = gklass->valuetype;
5923 klass->cast_class = klass->element_class = klass;
5925 if (mono_class_is_nullable (klass))
5926 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5929 * We're not interested in the nested classes of a generic instance.
5930 * We use the generic type definition to look for nested classes.
5933 mono_generic_class_setup_parent (klass, gklass);
5935 if (gclass->is_dynamic) {
5938 mono_class_setup_supertypes (klass);
5940 if (klass->enumtype) {
5942 * For enums, gklass->fields might not been set, but instance_size etc. is
5943 * already set in mono_reflection_create_internal_class (). For non-enums,
5944 * these will be computed normally in mono_class_layout_fields ().
5946 klass->instance_size = gklass->instance_size;
5947 klass->sizes.class_size = gklass->sizes.class_size;
5948 mono_memory_barrier ();
5949 klass->size_inited = 1;
5953 mono_memory_barrier ();
5954 gclass->cached_class = klass;
5956 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5958 inflated_classes ++;
5959 inflated_classes_size += sizeof (MonoClass);
5961 mono_loader_unlock ();
5967 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5969 MonoClass *klass, **ptr;
5971 MonoGenericContainer *container = mono_generic_param_owner (param);
5975 image = mono_defaults.corlib;
5977 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5978 classes_size += sizeof (MonoClass);
5981 klass->name = pinfo->name;
5983 int n = mono_generic_param_num (param);
5984 klass->name = mono_image_alloc0 (image, 16);
5985 sprintf ((char*)klass->name, "%d", n);
5990 MonoMethod *omethod = container->owner.method;
5991 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5993 MonoClass *oklass = container->owner.klass;
5994 klass->name_space = oklass ? oklass->name_space : "";
5997 klass->name_space = "";
6000 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6004 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6008 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6009 klass->parent = pinfo->constraints [0];
6011 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6012 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6014 klass->parent = mono_defaults.object_class;
6017 if (count - pos > 0) {
6018 klass->interface_count = count - pos;
6019 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6020 klass->interfaces_inited = TRUE;
6021 for (i = pos; i < count; i++)
6022 klass->interfaces [i - pos] = pinfo->constraints [i];
6025 klass->image = image;
6027 klass->inited = TRUE;
6028 klass->cast_class = klass->element_class = klass;
6029 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6031 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6032 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6033 klass->this_arg.byref = TRUE;
6035 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6036 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6038 /*Init these fields to sane values*/
6039 klass->min_align = 1;
6040 klass->instance_size = sizeof (gpointer);
6041 mono_memory_barrier ();
6042 klass->size_inited = 1;
6044 mono_class_setup_supertypes (klass);
6046 if (count - pos > 0) {
6047 mono_class_setup_vtable (klass->parent);
6048 if (klass->parent->exception_type)
6049 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6051 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6057 #define FAST_CACHE_SIZE 16
6060 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6062 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6063 MonoImage *image = param->image;
6068 if (n < FAST_CACHE_SIZE) {
6070 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6072 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6074 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6075 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6080 * LOCKING: Acquires the loader lock.
6083 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6085 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6086 MonoImage *image = param->image;
6091 if (n < FAST_CACHE_SIZE) {
6093 /* No locking needed */
6094 if (!image->mvar_cache_fast)
6095 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6096 image->mvar_cache_fast [n] = klass;
6098 if (!image->var_cache_fast)
6099 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6100 image->var_cache_fast [n] = klass;
6104 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6106 mono_image_lock (image);
6107 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6109 ht = g_hash_table_new (NULL, NULL);
6110 mono_memory_barrier ();
6112 image->mvar_cache_slow = ht;
6114 image->var_cache_slow = ht;
6116 mono_image_unlock (image);
6119 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6123 * LOCKING: Acquires the loader lock.
6126 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6128 MonoGenericContainer *container = mono_generic_param_owner (param);
6129 MonoGenericParamInfo *pinfo;
6132 mono_loader_lock ();
6135 pinfo = mono_generic_param_info (param);
6136 if (pinfo->pklass) {
6137 mono_loader_unlock ();
6138 return pinfo->pklass;
6144 klass = get_anon_gparam_class (param, is_mvar);
6146 mono_loader_unlock ();
6151 if (!image && container) {
6153 MonoMethod *method = container->owner.method;
6154 image = (method && method->klass) ? method->klass->image : NULL;
6156 MonoClass *klass = container->owner.klass;
6157 // FIXME: 'klass' should not be null
6158 // But, monodis creates GenericContainers without associating a owner to it
6159 image = klass ? klass->image : NULL;
6163 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6165 mono_memory_barrier ();
6168 pinfo->pklass = klass;
6170 set_anon_gparam_class (param, is_mvar, klass);
6172 mono_loader_unlock ();
6174 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6175 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6181 mono_ptr_class_get (MonoType *type)
6184 MonoClass *el_class;
6188 el_class = mono_class_from_mono_type (type);
6189 image = el_class->image;
6191 mono_loader_lock ();
6193 if (!image->ptr_cache)
6194 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6196 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6197 mono_loader_unlock ();
6200 result = mono_image_alloc0 (image, sizeof (MonoClass));
6202 classes_size += sizeof (MonoClass);
6204 result->parent = NULL; /* no parent for PTR types */
6205 result->name_space = el_class->name_space;
6206 name = g_strdup_printf ("%s*", el_class->name);
6207 result->name = mono_image_strdup (image, name);
6210 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6212 result->image = el_class->image;
6213 result->inited = TRUE;
6214 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6215 /* Can pointers get boxed? */
6216 result->instance_size = sizeof (gpointer);
6217 result->cast_class = result->element_class = el_class;
6218 result->blittable = TRUE;
6220 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6221 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6222 result->this_arg.byref = TRUE;
6224 mono_class_setup_supertypes (result);
6226 g_hash_table_insert (image->ptr_cache, el_class, result);
6228 mono_loader_unlock ();
6230 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6236 mono_fnptr_class_get (MonoMethodSignature *sig)
6239 static GHashTable *ptr_hash = NULL;
6241 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6243 mono_loader_lock ();
6246 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6248 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6249 mono_loader_unlock ();
6252 result = g_new0 (MonoClass, 1);
6254 result->parent = NULL; /* no parent for PTR types */
6255 result->name_space = "System";
6256 result->name = "MonoFNPtrFakeClass";
6258 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6260 result->image = mono_defaults.corlib; /* need to fix... */
6261 result->inited = TRUE;
6262 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6263 /* Can pointers get boxed? */
6264 result->instance_size = sizeof (gpointer);
6265 result->cast_class = result->element_class = result;
6266 result->blittable = TRUE;
6268 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6269 result->this_arg.data.method = result->byval_arg.data.method = sig;
6270 result->this_arg.byref = TRUE;
6271 result->blittable = TRUE;
6273 mono_class_setup_supertypes (result);
6275 g_hash_table_insert (ptr_hash, sig, result);
6277 mono_loader_unlock ();
6279 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6285 mono_class_from_mono_type (MonoType *type)
6287 switch (type->type) {
6288 case MONO_TYPE_OBJECT:
6289 return type->data.klass? type->data.klass: mono_defaults.object_class;
6290 case MONO_TYPE_VOID:
6291 return type->data.klass? type->data.klass: mono_defaults.void_class;
6292 case MONO_TYPE_BOOLEAN:
6293 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6294 case MONO_TYPE_CHAR:
6295 return type->data.klass? type->data.klass: mono_defaults.char_class;
6297 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6299 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6301 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6303 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6305 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6307 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6309 return type->data.klass? type->data.klass: mono_defaults.int_class;
6311 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6313 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6315 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6317 return type->data.klass? type->data.klass: mono_defaults.single_class;
6319 return type->data.klass? type->data.klass: mono_defaults.double_class;
6320 case MONO_TYPE_STRING:
6321 return type->data.klass? type->data.klass: mono_defaults.string_class;
6322 case MONO_TYPE_TYPEDBYREF:
6323 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6324 case MONO_TYPE_ARRAY:
6325 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6327 return mono_ptr_class_get (type->data.type);
6328 case MONO_TYPE_FNPTR:
6329 return mono_fnptr_class_get (type->data.method);
6330 case MONO_TYPE_SZARRAY:
6331 return mono_array_class_get (type->data.klass, 1);
6332 case MONO_TYPE_CLASS:
6333 case MONO_TYPE_VALUETYPE:
6334 return type->data.klass;
6335 case MONO_TYPE_GENERICINST:
6336 return mono_generic_class_get_class (type->data.generic_class);
6338 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6339 case MONO_TYPE_MVAR:
6340 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6342 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6343 g_assert_not_reached ();
6350 * mono_type_retrieve_from_typespec
6351 * @image: context where the image is created
6352 * @type_spec: typespec token
6353 * @context: the generic context used to evaluate generic instantiations in
6356 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6358 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6360 mono_error_init (error);
6361 *did_inflate = FALSE;
6364 char *name = mono_class_name_from_token (image, type_spec);
6365 char *assembly = mono_assembly_name_from_token (image, type_spec);
6366 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6370 if (context && (context->class_inst || context->method_inst)) {
6371 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6373 if (!mono_error_ok (error))
6378 *did_inflate = TRUE;
6385 * mono_class_create_from_typespec
6386 * @image: context where the image is created
6387 * @type_spec: typespec token
6388 * @context: the generic context used to evaluate generic instantiations in
6391 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6394 gboolean inflated = FALSE;
6395 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6396 if (!mono_error_ok (error))
6398 ret = mono_class_from_mono_type (t);
6400 mono_metadata_free_type (t);
6405 * mono_bounded_array_class_get:
6406 * @element_class: element class
6407 * @rank: the dimension of the array class
6408 * @bounded: whenever the array has non-zero bounds
6410 * Returns: a class object describing the array with element type @element_type and
6414 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6418 MonoClass *parent = NULL;
6419 GSList *list, *rootlist = NULL;
6422 gboolean corlib_type = FALSE;
6424 g_assert (rank <= 255);
6427 /* bounded only matters for one-dimensional arrays */
6430 image = eclass->image;
6432 if (rank == 1 && !bounded) {
6434 * This case is very frequent not just during compilation because of calls
6435 * from mono_class_from_mono_type (), mono_array_new (),
6436 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6438 mono_mutex_lock (&image->szarray_cache_lock);
6439 if (!image->szarray_cache)
6440 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6441 class = g_hash_table_lookup (image->szarray_cache, eclass);
6442 mono_mutex_unlock (&image->szarray_cache_lock);
6446 mono_loader_lock ();
6448 mono_loader_lock ();
6450 if (!image->array_cache)
6451 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6453 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6454 for (; list; list = list->next) {
6456 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6457 mono_loader_unlock ();
6464 /* for the building corlib use System.Array from it */
6465 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6466 parent = mono_class_from_name (image, "System", "Array");
6469 parent = mono_defaults.array_class;
6470 if (!parent->inited)
6471 mono_class_init (parent);
6474 class = mono_image_alloc0 (image, sizeof (MonoClass));
6476 class->image = image;
6477 class->name_space = eclass->name_space;
6478 nsize = strlen (eclass->name);
6479 name = g_malloc (nsize + 2 + rank + 1);
6480 memcpy (name, eclass->name, nsize);
6483 memset (name + nsize + 1, ',', rank - 1);
6485 name [nsize + rank] = '*';
6486 name [nsize + rank + bounded] = ']';
6487 name [nsize + rank + bounded + 1] = 0;
6488 class->name = mono_image_strdup (image, name);
6491 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6493 classes_size += sizeof (MonoClass);
6495 class->type_token = 0;
6496 /* all arrays are marked serializable and sealed, bug #42779 */
6497 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6498 class->parent = parent;
6499 class->instance_size = mono_class_instance_size (class->parent);
6501 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6502 /*Arrays of those two types are invalid.*/
6503 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6504 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6505 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6506 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6507 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6509 /* element_size -1 is ok as this is not an instantitable type*/
6510 class->sizes.element_size = -1;
6512 class->sizes.element_size = mono_class_array_element_size (eclass);
6514 mono_class_setup_supertypes (class);
6516 if (eclass->generic_class)
6517 mono_class_init (eclass);
6518 if (!eclass->size_inited)
6519 mono_class_setup_fields (eclass);
6520 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6521 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6523 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6527 if (eclass->enumtype)
6528 class->cast_class = eclass->element_class;
6530 class->cast_class = eclass;
6532 switch (class->cast_class->byval_arg.type) {
6534 class->cast_class = mono_defaults.byte_class;
6537 class->cast_class = mono_defaults.int16_class;
6540 #if SIZEOF_VOID_P == 4
6544 class->cast_class = mono_defaults.int32_class;
6547 #if SIZEOF_VOID_P == 8
6551 class->cast_class = mono_defaults.int64_class;
6555 class->element_class = eclass;
6557 if ((rank > 1) || bounded) {
6558 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6559 class->byval_arg.type = MONO_TYPE_ARRAY;
6560 class->byval_arg.data.array = at;
6561 at->eklass = eclass;
6563 /* FIXME: complete.... */
6565 class->byval_arg.type = MONO_TYPE_SZARRAY;
6566 class->byval_arg.data.klass = eclass;
6568 class->this_arg = class->byval_arg;
6569 class->this_arg.byref = 1;
6574 class->generic_container = eclass->generic_container;
6576 if (rank == 1 && !bounded) {
6577 MonoClass *prev_class;
6579 mono_mutex_lock (&image->szarray_cache_lock);
6580 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6582 /* Someone got in before us */
6585 g_hash_table_insert (image->szarray_cache, eclass, class);
6586 mono_mutex_unlock (&image->szarray_cache_lock);
6588 list = g_slist_append (rootlist, class);
6589 g_hash_table_insert (image->array_cache, eclass, list);
6592 mono_loader_unlock ();
6594 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6600 * mono_array_class_get:
6601 * @element_class: element class
6602 * @rank: the dimension of the array class
6604 * Returns: a class object describing the array with element type @element_type and
6608 mono_array_class_get (MonoClass *eclass, guint32 rank)
6610 return mono_bounded_array_class_get (eclass, rank, FALSE);
6614 * mono_class_instance_size:
6617 * Returns: the size of an object instance
6620 mono_class_instance_size (MonoClass *klass)
6622 if (!klass->size_inited)
6623 mono_class_init (klass);
6625 return klass->instance_size;
6629 * mono_class_min_align:
6632 * Returns: minimm alignment requirements
6635 mono_class_min_align (MonoClass *klass)
6637 if (!klass->size_inited)
6638 mono_class_init (klass);
6640 return klass->min_align;
6644 * mono_class_value_size:
6647 * This function is used for value types, and return the
6648 * space and the alignment to store that kind of value object.
6650 * Returns: the size of a value of kind @klass
6653 mono_class_value_size (MonoClass *klass, guint32 *align)
6657 /* fixme: check disable, because we still have external revereces to
6658 * mscorlib and Dummy Objects
6660 /*g_assert (klass->valuetype);*/
6662 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6665 *align = klass->min_align;
6671 * mono_class_data_size:
6674 * Returns: the size of the static class data
6677 mono_class_data_size (MonoClass *klass)
6680 mono_class_init (klass);
6681 /* This can happen with dynamically created types */
6682 if (!klass->fields_inited)
6683 mono_class_setup_fields_locking (klass);
6685 /* in arrays, sizes.class_size is unioned with element_size
6686 * and arrays have no static fields
6690 return klass->sizes.class_size;
6694 * Auxiliary routine to mono_class_get_field
6696 * Takes a field index instead of a field token.
6698 static MonoClassField *
6699 mono_class_get_field_idx (MonoClass *class, int idx)
6701 mono_class_setup_fields_locking (class);
6702 if (class->exception_type)
6706 if (class->image->uncompressed_metadata) {
6708 * class->field.first points to the FieldPtr table, while idx points into the
6709 * Field table, so we have to do a search.
6711 /*FIXME this is broken for types with multiple fields with the same name.*/
6712 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6715 for (i = 0; i < class->field.count; ++i)
6716 if (mono_field_get_name (&class->fields [i]) == name)
6717 return &class->fields [i];
6718 g_assert_not_reached ();
6720 if (class->field.count) {
6721 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6722 return &class->fields [idx - class->field.first];
6726 class = class->parent;
6732 * mono_class_get_field:
6733 * @class: the class to lookup the field.
6734 * @field_token: the field token
6736 * Returns: A MonoClassField representing the type and offset of
6737 * the field, or a NULL value if the field does not belong to this
6741 mono_class_get_field (MonoClass *class, guint32 field_token)
6743 int idx = mono_metadata_token_index (field_token);
6745 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6747 return mono_class_get_field_idx (class, idx - 1);
6751 * mono_class_get_field_from_name:
6752 * @klass: the class to lookup the field.
6753 * @name: the field name
6755 * Search the class @klass and it's parents for a field with the name @name.
6757 * Returns: the MonoClassField pointer of the named field or NULL
6760 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6762 return mono_class_get_field_from_name_full (klass, name, NULL);
6766 * mono_class_get_field_from_name_full:
6767 * @klass: the class to lookup the field.
6768 * @name: the field name
6769 * @type: the type of the fields. This optional.
6771 * Search the class @klass and it's parents for a field with the name @name and type @type.
6773 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6774 * of its generic type definition.
6776 * Returns: the MonoClassField pointer of the named field or NULL
6779 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6783 mono_class_setup_fields_locking (klass);
6784 if (klass->exception_type)
6788 for (i = 0; i < klass->field.count; ++i) {
6789 MonoClassField *field = &klass->fields [i];
6791 if (strcmp (name, mono_field_get_name (field)) != 0)
6795 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6796 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6801 klass = klass->parent;
6807 * mono_class_get_field_token:
6808 * @field: the field we need the token of
6810 * Get the token of a field. Note that the tokesn is only valid for the image
6811 * the field was loaded from. Don't use this function for fields in dynamic types.
6813 * Returns: the token representing the field in the image it was loaded from.
6816 mono_class_get_field_token (MonoClassField *field)
6818 MonoClass *klass = field->parent;
6821 mono_class_setup_fields_locking (klass);
6826 for (i = 0; i < klass->field.count; ++i) {
6827 if (&klass->fields [i] == field) {
6828 int idx = klass->field.first + i + 1;
6830 if (klass->image->uncompressed_metadata)
6831 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6832 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6835 klass = klass->parent;
6838 g_assert_not_reached ();
6843 mono_field_get_index (MonoClassField *field)
6845 int index = field - field->parent->fields;
6847 g_assert (index >= 0 && index < field->parent->field.count);
6853 * mono_class_get_field_default_value:
6855 * Return the default value of the field as a pointer into the metadata blob.
6858 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6861 guint32 constant_cols [MONO_CONSTANT_SIZE];
6863 MonoClass *klass = field->parent;
6865 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6867 if (!klass->ext || !klass->ext->field_def_values) {
6868 MonoFieldDefaultValue *def_values;
6870 mono_class_alloc_ext (klass);
6872 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6874 mono_image_lock (klass->image);
6875 mono_memory_barrier ();
6876 if (!klass->ext->field_def_values)
6877 klass->ext->field_def_values = def_values;
6878 mono_image_unlock (klass->image);
6881 field_index = mono_field_get_index (field);
6883 if (!klass->ext->field_def_values [field_index].data) {
6884 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6888 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6890 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6891 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6892 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6895 *def_type = klass->ext->field_def_values [field_index].def_type;
6896 return klass->ext->field_def_values [field_index].data;
6900 mono_property_get_index (MonoProperty *prop)
6902 int index = prop - prop->parent->ext->properties;
6904 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6910 * mono_class_get_property_default_value:
6912 * Return the default value of the field as a pointer into the metadata blob.
6915 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6918 guint32 constant_cols [MONO_CONSTANT_SIZE];
6919 MonoClass *klass = property->parent;
6921 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6923 * We don't cache here because it is not used by C# so it's quite rare, but
6924 * we still do the lookup in klass->ext because that is where the data
6925 * is stored for dynamic assemblies.
6928 if (image_is_dynamic (klass->image)) {
6929 int prop_index = mono_property_get_index (property);
6930 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6931 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6932 return klass->ext->prop_def_values [prop_index].data;
6936 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6940 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6941 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6942 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6946 mono_class_get_event_token (MonoEvent *event)
6948 MonoClass *klass = event->parent;
6953 for (i = 0; i < klass->ext->event.count; ++i) {
6954 if (&klass->ext->events [i] == event)
6955 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6958 klass = klass->parent;
6961 g_assert_not_reached ();
6966 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6970 gpointer iter = NULL;
6971 while ((p = mono_class_get_properties (klass, &iter))) {
6972 if (! strcmp (name, p->name))
6975 klass = klass->parent;
6981 mono_class_get_property_token (MonoProperty *prop)
6983 MonoClass *klass = prop->parent;
6987 gpointer iter = NULL;
6988 while ((p = mono_class_get_properties (klass, &iter))) {
6989 if (&klass->ext->properties [i] == prop)
6990 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6994 klass = klass->parent;
6997 g_assert_not_reached ();
7002 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7004 const char *name, *nspace;
7005 if (image_is_dynamic (image))
7006 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7008 switch (type_token & 0xff000000){
7009 case MONO_TOKEN_TYPE_DEF: {
7010 guint32 cols [MONO_TYPEDEF_SIZE];
7011 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7012 guint tidx = mono_metadata_token_index (type_token);
7014 if (tidx > tt->rows)
7015 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7017 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7018 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7019 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7020 if (strlen (nspace) == 0)
7021 return g_strdup_printf ("%s", name);
7023 return g_strdup_printf ("%s.%s", nspace, name);
7026 case MONO_TOKEN_TYPE_REF: {
7028 guint32 cols [MONO_TYPEREF_SIZE];
7029 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7030 guint tidx = mono_metadata_token_index (type_token);
7033 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7035 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7036 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7037 mono_error_cleanup (&error);
7041 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7042 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7043 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7044 if (strlen (nspace) == 0)
7045 return g_strdup_printf ("%s", name);
7047 return g_strdup_printf ("%s.%s", nspace, name);
7050 case MONO_TOKEN_TYPE_SPEC:
7051 return g_strdup_printf ("Typespec 0x%08x", type_token);
7053 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7058 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7060 if (image_is_dynamic (image))
7061 return g_strdup_printf ("DynamicAssembly %s", image->name);
7063 switch (type_token & 0xff000000){
7064 case MONO_TOKEN_TYPE_DEF:
7065 if (image->assembly)
7066 return mono_stringify_assembly_name (&image->assembly->aname);
7067 else if (image->assembly_name)
7068 return g_strdup (image->assembly_name);
7069 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7070 case MONO_TOKEN_TYPE_REF: {
7072 MonoAssemblyName aname;
7073 guint32 cols [MONO_TYPEREF_SIZE];
7074 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7075 guint32 idx = mono_metadata_token_index (type_token);
7078 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7080 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7081 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7082 mono_error_cleanup (&error);
7085 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7087 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7088 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7089 case MONO_RESOLTION_SCOPE_MODULE:
7091 return g_strdup ("");
7092 case MONO_RESOLTION_SCOPE_MODULEREF:
7094 return g_strdup ("");
7095 case MONO_RESOLTION_SCOPE_TYPEREF:
7097 return g_strdup ("");
7098 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7099 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7100 return mono_stringify_assembly_name (&aname);
7102 g_assert_not_reached ();
7106 case MONO_TOKEN_TYPE_SPEC:
7108 return g_strdup ("");
7110 g_assert_not_reached ();
7117 * mono_class_get_full:
7118 * @image: the image where the class resides
7119 * @type_token: the token for the class
7120 * @context: the generic context used to evaluate generic instantiations in
7122 * Returns: the MonoClass that represents @type_token in @image
7125 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7128 MonoClass *class = NULL;
7130 if (image_is_dynamic (image)) {
7131 int table = mono_metadata_token_table (type_token);
7133 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7134 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7137 return mono_lookup_dynamic_token (image, type_token, context);
7140 switch (type_token & 0xff000000){
7141 case MONO_TOKEN_TYPE_DEF:
7142 class = mono_class_create_from_typedef (image, type_token, &error);
7143 if (!mono_error_ok (&error)) {
7144 mono_loader_set_error_from_mono_error (&error);
7145 /*FIXME don't swallow the error message*/
7146 mono_error_cleanup (&error);
7150 case MONO_TOKEN_TYPE_REF:
7151 class = mono_class_from_typeref (image, type_token);
7153 case MONO_TOKEN_TYPE_SPEC:
7154 class = mono_class_create_from_typespec (image, type_token, context, &error);
7155 if (!mono_error_ok (&error)) {
7156 /*FIXME don't swallow the error message*/
7157 mono_error_cleanup (&error);
7161 g_warning ("unknown token type %x", type_token & 0xff000000);
7162 g_assert_not_reached ();
7166 char *name = mono_class_name_from_token (image, type_token);
7167 char *assembly = mono_assembly_name_from_token (image, type_token);
7168 mono_loader_set_error_type_load (name, assembly);
7178 * mono_type_get_full:
7179 * @image: the image where the type resides
7180 * @type_token: the token for the type
7181 * @context: the generic context used to evaluate generic instantiations in
7183 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7185 * Returns: the MonoType that represents @type_token in @image
7188 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7191 MonoType *type = NULL;
7192 gboolean inflated = FALSE;
7194 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7195 if (image_is_dynamic (image))
7196 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7198 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7199 MonoClass *class = mono_class_get_full (image, type_token, context);
7200 return class ? mono_class_get_type (class) : NULL;
7203 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7205 if (!mono_error_ok (&error)) {
7206 /*FIXME don't swalloc the error message.*/
7207 char *name = mono_class_name_from_token (image, type_token);
7208 char *assembly = mono_assembly_name_from_token (image, type_token);
7210 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7212 mono_error_cleanup (&error);
7213 mono_loader_set_error_type_load (name, assembly);
7218 MonoType *tmp = type;
7219 type = mono_class_get_type (mono_class_from_mono_type (type));
7220 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7221 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7222 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7224 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7226 if (type->type != tmp->type)
7229 mono_metadata_free_type (tmp);
7236 mono_class_get (MonoImage *image, guint32 type_token)
7238 return mono_class_get_full (image, type_token, NULL);
7242 * mono_image_init_name_cache:
7244 * Initializes the class name cache stored in image->name_cache.
7246 * LOCKING: Acquires the corresponding image lock.
7249 mono_image_init_name_cache (MonoImage *image)
7251 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7252 guint32 cols [MONO_TYPEDEF_SIZE];
7255 guint32 i, visib, nspace_index;
7256 GHashTable *name_cache2, *nspace_table;
7258 mono_image_lock (image);
7260 if (image->name_cache) {
7261 mono_image_unlock (image);
7265 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7267 if (image_is_dynamic (image)) {
7268 mono_image_unlock (image);
7272 /* Temporary hash table to avoid lookups in the nspace_table */
7273 name_cache2 = g_hash_table_new (NULL, NULL);
7275 for (i = 1; i <= t->rows; ++i) {
7276 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7277 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7279 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7280 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7282 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7284 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7285 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7287 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7288 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7289 if (!nspace_table) {
7290 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7291 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7292 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7295 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7298 /* Load type names from EXPORTEDTYPES table */
7300 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7301 guint32 cols [MONO_EXP_TYPE_SIZE];
7304 for (i = 0; i < t->rows; ++i) {
7305 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7306 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7307 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7309 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7310 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7311 if (!nspace_table) {
7312 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7313 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7314 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7317 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7321 g_hash_table_destroy (name_cache2);
7322 mono_image_unlock (image);
7325 /*FIXME Only dynamic assemblies should allow this operation.*/
7327 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7328 const char *name, guint32 index)
7330 GHashTable *nspace_table;
7331 GHashTable *name_cache;
7334 mono_image_lock (image);
7336 if (!image->name_cache)
7337 mono_image_init_name_cache (image);
7339 name_cache = image->name_cache;
7340 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7341 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7342 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7345 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7346 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7348 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7350 mono_image_unlock (image);
7359 find_nocase (gpointer key, gpointer value, gpointer user_data)
7361 char *name = (char*)key;
7362 FindUserData *data = (FindUserData*)user_data;
7364 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7365 data->value = value;
7369 * mono_class_from_name_case:
7370 * @image: The MonoImage where the type is looked up in
7371 * @name_space: the type namespace
7372 * @name: the type short name.
7374 * Obtains a MonoClass with a given namespace and a given name which
7375 * is located in the given MonoImage. The namespace and name
7376 * lookups are case insensitive.
7379 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7381 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7382 guint32 cols [MONO_TYPEDEF_SIZE];
7387 if (image_is_dynamic (image)) {
7389 FindUserData user_data;
7391 mono_image_lock (image);
7393 if (!image->name_cache)
7394 mono_image_init_name_cache (image);
7396 user_data.key = name_space;
7397 user_data.value = NULL;
7398 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7400 if (user_data.value) {
7401 GHashTable *nspace_table = (GHashTable*)user_data.value;
7403 user_data.key = name;
7404 user_data.value = NULL;
7406 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7408 if (user_data.value)
7409 token = GPOINTER_TO_UINT (user_data.value);
7412 mono_image_unlock (image);
7415 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7421 /* add a cache if needed */
7422 for (i = 1; i <= t->rows; ++i) {
7423 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7424 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7426 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7427 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7429 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7431 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7432 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7433 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7434 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7440 return_nested_in (MonoClass *class, char *nested)
7443 char *s = strchr (nested, '/');
7444 gpointer iter = NULL;
7451 while ((found = mono_class_get_nested_types (class, &iter))) {
7452 if (strcmp (found->name, nested) == 0) {
7454 return return_nested_in (found, s);
7462 search_modules (MonoImage *image, const char *name_space, const char *name)
7464 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7465 MonoImage *file_image;
7470 * The EXPORTEDTYPES table only contains public types, so have to search the
7472 * Note: image->modules contains the contents of the MODULEREF table, while
7473 * the real module list is in the FILE table.
7475 for (i = 0; i < file_table->rows; i++) {
7476 guint32 cols [MONO_FILE_SIZE];
7477 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7478 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7481 file_image = mono_image_load_file_for_image (image, i + 1);
7483 class = mono_class_from_name (file_image, name_space, name);
7493 * mono_class_from_name:
7494 * @image: The MonoImage where the type is looked up in
7495 * @name_space: the type namespace
7496 * @name: the type short name.
7498 * Obtains a MonoClass with a given namespace and a given name which
7499 * is located in the given MonoImage.
7501 * To reference nested classes, use the "/" character as a separator.
7502 * For example use "Foo/Bar" to reference the class Bar that is nested
7503 * inside Foo, like this: "class Foo { class Bar {} }".
7506 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7508 GHashTable *nspace_table;
7509 MonoImage *loaded_image;
7516 if ((nested = strchr (name, '/'))) {
7517 int pos = nested - name;
7518 int len = strlen (name);
7521 memcpy (buf, name, len + 1);
7523 nested = buf + pos + 1;
7527 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7528 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7529 gboolean res = get_class_from_name (image, name_space, name, &class);
7532 class = search_modules (image, name_space, name);
7534 return class ? return_nested_in (class, nested) : NULL;
7540 mono_image_lock (image);
7542 if (!image->name_cache)
7543 mono_image_init_name_cache (image);
7545 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7548 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7550 mono_image_unlock (image);
7552 if (!token && image_is_dynamic (image) && image->modules) {
7553 /* Search modules as well */
7554 for (i = 0; i < image->module_count; ++i) {
7555 MonoImage *module = image->modules [i];
7557 class = mono_class_from_name (module, name_space, name);
7564 class = search_modules (image, name_space, name);
7572 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7573 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7574 guint32 cols [MONO_EXP_TYPE_SIZE];
7577 idx = mono_metadata_token_index (token);
7579 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7581 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7582 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7583 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7586 class = mono_class_from_name (loaded_image, name_space, name);
7588 return return_nested_in (class, nested);
7590 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7591 guint32 assembly_idx;
7593 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7595 mono_assembly_load_reference (image, assembly_idx - 1);
7596 g_assert (image->references [assembly_idx - 1]);
7597 if (image->references [assembly_idx - 1] == (gpointer)-1)
7600 /* FIXME: Cycle detection */
7601 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7603 g_error ("not yet implemented");
7607 token = MONO_TOKEN_TYPE_DEF | token;
7609 class = mono_class_get (image, token);
7611 return return_nested_in (class, nested);
7616 * mono_class_is_subclass_of:
7617 * @klass: class to probe if it is a subclass of another one
7618 * @klassc: the class we suspect is the base class
7619 * @check_interfaces: whether we should perform interface checks
7621 * This method determines whether @klass is a subclass of @klassc.
7623 * If the @check_interfaces flag is set, then if @klassc is an interface
7624 * this method return true if the @klass implements the interface or
7625 * if @klass is an interface, if one of its base classes is @klass.
7627 * If @check_interfaces is false then, then if @klass is not an interface
7628 * then it returns true if the @klass is a subclass of @klassc.
7630 * if @klass is an interface and @klassc is System.Object, then this function
7635 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7636 gboolean check_interfaces)
7638 /*FIXME test for interfaces with variant generic arguments*/
7640 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7641 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7643 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7646 for (i = 0; i < klass->interface_count; i ++) {
7647 MonoClass *ic = klass->interfaces [i];
7652 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7657 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7660 if (klassc == mono_defaults.object_class)
7667 mono_type_is_generic_argument (MonoType *type)
7669 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7673 mono_class_has_variant_generic_params (MonoClass *klass)
7676 MonoGenericContainer *container;
7678 if (!klass->generic_class)
7681 container = klass->generic_class->container_class->generic_container;
7683 for (i = 0; i < container->type_argc; ++i)
7684 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7691 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7693 if (target == candidate)
7696 if (check_for_reference_conv &&
7697 mono_type_is_generic_argument (&target->byval_arg) &&
7698 mono_type_is_generic_argument (&candidate->byval_arg)) {
7699 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7700 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7702 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7705 if (!mono_class_is_assignable_from (target, candidate))
7711 * @container the generic container from the GTD
7712 * @klass: the class to be assigned to
7713 * @oklass: the source class
7715 * Both klass and oklass must be instances of the same generic interface.
7716 * Return true if @klass can be assigned to a @klass variable
7719 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7722 MonoType **klass_argv, **oklass_argv;
7723 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7724 MonoGenericContainer *container = klass_gtd->generic_container;
7726 if (klass == oklass)
7729 /*Viable candidates are instances of the same generic interface*/
7730 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7733 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7734 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7736 for (j = 0; j < container->type_argc; ++j) {
7737 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7738 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7740 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7744 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7745 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7747 if (param1_class != param2_class) {
7748 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7749 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7751 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7752 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7762 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7764 MonoGenericParam *gparam, *ogparam;
7765 MonoGenericParamInfo *tinfo, *cinfo;
7766 MonoClass **candidate_class;
7767 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7770 if (target == candidate)
7772 if (target->byval_arg.type != candidate->byval_arg.type)
7775 gparam = target->byval_arg.data.generic_param;
7776 ogparam = candidate->byval_arg.data.generic_param;
7777 tinfo = mono_generic_param_info (gparam);
7778 cinfo = mono_generic_param_info (ogparam);
7780 class_constraint_satisfied = FALSE;
7781 valuetype_constraint_satisfied = FALSE;
7783 /*candidate must have a super set of target's special constraints*/
7784 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7785 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7787 if (cinfo->constraints) {
7788 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7789 MonoClass *cc = *candidate_class;
7791 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7792 class_constraint_satisfied = TRUE;
7793 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7794 valuetype_constraint_satisfied = TRUE;
7797 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7798 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7800 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7802 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7804 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7805 valuetype_constraint_satisfied)) {
7810 /*candidate type constraints must be a superset of target's*/
7811 if (tinfo->constraints) {
7812 MonoClass **target_class;
7813 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7814 MonoClass *tc = *target_class;
7817 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7818 * check it's constraints since it satisfy the constraint by itself.
7820 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7823 if (!cinfo->constraints)
7826 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7827 MonoClass *cc = *candidate_class;
7829 if (mono_class_is_assignable_from (tc, cc))
7833 * This happens when we have the following:
7835 * Bar<K> where K : IFace
7836 * Foo<T, U> where T : U where U : IFace
7838 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7841 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7842 if (mono_gparam_is_assignable_from (target, cc))
7846 if (!*candidate_class)
7851 /*candidate itself must have a constraint that satisfy target*/
7852 if (cinfo->constraints) {
7853 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7854 MonoClass *cc = *candidate_class;
7855 if (mono_class_is_assignable_from (target, cc))
7863 * mono_class_is_assignable_from:
7864 * @klass: the class to be assigned to
7865 * @oklass: the source class
7867 * Return: true if an instance of object oklass can be assigned to an
7868 * instance of object @klass
7871 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7873 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7875 mono_class_init (klass);
7877 if (!oklass->inited)
7878 mono_class_init (oklass);
7880 if (klass->exception_type || oklass->exception_type)
7883 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7884 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7886 return mono_gparam_is_assignable_from (klass, oklass);
7889 if (MONO_CLASS_IS_INTERFACE (klass)) {
7890 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7891 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7892 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7896 for (i = 0; constraints [i]; ++i) {
7897 if (mono_class_is_assignable_from (klass, constraints [i]))
7905 /* interface_offsets might not be set for dynamic classes */
7906 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7908 * oklass might be a generic type parameter but they have
7909 * interface_offsets set.
7911 return mono_reflection_call_is_assignable_to (oklass, klass);
7912 if (!oklass->interface_bitmap)
7913 /* Happens with generic instances of not-yet created dynamic types */
7915 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7918 if (mono_class_has_variant_generic_params (klass)) {
7921 mono_class_setup_interfaces (oklass, &error);
7922 if (!mono_error_ok (&error)) {
7923 mono_error_cleanup (&error);
7927 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7928 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7929 MonoClass *iface = oklass->interfaces_packed [i];
7931 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7936 } else if (klass->delegate) {
7937 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7939 }else if (klass->rank) {
7940 MonoClass *eclass, *eoclass;
7942 if (oklass->rank != klass->rank)
7945 /* vectors vs. one dimensional arrays */
7946 if (oklass->byval_arg.type != klass->byval_arg.type)
7949 eclass = klass->cast_class;
7950 eoclass = oklass->cast_class;
7953 * a is b does not imply a[] is b[] when a is a valuetype, and
7954 * b is a reference type.
7957 if (eoclass->valuetype) {
7958 if ((eclass == mono_defaults.enum_class) ||
7959 (eclass == mono_defaults.enum_class->parent) ||
7960 (eclass == mono_defaults.object_class))
7964 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7965 } else if (mono_class_is_nullable (klass)) {
7966 if (mono_class_is_nullable (oklass))
7967 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7969 return mono_class_is_assignable_from (klass->cast_class, oklass);
7970 } else if (klass == mono_defaults.object_class)
7973 return mono_class_has_parent (oklass, klass);
7976 /*Check if @oklass is variant compatible with @klass.*/
7978 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7981 MonoType **klass_argv, **oklass_argv;
7982 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7983 MonoGenericContainer *container = klass_gtd->generic_container;
7985 /*Viable candidates are instances of the same generic interface*/
7986 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7989 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7990 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7992 for (j = 0; j < container->type_argc; ++j) {
7993 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7994 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7996 if (param1_class->valuetype != param2_class->valuetype)
8000 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8001 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8003 if (param1_class != param2_class) {
8004 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8005 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8007 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8008 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8016 /*Check if @candidate implements the interface @target*/
8018 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8022 gboolean is_variant = mono_class_has_variant_generic_params (target);
8024 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8025 if (mono_class_is_variant_compatible_slow (target, candidate))
8030 if (candidate == target)
8033 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8034 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8035 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8037 if (tb && tb->interfaces) {
8038 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8039 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8040 MonoClass *iface_class;
8042 /* we can't realize the type here since it can do pretty much anything. */
8045 iface_class = mono_class_from_mono_type (iface->type);
8046 if (iface_class == target)
8048 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8050 if (mono_class_implement_interface_slow (target, iface_class))
8055 /*setup_interfaces don't mono_class_init anything*/
8056 /*FIXME this doesn't handle primitive type arrays.
8057 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8058 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8060 mono_class_setup_interfaces (candidate, &error);
8061 if (!mono_error_ok (&error)) {
8062 mono_error_cleanup (&error);
8066 for (i = 0; i < candidate->interface_count; ++i) {
8067 if (candidate->interfaces [i] == target)
8070 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8073 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8077 candidate = candidate->parent;
8078 } while (candidate);
8084 * Check if @oklass can be assigned to @klass.
8085 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8088 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8090 if (candidate == target)
8092 if (target == mono_defaults.object_class)
8095 if (mono_class_has_parent (candidate, target))
8098 /*If target is not an interface there is no need to check them.*/
8099 if (MONO_CLASS_IS_INTERFACE (target))
8100 return mono_class_implement_interface_slow (target, candidate);
8102 if (target->delegate && mono_class_has_variant_generic_params (target))
8103 return mono_class_is_variant_compatible (target, candidate, FALSE);
8106 MonoClass *eclass, *eoclass;
8108 if (target->rank != candidate->rank)
8111 /* vectors vs. one dimensional arrays */
8112 if (target->byval_arg.type != candidate->byval_arg.type)
8115 eclass = target->cast_class;
8116 eoclass = candidate->cast_class;
8119 * a is b does not imply a[] is b[] when a is a valuetype, and
8120 * b is a reference type.
8123 if (eoclass->valuetype) {
8124 if ((eclass == mono_defaults.enum_class) ||
8125 (eclass == mono_defaults.enum_class->parent) ||
8126 (eclass == mono_defaults.object_class))
8130 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8132 /*FIXME properly handle nullables */
8133 /*FIXME properly handle (M)VAR */
8138 * mono_class_get_cctor:
8139 * @klass: A MonoClass pointer
8141 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8144 mono_class_get_cctor (MonoClass *klass)
8146 MonoCachedClassInfo cached_info;
8148 if (image_is_dynamic (klass->image)) {
8150 * has_cctor is not set for these classes because mono_class_init () is
8153 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8156 if (!klass->has_cctor)
8159 if (mono_class_get_cached_class_info (klass, &cached_info))
8160 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8162 if (klass->generic_class && !klass->methods)
8163 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8165 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8169 * mono_class_get_finalizer:
8170 * @klass: The MonoClass pointer
8172 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8175 mono_class_get_finalizer (MonoClass *klass)
8177 MonoCachedClassInfo cached_info;
8180 mono_class_init (klass);
8181 if (!mono_class_has_finalizer (klass))
8184 if (mono_class_get_cached_class_info (klass, &cached_info))
8185 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8187 mono_class_setup_vtable (klass);
8188 return klass->vtable [finalize_slot];
8193 * mono_class_needs_cctor_run:
8194 * @klass: the MonoClass pointer
8195 * @caller: a MonoMethod describing the caller
8197 * Determines whenever the class has a static constructor and whenever it
8198 * needs to be called when executing CALLER.
8201 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8205 method = mono_class_get_cctor (klass);
8207 return (method == caller) ? FALSE : TRUE;
8213 * mono_class_array_element_size:
8216 * Returns: the number of bytes an element of type @klass
8217 * uses when stored into an array.
8220 mono_class_array_element_size (MonoClass *klass)
8222 MonoType *type = &klass->byval_arg;
8225 switch (type->type) {
8228 case MONO_TYPE_BOOLEAN:
8232 case MONO_TYPE_CHAR:
8241 case MONO_TYPE_CLASS:
8242 case MONO_TYPE_STRING:
8243 case MONO_TYPE_OBJECT:
8244 case MONO_TYPE_SZARRAY:
8245 case MONO_TYPE_ARRAY:
8247 case MONO_TYPE_MVAR:
8248 return sizeof (gpointer);
8253 case MONO_TYPE_VALUETYPE:
8254 if (type->data.klass->enumtype) {
8255 type = mono_class_enum_basetype (type->data.klass);
8256 klass = klass->element_class;
8259 return mono_class_instance_size (klass) - sizeof (MonoObject);
8260 case MONO_TYPE_GENERICINST:
8261 type = &type->data.generic_class->container_class->byval_arg;
8264 case MONO_TYPE_VOID:
8268 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8274 * mono_array_element_size:
8275 * @ac: pointer to a #MonoArrayClass
8277 * Returns: the size of single array element.
8280 mono_array_element_size (MonoClass *ac)
8282 g_assert (ac->rank);
8283 return ac->sizes.element_size;
8287 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8288 MonoGenericContext *context)
8290 if (image_is_dynamic (image)) {
8291 MonoClass *tmp_handle_class;
8292 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8294 g_assert (tmp_handle_class);
8296 *handle_class = tmp_handle_class;
8298 if (tmp_handle_class == mono_defaults.typehandle_class)
8299 return &((MonoClass*)obj)->byval_arg;
8304 switch (token & 0xff000000) {
8305 case MONO_TOKEN_TYPE_DEF:
8306 case MONO_TOKEN_TYPE_REF:
8307 case MONO_TOKEN_TYPE_SPEC: {
8310 *handle_class = mono_defaults.typehandle_class;
8311 type = mono_type_get_full (image, token, context);
8314 mono_class_init (mono_class_from_mono_type (type));
8315 /* We return a MonoType* as handle */
8318 case MONO_TOKEN_FIELD_DEF: {
8320 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8324 *handle_class = mono_defaults.fieldhandle_class;
8325 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8328 mono_class_init (class);
8329 return mono_class_get_field (class, token);
8331 case MONO_TOKEN_METHOD_DEF:
8332 case MONO_TOKEN_METHOD_SPEC: {
8334 meth = mono_get_method_full (image, token, NULL, context);
8336 *handle_class = mono_defaults.methodhandle_class;
8339 case MONO_TOKEN_MEMBER_REF: {
8340 guint32 cols [MONO_MEMBERREF_SIZE];
8342 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8343 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8344 mono_metadata_decode_blob_size (sig, &sig);
8345 if (*sig == 0x6) { /* it's a field */
8347 MonoClassField *field;
8348 field = mono_field_from_token (image, token, &klass, context);
8350 *handle_class = mono_defaults.fieldhandle_class;
8354 meth = mono_get_method_full (image, token, NULL, context);
8356 *handle_class = mono_defaults.methodhandle_class;
8361 g_warning ("Unknown token 0x%08x in ldtoken", token);
8368 * This function might need to call runtime functions so it can't be part
8369 * of the metadata library.
8371 static MonoLookupDynamicToken lookup_dynamic = NULL;
8374 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8376 lookup_dynamic = func;
8380 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8382 MonoClass *handle_class;
8384 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8388 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8390 return lookup_dynamic (image, token, valid_token, handle_class, context);
8393 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8396 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8398 get_cached_class_info = func;
8402 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8404 if (!get_cached_class_info)
8407 return get_cached_class_info (klass, res);
8411 mono_install_get_class_from_name (MonoGetClassFromName func)
8413 get_class_from_name = func;
8417 mono_class_get_image (MonoClass *klass)
8419 return klass->image;
8423 * mono_class_get_element_class:
8424 * @klass: the MonoClass to act on
8426 * Returns: the element class of an array or an enumeration.
8429 mono_class_get_element_class (MonoClass *klass)
8431 return klass->element_class;
8435 * mono_class_is_valuetype:
8436 * @klass: the MonoClass to act on
8438 * Returns: true if the MonoClass represents a ValueType.
8441 mono_class_is_valuetype (MonoClass *klass)
8443 return klass->valuetype;
8447 * mono_class_is_enum:
8448 * @klass: the MonoClass to act on
8450 * Returns: true if the MonoClass represents an enumeration.
8453 mono_class_is_enum (MonoClass *klass)
8455 return klass->enumtype;
8459 * mono_class_enum_basetype:
8460 * @klass: the MonoClass to act on
8462 * Returns: the underlying type representation for an enumeration.
8465 mono_class_enum_basetype (MonoClass *klass)
8467 if (klass->element_class == klass)
8468 /* SRE or broken types */
8471 return &klass->element_class->byval_arg;
8475 * mono_class_get_parent
8476 * @klass: the MonoClass to act on
8478 * Returns: the parent class for this class.
8481 mono_class_get_parent (MonoClass *klass)
8483 return klass->parent;
8487 * mono_class_get_nesting_type;
8488 * @klass: the MonoClass to act on
8490 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8493 mono_class_get_nesting_type (MonoClass *klass)
8495 return klass->nested_in;
8499 * mono_class_get_rank:
8500 * @klass: the MonoClass to act on
8502 * Returns: the rank for the array (the number of dimensions).
8505 mono_class_get_rank (MonoClass *klass)
8511 * mono_class_get_flags:
8512 * @klass: the MonoClass to act on
8514 * The type flags from the TypeDef table from the metadata.
8515 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8518 * Returns: the flags from the TypeDef table.
8521 mono_class_get_flags (MonoClass *klass)
8523 return klass->flags;
8527 * mono_class_get_name
8528 * @klass: the MonoClass to act on
8530 * Returns: the name of the class.
8533 mono_class_get_name (MonoClass *klass)
8539 * mono_class_get_namespace:
8540 * @klass: the MonoClass to act on
8542 * Returns: the namespace of the class.
8545 mono_class_get_namespace (MonoClass *klass)
8547 return klass->name_space;
8551 * mono_class_get_type:
8552 * @klass: the MonoClass to act on
8554 * This method returns the internal Type representation for the class.
8556 * Returns: the MonoType from the class.
8559 mono_class_get_type (MonoClass *klass)
8561 return &klass->byval_arg;
8565 * mono_class_get_type_token
8566 * @klass: the MonoClass to act on
8568 * This method returns type token for the class.
8570 * Returns: the type token for the class.
8573 mono_class_get_type_token (MonoClass *klass)
8575 return klass->type_token;
8579 * mono_class_get_byref_type:
8580 * @klass: the MonoClass to act on
8585 mono_class_get_byref_type (MonoClass *klass)
8587 return &klass->this_arg;
8591 * mono_class_num_fields:
8592 * @klass: the MonoClass to act on
8594 * Returns: the number of static and instance fields in the class.
8597 mono_class_num_fields (MonoClass *klass)
8599 return klass->field.count;
8603 * mono_class_num_methods:
8604 * @klass: the MonoClass to act on
8606 * Returns: the number of methods in the class.
8609 mono_class_num_methods (MonoClass *klass)
8611 return klass->method.count;
8615 * mono_class_num_properties
8616 * @klass: the MonoClass to act on
8618 * Returns: the number of properties in the class.
8621 mono_class_num_properties (MonoClass *klass)
8623 mono_class_setup_properties (klass);
8625 return klass->ext->property.count;
8629 * mono_class_num_events:
8630 * @klass: the MonoClass to act on
8632 * Returns: the number of events in the class.
8635 mono_class_num_events (MonoClass *klass)
8637 mono_class_setup_events (klass);
8639 return klass->ext->event.count;
8643 * mono_class_get_fields:
8644 * @klass: the MonoClass to act on
8646 * This routine is an iterator routine for retrieving the fields in a class.
8648 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8649 * iterate over all of the elements. When no more values are
8650 * available, the return value is NULL.
8652 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8655 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8657 MonoClassField* field;
8661 mono_class_setup_fields_locking (klass);
8662 if (klass->exception_type)
8664 /* start from the first */
8665 if (klass->field.count) {
8666 return *iter = &klass->fields [0];
8674 if (field < &klass->fields [klass->field.count]) {
8675 return *iter = field;
8681 * mono_class_get_methods
8682 * @klass: the MonoClass to act on
8684 * This routine is an iterator routine for retrieving the fields in a class.
8686 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8687 * iterate over all of the elements. When no more values are
8688 * available, the return value is NULL.
8690 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8693 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8695 MonoMethod** method;
8699 mono_class_setup_methods (klass);
8702 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8703 * FIXME we should better report this error to the caller
8705 if (!klass->methods)
8707 /* start from the first */
8708 if (klass->method.count) {
8709 *iter = &klass->methods [0];
8710 return klass->methods [0];
8718 if (method < &klass->methods [klass->method.count]) {
8726 * mono_class_get_virtual_methods:
8728 * Iterate over the virtual methods of KLASS.
8730 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8733 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8735 MonoMethod** method;
8738 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8740 mono_class_setup_methods (klass);
8742 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8743 * FIXME we should better report this error to the caller
8745 if (!klass->methods)
8747 /* start from the first */
8748 method = &klass->methods [0];
8753 while (method < &klass->methods [klass->method.count]) {
8754 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8758 if (method < &klass->methods [klass->method.count]) {
8765 /* Search directly in metadata to avoid calling setup_methods () */
8766 MonoMethod *res = NULL;
8772 start_index = GPOINTER_TO_UINT (*iter);
8775 for (i = start_index; i < klass->method.count; ++i) {
8778 /* class->method.first points into the methodptr table */
8779 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8781 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8785 if (i < klass->method.count) {
8786 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8787 /* Add 1 here so the if (*iter) check fails */
8788 *iter = GUINT_TO_POINTER (i + 1);
8797 * mono_class_get_properties:
8798 * @klass: the MonoClass to act on
8800 * This routine is an iterator routine for retrieving the properties in a class.
8802 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8803 * iterate over all of the elements. When no more values are
8804 * available, the return value is NULL.
8806 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8809 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8811 MonoProperty* property;
8815 mono_class_setup_properties (klass);
8816 /* start from the first */
8817 if (klass->ext->property.count) {
8818 return *iter = &klass->ext->properties [0];
8826 if (property < &klass->ext->properties [klass->ext->property.count]) {
8827 return *iter = property;
8833 * mono_class_get_events:
8834 * @klass: the MonoClass to act on
8836 * This routine is an iterator routine for retrieving the properties in a class.
8838 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8839 * iterate over all of the elements. When no more values are
8840 * available, the return value is NULL.
8842 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8845 mono_class_get_events (MonoClass* klass, gpointer *iter)
8851 mono_class_setup_events (klass);
8852 /* start from the first */
8853 if (klass->ext->event.count) {
8854 return *iter = &klass->ext->events [0];
8862 if (event < &klass->ext->events [klass->ext->event.count]) {
8863 return *iter = event;
8869 * mono_class_get_interfaces
8870 * @klass: the MonoClass to act on
8872 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8874 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8875 * iterate over all of the elements. When no more values are
8876 * available, the return value is NULL.
8878 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8881 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8889 mono_class_init (klass);
8890 if (!klass->interfaces_inited) {
8891 mono_class_setup_interfaces (klass, &error);
8892 if (!mono_error_ok (&error)) {
8893 mono_error_cleanup (&error);
8897 /* start from the first */
8898 if (klass->interface_count) {
8899 *iter = &klass->interfaces [0];
8900 return klass->interfaces [0];
8908 if (iface < &klass->interfaces [klass->interface_count]) {
8916 setup_nested_types (MonoClass *klass)
8919 GList *classes, *nested_classes, *l;
8922 if (klass->nested_classes_inited)
8925 if (!klass->type_token)
8926 klass->nested_classes_inited = TRUE;
8928 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8932 guint32 cols [MONO_NESTED_CLASS_SIZE];
8933 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8934 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8935 if (!mono_error_ok (&error)) {
8936 /*FIXME don't swallow the error message*/
8937 mono_error_cleanup (&error);
8939 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8943 classes = g_list_prepend (classes, nclass);
8945 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8948 mono_class_alloc_ext (klass);
8950 nested_classes = NULL;
8951 for (l = classes; l; l = l->next)
8952 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
8953 g_list_free (classes);
8955 mono_image_lock (klass->image);
8957 mono_memory_barrier ();
8958 if (!klass->nested_classes_inited) {
8959 klass->ext->nested_classes = nested_classes;
8960 mono_memory_barrier ();
8961 klass->nested_classes_inited = TRUE;
8964 mono_image_unlock (klass->image);
8968 * mono_class_get_nested_types
8969 * @klass: the MonoClass to act on
8971 * This routine is an iterator routine for retrieving the nested types of a class.
8972 * This works only if @klass is non-generic, or a generic type definition.
8974 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8975 * iterate over all of the elements. When no more values are
8976 * available, the return value is NULL.
8978 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8981 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8987 if (!klass->nested_classes_inited)
8988 setup_nested_types (klass);
8991 /* start from the first */
8992 if (klass->ext && klass->ext->nested_classes) {
8993 *iter = klass->ext->nested_classes;
8994 return klass->ext->nested_classes->data;
8996 /* no nested types */
9011 * mono_class_is_delegate
9012 * @klass: the MonoClass to act on
9014 * Returns: true if the MonoClass represents a System.Delegate.
9017 mono_class_is_delegate (MonoClass *klass)
9019 return klass->delegate;
9023 * mono_class_implements_interface
9024 * @klass: The MonoClass to act on
9025 * @interface: The interface to check if @klass implements.
9027 * Returns: true if @klass implements @interface.
9030 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9032 return mono_class_is_assignable_from (iface, klass);
9036 * mono_field_get_name:
9037 * @field: the MonoClassField to act on
9039 * Returns: the name of the field.
9042 mono_field_get_name (MonoClassField *field)
9048 * mono_field_get_type:
9049 * @field: the MonoClassField to act on
9051 * Returns: MonoType of the field.
9054 mono_field_get_type (MonoClassField *field)
9057 MonoType *type = mono_field_get_type_checked (field, &error);
9058 if (!mono_error_ok (&error)) {
9059 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9060 mono_error_cleanup (&error);
9067 * mono_field_get_type_checked:
9068 * @field: the MonoClassField to act on
9069 * @error: used to return any erro found while retrieving @field type
9071 * Returns: MonoType of the field.
9074 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9076 mono_error_init (error);
9078 mono_field_resolve_type (field, error);
9083 * mono_field_get_parent:
9084 * @field: the MonoClassField to act on
9086 * Returns: MonoClass where the field was defined.
9089 mono_field_get_parent (MonoClassField *field)
9091 return field->parent;
9095 * mono_field_get_flags;
9096 * @field: the MonoClassField to act on
9098 * The metadata flags for a field are encoded using the
9099 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9101 * Returns: the flags for the field.
9104 mono_field_get_flags (MonoClassField *field)
9107 return mono_field_resolve_flags (field);
9108 return field->type->attrs;
9112 * mono_field_get_offset;
9113 * @field: the MonoClassField to act on
9115 * Returns: the field offset.
9118 mono_field_get_offset (MonoClassField *field)
9120 return field->offset;
9124 mono_field_get_rva (MonoClassField *field)
9128 MonoClass *klass = field->parent;
9129 MonoFieldDefaultValue *field_def_values;
9131 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9133 if (!klass->ext || !klass->ext->field_def_values) {
9134 mono_class_alloc_ext (klass);
9136 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9138 mono_image_lock (klass->image);
9139 if (!klass->ext->field_def_values)
9140 klass->ext->field_def_values = field_def_values;
9141 mono_image_unlock (klass->image);
9144 field_index = mono_field_get_index (field);
9146 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9147 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9149 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9150 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9153 return klass->ext->field_def_values [field_index].data;
9157 * mono_field_get_data;
9158 * @field: the MonoClassField to act on
9160 * Returns: pointer to the metadata constant value or to the field
9161 * data if it has an RVA flag.
9164 mono_field_get_data (MonoClassField *field)
9166 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9167 MonoTypeEnum def_type;
9169 return mono_class_get_field_default_value (field, &def_type);
9170 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9171 return mono_field_get_rva (field);
9178 * mono_property_get_name:
9179 * @prop: the MonoProperty to act on
9181 * Returns: the name of the property
9184 mono_property_get_name (MonoProperty *prop)
9190 * mono_property_get_set_method
9191 * @prop: the MonoProperty to act on.
9193 * Returns: the setter method of the property (A MonoMethod)
9196 mono_property_get_set_method (MonoProperty *prop)
9202 * mono_property_get_get_method
9203 * @prop: the MonoProperty to act on.
9205 * Returns: the setter method of the property (A MonoMethod)
9208 mono_property_get_get_method (MonoProperty *prop)
9214 * mono_property_get_parent:
9215 * @prop: the MonoProperty to act on.
9217 * Returns: the MonoClass where the property was defined.
9220 mono_property_get_parent (MonoProperty *prop)
9222 return prop->parent;
9226 * mono_property_get_flags:
9227 * @prop: the MonoProperty to act on.
9229 * The metadata flags for a property are encoded using the
9230 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9232 * Returns: the flags for the property.
9235 mono_property_get_flags (MonoProperty *prop)
9241 * mono_event_get_name:
9242 * @event: the MonoEvent to act on
9244 * Returns: the name of the event.
9247 mono_event_get_name (MonoEvent *event)
9253 * mono_event_get_add_method:
9254 * @event: The MonoEvent to act on.
9256 * Returns: the @add' method for the event (a MonoMethod).
9259 mono_event_get_add_method (MonoEvent *event)
9265 * mono_event_get_remove_method:
9266 * @event: The MonoEvent to act on.
9268 * Returns: the @remove method for the event (a MonoMethod).
9271 mono_event_get_remove_method (MonoEvent *event)
9273 return event->remove;
9277 * mono_event_get_raise_method:
9278 * @event: The MonoEvent to act on.
9280 * Returns: the @raise method for the event (a MonoMethod).
9283 mono_event_get_raise_method (MonoEvent *event)
9285 return event->raise;
9289 * mono_event_get_parent:
9290 * @event: the MonoEvent to act on.
9292 * Returns: the MonoClass where the event is defined.
9295 mono_event_get_parent (MonoEvent *event)
9297 return event->parent;
9301 * mono_event_get_flags
9302 * @event: the MonoEvent to act on.
9304 * The metadata flags for an event are encoded using the
9305 * EVENT_* constants. See the tabledefs.h file for details.
9307 * Returns: the flags for the event.
9310 mono_event_get_flags (MonoEvent *event)
9312 return event->attrs;
9316 * mono_class_get_method_from_name:
9317 * @klass: where to look for the method
9318 * @name: name of the method
9319 * @param_count: number of parameters. -1 for any number.
9321 * Obtains a MonoMethod with a given name and number of parameters.
9322 * It only works if there are no multiple signatures for any given method name.
9325 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9327 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9331 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9333 MonoMethod *res = NULL;
9336 /* Search directly in the metadata to avoid calling setup_methods () */
9337 for (i = 0; i < klass->method.count; ++i) {
9338 guint32 cols [MONO_METHOD_SIZE];
9340 MonoMethodSignature *sig;
9342 /* class->method.first points into the methodptr table */
9343 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9345 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9346 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9347 if (param_count == -1) {
9351 sig = mono_method_signature (method);
9352 if (sig && sig->param_count == param_count) {
9363 * mono_class_get_method_from_name_flags:
9364 * @klass: where to look for the method
9365 * @name_space: name of the method
9366 * @param_count: number of parameters. -1 for any number.
9367 * @flags: flags which must be set in the method
9369 * Obtains a MonoMethod with a given name and number of parameters.
9370 * It only works if there are no multiple signatures for any given method name.
9373 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9375 MonoMethod *res = NULL;
9378 mono_class_init (klass);
9380 if (klass->generic_class && !klass->methods) {
9381 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9383 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9387 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9388 mono_class_setup_methods (klass);
9390 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9391 See mono/tests/array_load_exception.il
9392 FIXME we should better report this error to the caller
9394 if (!klass->methods)
9396 for (i = 0; i < klass->method.count; ++i) {
9397 MonoMethod *method = klass->methods [i];
9399 if (method->name[0] == name [0] &&
9400 !strcmp (name, method->name) &&
9401 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9402 ((method->flags & flags) == flags)) {
9409 res = find_method_in_metadata (klass, name, param_count, flags);
9416 * mono_class_set_failure:
9417 * @klass: class in which the failure was detected
9418 * @ex_type: the kind of exception/error to be thrown (later)
9419 * @ex_data: exception data (specific to each type of exception/error)
9421 * Keep a detected failure informations in the class for later processing.
9422 * Note that only the first failure is kept.
9424 * LOCKING: Acquires the loader lock.
9427 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9429 if (klass->exception_type)
9432 mono_loader_lock ();
9433 klass->exception_type = ex_type;
9435 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9436 mono_loader_unlock ();
9442 * mono_class_get_exception_data:
9444 * Return the exception_data property of KLASS.
9446 * LOCKING: Acquires the loader lock.
9449 mono_class_get_exception_data (MonoClass *klass)
9451 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9455 * mono_classes_init:
9457 * Initialize the resources used by this module.
9460 mono_classes_init (void)
9462 mono_mutex_init (&classes_mutex);
9464 mono_counters_register ("Inflated methods size",
9465 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9466 mono_counters_register ("Inflated classes",
9467 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9468 mono_counters_register ("Inflated classes size",
9469 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9470 mono_counters_register ("MonoClass size",
9471 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9472 mono_counters_register ("MonoClassExt size",
9473 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9477 * mono_classes_cleanup:
9479 * Free the resources used by this module.
9482 mono_classes_cleanup (void)
9484 if (global_interface_bitset)
9485 mono_bitset_free (global_interface_bitset);
9486 global_interface_bitset = NULL;
9487 mono_mutex_destroy (&classes_mutex);
9491 * mono_class_get_exception_for_failure:
9492 * @klass: class in which the failure was detected
9494 * Return a constructed MonoException than the caller can then throw
9495 * using mono_raise_exception - or NULL if no failure is present (or
9496 * doesn't result in an exception).
9499 mono_class_get_exception_for_failure (MonoClass *klass)
9501 gpointer exception_data = mono_class_get_exception_data (klass);
9503 switch (klass->exception_type) {
9504 #ifndef DISABLE_SECURITY
9505 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9506 MonoDomain *domain = mono_domain_get ();
9507 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9508 MonoMethod *method = exception_data;
9509 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9510 MonoObject *exc = NULL;
9514 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9515 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9516 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9518 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9519 return (MonoException*) exc;
9522 case MONO_EXCEPTION_TYPE_LOAD: {
9525 char *str = mono_type_get_full_name (klass);
9526 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9527 name = mono_string_new (mono_domain_get (), str);
9529 ex = mono_get_exception_type_load (name, astr);
9533 case MONO_EXCEPTION_MISSING_METHOD: {
9534 char *class_name = exception_data;
9535 char *assembly_name = class_name + strlen (class_name) + 1;
9537 return mono_get_exception_missing_method (class_name, assembly_name);
9539 case MONO_EXCEPTION_MISSING_FIELD: {
9540 char *class_name = exception_data;
9541 char *member_name = class_name + strlen (class_name) + 1;
9543 return mono_get_exception_missing_field (class_name, member_name);
9545 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9546 char *msg_format = exception_data;
9547 char *assembly_name = msg_format + strlen (msg_format) + 1;
9548 char *msg = g_strdup_printf (msg_format, assembly_name);
9551 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9557 case MONO_EXCEPTION_BAD_IMAGE: {
9558 return mono_get_exception_bad_image_format (exception_data);
9561 MonoLoaderError *error;
9564 error = mono_loader_get_last_error ();
9566 ex = mono_loader_error_prepare_exception (error);
9570 /* TODO - handle other class related failures */
9577 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9579 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9580 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9582 if (outer_klass == inner_klass)
9584 inner_klass = inner_klass->nested_in;
9585 } while (inner_klass);
9590 mono_class_get_generic_type_definition (MonoClass *klass)
9592 return klass->generic_class ? klass->generic_class->container_class : klass;
9596 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9598 * Generic instantiations are ignored for all super types of @klass.
9600 * Visibility checks ignoring generic instantiations.
9603 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9606 klass = mono_class_get_generic_type_definition (klass);
9607 parent = mono_class_get_generic_type_definition (parent);
9608 mono_class_setup_supertypes (klass);
9610 for (i = 0; i < klass->idepth; ++i) {
9611 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9617 * Subtype can only access parent members with family protection if the site object
9618 * is subclass of Subtype. For example:
9619 * class A { protected int x; }
9621 * void valid_access () {
9625 * void invalid_access () {
9632 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9634 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9637 if (context_klass == NULL)
9639 /*if access_klass is not member_klass context_klass must be type compat*/
9640 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9646 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9649 if (accessing == accessed)
9651 if (!accessed || !accessing)
9654 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9655 * anywhere so untrusted friends are not safe to access platform's code internals */
9656 if (mono_security_core_clr_enabled ()) {
9657 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9661 mono_assembly_load_friends (accessed);
9662 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9663 MonoAssemblyName *friend = tmp->data;
9664 /* Be conservative with checks */
9667 if (strcmp (accessing->aname.name, friend->name))
9669 if (friend->public_key_token [0]) {
9670 if (!accessing->aname.public_key_token [0])
9672 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9681 * If klass is a generic type or if it is derived from a generic type, return the
9682 * MonoClass of the generic definition
9683 * Returns NULL if not found
9686 get_generic_definition_class (MonoClass *klass)
9689 if (klass->generic_class && klass->generic_class->container_class)
9690 return klass->generic_class->container_class;
9691 klass = klass->parent;
9697 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9700 for (i = 0; i < ginst->type_argc; ++i) {
9701 MonoType *type = ginst->type_argv[i];
9702 switch (type->type) {
9703 case MONO_TYPE_SZARRAY:
9704 if (!can_access_type (access_klass, type->data.klass))
9707 case MONO_TYPE_ARRAY:
9708 if (!can_access_type (access_klass, type->data.array->eklass))
9712 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9715 case MONO_TYPE_CLASS:
9716 case MONO_TYPE_VALUETYPE:
9717 case MONO_TYPE_GENERICINST:
9718 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9726 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9730 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9733 if (access_klass->element_class && !access_klass->enumtype)
9734 access_klass = access_klass->element_class;
9736 if (member_klass->element_class && !member_klass->enumtype)
9737 member_klass = member_klass->element_class;
9739 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9741 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9744 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9747 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9750 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9753 /*Non nested type with nested visibility. We just fail it.*/
9754 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9757 switch (access_level) {
9758 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9759 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9761 case TYPE_ATTRIBUTE_PUBLIC:
9764 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9767 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9768 return is_nesting_type (member_klass, access_klass);
9770 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9771 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9773 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9774 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9776 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9777 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9778 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9780 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9781 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9782 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9787 /* FIXME: check visibility of type, too */
9789 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9791 MonoClass *member_generic_def;
9792 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9795 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9796 access_klass->generic_container) &&
9797 (member_generic_def = get_generic_definition_class (member_klass))) {
9798 MonoClass *access_container;
9800 if (access_klass->generic_container)
9801 access_container = access_klass;
9803 access_container = access_klass->generic_class->container_class;
9805 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9809 /* Partition I 8.5.3.2 */
9810 /* the access level values are the same for fields and methods */
9811 switch (access_level) {
9812 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9813 /* same compilation unit */
9814 return access_klass->image == member_klass->image;
9815 case FIELD_ATTRIBUTE_PRIVATE:
9816 return access_klass == member_klass;
9817 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9818 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9819 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9822 case FIELD_ATTRIBUTE_ASSEMBLY:
9823 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9824 case FIELD_ATTRIBUTE_FAMILY:
9825 if (is_valid_family_access (access_klass, member_klass, context_klass))
9828 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9829 if (is_valid_family_access (access_klass, member_klass, context_klass))
9831 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9832 case FIELD_ATTRIBUTE_PUBLIC:
9839 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9841 /* FIXME: check all overlapping fields */
9842 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9844 MonoClass *nested = method->klass->nested_in;
9846 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9849 nested = nested->nested_in;
9856 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9858 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9860 MonoClass *nested = method->klass->nested_in;
9862 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9865 nested = nested->nested_in;
9870 * with generics calls to explicit interface implementations can be expressed
9871 * directly: the method is private, but we must allow it. This may be opening
9872 * a hole or the generics code should handle this differently.
9873 * Maybe just ensure the interface type is public.
9875 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9881 * mono_method_can_access_method_full:
9882 * @method: The caller method
9883 * @called: The called method
9884 * @context_klass: The static type on stack of the owner @called object used
9886 * This function must be used with instance calls, as they have more strict family accessibility.
9887 * It can be used with static methods, but context_klass should be NULL.
9889 * Returns: TRUE if caller have proper visibility and acessibility to @called
9892 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9894 MonoClass *access_class = method->klass;
9895 MonoClass *member_class = called->klass;
9896 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9898 MonoClass *nested = access_class->nested_in;
9900 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9903 nested = nested->nested_in;
9910 can = can_access_type (access_class, member_class);
9912 MonoClass *nested = access_class->nested_in;
9914 can = can_access_type (nested, member_class);
9917 nested = nested->nested_in;
9924 if (called->is_inflated) {
9925 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9926 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9935 * mono_method_can_access_field_full:
9936 * @method: The caller method
9937 * @field: The accessed field
9938 * @context_klass: The static type on stack of the owner @field object used
9940 * This function must be used with instance fields, as they have more strict family accessibility.
9941 * It can be used with static fields, but context_klass should be NULL.
9943 * Returns: TRUE if caller have proper visibility and acessibility to @field
9946 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9948 MonoClass *access_class = method->klass;
9949 MonoClass *member_class = field->parent;
9950 /* FIXME: check all overlapping fields */
9951 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9953 MonoClass *nested = access_class->nested_in;
9955 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9958 nested = nested->nested_in;
9965 can = can_access_type (access_class, member_class);
9967 MonoClass *nested = access_class->nested_in;
9969 can = can_access_type (nested, member_class);
9972 nested = nested->nested_in;
9982 * mono_class_can_access_class:
9983 * @source_class: The source class
9984 * @target_class: The accessed class
9986 * This function returns is @target_class is visible to @source_class
9988 * Returns: TRUE if source have proper visibility and acessibility to target
9991 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9993 return can_access_type (source_class, target_class);
9997 * mono_type_is_valid_enum_basetype:
9998 * @type: The MonoType to check
10000 * Returns: TRUE if the type can be used as the basetype of an enum
10002 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10003 switch (type->type) {
10006 case MONO_TYPE_BOOLEAN:
10009 case MONO_TYPE_CHAR:
10022 * mono_class_is_valid_enum:
10023 * @klass: An enum class to be validated
10025 * This method verify the required properties an enum should have.
10027 * Returns: TRUE if the informed enum class is valid
10029 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10030 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10031 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10033 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10034 MonoClassField * field;
10035 gpointer iter = NULL;
10036 gboolean found_base_field = FALSE;
10038 g_assert (klass->enumtype);
10039 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10040 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10044 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10047 while ((field = mono_class_get_fields (klass, &iter))) {
10048 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10049 if (found_base_field)
10051 found_base_field = TRUE;
10052 if (!mono_type_is_valid_enum_basetype (field->type))
10057 if (!found_base_field)
10060 if (klass->method.count > 0)
10067 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10069 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10073 * mono_class_setup_interface_id:
10075 * Initializes MonoClass::interface_id if required.
10077 * LOCKING: Acquires the loader lock.
10080 mono_class_setup_interface_id (MonoClass *class)
10082 mono_loader_lock ();
10083 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10084 class->interface_id = mono_get_unique_iid (class);
10085 mono_loader_unlock ();
10089 * mono_class_alloc_ext:
10091 * Allocate klass->ext if not already done.
10094 mono_class_alloc_ext (MonoClass *klass)
10101 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10102 mono_image_lock (klass->image);
10103 mono_memory_barrier ();
10106 class_ext_size += sizeof (MonoClassExt);
10107 mono_image_unlock (klass->image);
10111 * mono_class_setup_interfaces:
10113 * Initialize class->interfaces/interfaces_count.
10114 * LOCKING: Acquires the loader lock.
10115 * This function can fail the type.
10118 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10120 int i, interface_count;
10121 MonoClass **interfaces;
10123 mono_error_init (error);
10125 if (klass->interfaces_inited)
10128 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10129 MonoType *args [1];
10131 /* generic IList, ICollection, IEnumerable */
10132 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10133 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10135 args [0] = &klass->element_class->byval_arg;
10136 interfaces [0] = mono_class_bind_generic_parameters (
10137 mono_defaults.generic_ilist_class, 1, args, FALSE);
10138 if (interface_count > 1)
10139 interfaces [1] = mono_class_bind_generic_parameters (
10140 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10141 } else if (klass->generic_class) {
10142 MonoClass *gklass = klass->generic_class->container_class;
10144 mono_class_setup_interfaces (gklass, error);
10145 if (!mono_error_ok (error)) {
10146 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10150 interface_count = gklass->interface_count;
10151 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10152 for (i = 0; i < interface_count; i++) {
10153 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10154 if (!mono_error_ok (error)) {
10155 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10160 interface_count = 0;
10164 mono_image_lock (klass->image);
10166 if (!klass->interfaces_inited) {
10167 klass->interface_count = interface_count;
10168 klass->interfaces = interfaces;
10170 mono_memory_barrier ();
10172 klass->interfaces_inited = TRUE;
10175 mono_image_unlock (klass->image);
10179 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10181 MonoClass *class = field->parent;
10182 MonoImage *image = class->image;
10183 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10184 int field_idx = field - class->fields;
10186 mono_error_init (error);
10189 MonoClassField *gfield = >d->fields [field_idx];
10190 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10191 if (!mono_error_ok (error)) {
10192 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10193 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10197 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10198 if (!mono_error_ok (error)) {
10199 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10200 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10205 guint32 cols [MONO_FIELD_SIZE];
10206 MonoGenericContainer *container = NULL;
10207 int idx = class->field.first + field_idx;
10209 /*FIXME, in theory we do not lazy load SRE fields*/
10210 g_assert (!image_is_dynamic (image));
10212 if (class->generic_container) {
10213 container = class->generic_container;
10215 container = gtd->generic_container;
10216 g_assert (container);
10219 /* class->field.first and idx points into the fieldptr table */
10220 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10222 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10223 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10224 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10228 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10230 mono_metadata_decode_value (sig, &sig);
10231 /* FIELD signature == 0x06 */
10232 g_assert (*sig == 0x06);
10233 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10235 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10240 mono_field_resolve_flags (MonoClassField *field)
10242 MonoClass *class = field->parent;
10243 MonoImage *image = class->image;
10244 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10245 int field_idx = field - class->fields;
10249 MonoClassField *gfield = >d->fields [field_idx];
10250 return mono_field_get_flags (gfield);
10252 int idx = class->field.first + field_idx;
10254 /*FIXME, in theory we do not lazy load SRE fields*/
10255 g_assert (!image_is_dynamic (image));
10257 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10262 * mono_class_setup_basic_field_info:
10263 * @class: The class to initialize
10265 * Initializes the class->fields array of fields.
10266 * Aquires the loader lock.
10269 mono_class_setup_basic_field_info_locking (MonoClass *class)
10271 mono_loader_lock ();
10272 mono_class_setup_basic_field_info (class);
10273 mono_loader_unlock ();
10277 * mono_class_get_fields_lazy:
10278 * @klass: the MonoClass to act on
10280 * This routine is an iterator routine for retrieving the fields in a class.
10281 * Only minimal information about fields are loaded. Accessors must be used
10282 * for all MonoClassField returned.
10284 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10285 * iterate over all of the elements. When no more values are
10286 * available, the return value is NULL.
10288 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10291 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10293 MonoClassField* field;
10297 mono_class_setup_basic_field_info_locking (klass);
10298 if (!klass->fields)
10300 /* start from the first */
10301 if (klass->field.count) {
10302 return *iter = &klass->fields [0];
10310 if (field < &klass->fields [klass->field.count]) {
10311 return *iter = field;
10317 mono_class_full_name (MonoClass *klass)
10319 return mono_type_full_name (&klass->byval_arg);