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_loader_lock ();
2185 if (class->methods) {
2186 mono_loader_unlock ();
2190 class->method.count = count;
2192 /* Needed because of the double-checking locking pattern */
2193 mono_memory_barrier ();
2195 class->methods = methods;
2197 mono_loader_unlock ();
2201 * mono_class_get_method_by_index:
2203 * Returns class->methods [index], initializing class->methods if neccesary.
2205 * LOCKING: Acquires the loader lock.
2208 mono_class_get_method_by_index (MonoClass *class, int index)
2210 /* Avoid calling setup_methods () if possible */
2211 if (class->generic_class && !class->methods) {
2212 MonoClass *gklass = class->generic_class->container_class;
2215 m = mono_class_inflate_generic_method_full (
2216 gklass->methods [index], class, mono_class_get_context (class));
2218 * If setup_methods () is called later for this class, no duplicates are created,
2219 * since inflate_generic_method guarantees that only one instance of a method
2220 * is created for each context.
2223 mono_class_setup_methods (class);
2224 g_assert (m == class->methods [index]);
2228 mono_class_setup_methods (class);
2229 if (class->exception_type) /*FIXME do proper error handling*/
2231 g_assert (index >= 0 && index < class->method.count);
2232 return class->methods [index];
2237 * mono_class_get_inflated_method:
2239 * Given an inflated class CLASS and a method METHOD which should be a method of
2240 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2243 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2245 MonoClass *gklass = class->generic_class->container_class;
2248 g_assert (method->klass == gklass);
2250 mono_class_setup_methods (gklass);
2251 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2253 for (i = 0; i < gklass->method.count; ++i) {
2254 if (gklass->methods [i] == method) {
2256 return class->methods [i];
2258 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2266 * mono_class_get_vtable_entry:
2268 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2269 * LOCKING: Acquires the loader lock.
2272 mono_class_get_vtable_entry (MonoClass *class, int offset)
2276 if (class->rank == 1) {
2278 * szarrays do not overwrite any methods of Array, so we can avoid
2279 * initializing their vtables in some cases.
2281 mono_class_setup_vtable (class->parent);
2282 if (offset < class->parent->vtable_size)
2283 return class->parent->vtable [offset];
2286 if (class->generic_class) {
2287 MonoClass *gklass = class->generic_class->container_class;
2288 mono_class_setup_vtable (gklass);
2289 m = gklass->vtable [offset];
2291 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2293 mono_class_setup_vtable (class);
2294 if (class->exception_type)
2296 m = class->vtable [offset];
2303 * mono_class_get_vtable_size:
2305 * Return the vtable size for KLASS.
2308 mono_class_get_vtable_size (MonoClass *klass)
2310 mono_class_setup_vtable (klass);
2312 return klass->vtable_size;
2316 * mono_class_setup_properties:
2318 * Initialize class->ext.property and class->ext.properties.
2320 * This method can fail the class.
2323 mono_class_setup_properties (MonoClass *class)
2325 guint startm, endm, i, j;
2326 guint32 cols [MONO_PROPERTY_SIZE];
2327 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2328 MonoProperty *properties;
2332 if (class->ext && class->ext->properties)
2335 if (class->generic_class) {
2336 MonoClass *gklass = class->generic_class->container_class;
2338 mono_class_init (gklass);
2339 mono_class_setup_properties (gklass);
2340 if (gklass->exception_type) {
2341 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2345 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2347 for (i = 0; i < gklass->ext->property.count; i++) {
2348 MonoProperty *prop = &properties [i];
2350 *prop = gklass->ext->properties [i];
2353 prop->get = mono_class_inflate_generic_method_full (
2354 prop->get, class, mono_class_get_context (class));
2356 prop->set = mono_class_inflate_generic_method_full (
2357 prop->set, class, mono_class_get_context (class));
2359 prop->parent = class;
2362 first = gklass->ext->property.first;
2363 count = gklass->ext->property.count;
2365 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2366 count = last - first;
2369 mono_class_setup_methods (class);
2370 if (class->exception_type)
2374 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2375 for (i = first; i < last; ++i) {
2376 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2377 properties [i - first].parent = class;
2378 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2379 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2381 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2382 for (j = startm; j < endm; ++j) {
2385 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2387 if (class->image->uncompressed_metadata)
2388 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2389 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2391 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2393 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2394 case METHOD_SEMANTIC_SETTER:
2395 properties [i - first].set = method;
2397 case METHOD_SEMANTIC_GETTER:
2398 properties [i - first].get = method;
2407 mono_loader_lock ();
2409 if (class->ext && class->ext->properties) {
2410 /* We leak 'properties' which was allocated from the image mempool */
2411 mono_loader_unlock ();
2415 mono_class_alloc_ext (class);
2417 class->ext->property.first = first;
2418 class->ext->property.count = count;
2420 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2421 mono_memory_barrier ();
2423 /* Leave this assignment as the last op in the function */
2424 class->ext->properties = properties;
2426 mono_loader_unlock ();
2430 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2432 MonoMethod **om, **retval;
2435 for (om = methods, count = 0; *om; ++om, ++count)
2438 retval = g_new0 (MonoMethod*, count + 1);
2440 for (om = methods, count = 0; *om; ++om, ++count)
2441 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2446 /*This method can fail the class.*/
2448 mono_class_setup_events (MonoClass *class)
2451 guint startm, endm, i, j;
2452 guint32 cols [MONO_EVENT_SIZE];
2453 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2457 if (class->ext && class->ext->events)
2460 if (class->generic_class) {
2461 MonoClass *gklass = class->generic_class->container_class;
2462 MonoGenericContext *context;
2464 mono_class_setup_events (gklass);
2465 if (gklass->exception_type) {
2466 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2470 first = gklass->ext->event.first;
2471 count = gklass->ext->event.count;
2473 events = mono_class_new0 (class, MonoEvent, count);
2476 context = mono_class_get_context (class);
2478 for (i = 0; i < count; i++) {
2479 MonoEvent *event = &events [i];
2480 MonoEvent *gevent = &gklass->ext->events [i];
2482 event->parent = class;
2483 event->name = gevent->name;
2484 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2485 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2486 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2487 #ifndef MONO_SMALL_CONFIG
2488 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2490 event->attrs = gevent->attrs;
2493 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2494 count = last - first;
2497 mono_class_setup_methods (class);
2498 if (class->exception_type) {
2499 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2504 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2505 for (i = first; i < last; ++i) {
2506 MonoEvent *event = &events [i - first];
2508 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2509 event->parent = class;
2510 event->attrs = cols [MONO_EVENT_FLAGS];
2511 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2513 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2514 for (j = startm; j < endm; ++j) {
2517 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2519 if (class->image->uncompressed_metadata)
2520 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2521 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2523 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2525 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2526 case METHOD_SEMANTIC_ADD_ON:
2527 event->add = method;
2529 case METHOD_SEMANTIC_REMOVE_ON:
2530 event->remove = method;
2532 case METHOD_SEMANTIC_FIRE:
2533 event->raise = method;
2535 case METHOD_SEMANTIC_OTHER: {
2536 #ifndef MONO_SMALL_CONFIG
2539 if (event->other == NULL) {
2540 event->other = g_new0 (MonoMethod*, 2);
2542 while (event->other [n])
2544 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2546 event->other [n] = method;
2547 /* NULL terminated */
2548 event->other [n + 1] = NULL;
2559 mono_loader_lock ();
2561 if (class->ext && class->ext->events) {
2562 mono_loader_unlock ();
2566 mono_class_alloc_ext (class);
2568 class->ext->event.first = first;
2569 class->ext->event.count = count;
2571 /* Flush any pending writes as we do double checked locking on class->ext.events */
2572 mono_memory_barrier ();
2574 /* Leave this assignment as the last op in the function */
2575 class->ext->events = events;
2577 mono_loader_unlock ();
2581 * Global pool of interface IDs, represented as a bitset.
2582 * LOCKING: Protected by the classes lock.
2584 static MonoBitSet *global_interface_bitset = NULL;
2587 * mono_unload_interface_ids:
2588 * @bitset: bit set of interface IDs
2590 * When an image is unloaded, the interface IDs associated with
2591 * the image are put back in the global pool of IDs so the numbers
2595 mono_unload_interface_ids (MonoBitSet *bitset)
2598 mono_bitset_sub (global_interface_bitset, bitset);
2603 mono_unload_interface_id (MonoClass *class)
2605 if (global_interface_bitset && class->interface_id) {
2607 mono_bitset_clear (global_interface_bitset, class->interface_id);
2613 * mono_get_unique_iid:
2616 * Assign a unique integer ID to the interface represented by @class.
2617 * The ID will positive and as small as possible.
2618 * LOCKING: Acquires the classes lock.
2619 * Returns: the new ID.
2622 mono_get_unique_iid (MonoClass *class)
2626 g_assert (MONO_CLASS_IS_INTERFACE (class));
2630 if (!global_interface_bitset) {
2631 global_interface_bitset = mono_bitset_new (128, 0);
2634 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2636 int old_size = mono_bitset_size (global_interface_bitset);
2637 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2638 mono_bitset_free (global_interface_bitset);
2639 global_interface_bitset = new_set;
2642 mono_bitset_set (global_interface_bitset, iid);
2643 /* set the bit also in the per-image set */
2644 if (!class->generic_class) {
2645 if (class->image->interface_bitset) {
2646 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2647 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2648 mono_bitset_free (class->image->interface_bitset);
2649 class->image->interface_bitset = new_set;
2652 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2654 mono_bitset_set (class->image->interface_bitset, iid);
2659 #ifndef MONO_SMALL_CONFIG
2660 if (mono_print_vtable) {
2662 char *type_name = mono_type_full_name (&class->byval_arg);
2663 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2664 generic_id = class->generic_class->context.class_inst->id;
2665 g_assert (generic_id != 0);
2669 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2674 g_assert (iid <= 65535);
2679 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2684 mono_class_setup_interfaces (klass, error);
2685 if (!mono_error_ok (error))
2688 for (i = 0; i < klass->interface_count; i++) {
2689 ic = klass->interfaces [i];
2692 *res = g_ptr_array_new ();
2693 g_ptr_array_add (*res, ic);
2694 mono_class_init (ic);
2695 if (ic->exception_type) {
2696 mono_error_set_type_load_class (error, ic, "Error Loading class");
2700 collect_implemented_interfaces_aux (ic, res, error);
2701 if (!mono_error_ok (error))
2707 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2709 GPtrArray *res = NULL;
2711 collect_implemented_interfaces_aux (klass, &res, error);
2712 if (!mono_error_ok (error)) {
2714 g_ptr_array_free (res, TRUE);
2721 compare_interface_ids (const void *p_key, const void *p_element) {
2722 const MonoClass *key = p_key;
2723 const MonoClass *element = *(MonoClass**) p_element;
2725 return (key->interface_id - element->interface_id);
2728 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2730 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2731 MonoClass **result = mono_binary_search (
2733 klass->interfaces_packed,
2734 klass->interface_offsets_count,
2735 sizeof (MonoClass *),
2736 compare_interface_ids);
2738 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2745 * mono_class_interface_offset_with_variance:
2747 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2748 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2750 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2752 * FIXME figure out MS disambiguation rules and fix this function.
2755 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2756 int i = mono_class_interface_offset (klass, itf);
2757 *non_exact_match = FALSE;
2761 if (!mono_class_has_variant_generic_params (itf))
2764 for (i = 0; i < klass->interface_offsets_count; i++) {
2765 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2766 *non_exact_match = TRUE;
2767 return klass->interface_offsets_packed [i];
2775 print_implemented_interfaces (MonoClass *klass) {
2778 GPtrArray *ifaces = NULL;
2780 int ancestor_level = 0;
2782 name = mono_type_get_full_name (klass);
2783 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2786 for (i = 0; i < klass->interface_offsets_count; i++)
2787 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2788 klass->interfaces_packed [i]->interface_id,
2789 klass->interface_offsets_packed [i],
2790 klass->interfaces_packed [i]->method.count,
2791 klass->interfaces_packed [i]->name_space,
2792 klass->interfaces_packed [i]->name );
2793 printf ("Interface flags: ");
2794 for (i = 0; i <= klass->max_interface_id; i++)
2795 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2796 printf ("(%d,T)", i);
2798 printf ("(%d,F)", i);
2800 printf ("Dump interface flags:");
2801 #ifdef COMPRESSED_INTERFACE_BITMAP
2803 const uint8_t* p = klass->interface_bitmap;
2804 i = klass->max_interface_id;
2806 printf (" %d x 00 %02X", p [0], p [1]);
2812 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2813 printf (" %02X", klass->interface_bitmap [i]);
2816 while (klass != NULL) {
2817 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2818 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2819 if (!mono_error_ok (&error)) {
2820 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2821 mono_error_cleanup (&error);
2822 } else if (ifaces) {
2823 for (i = 0; i < ifaces->len; i++) {
2824 MonoClass *ic = g_ptr_array_index (ifaces, i);
2825 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2826 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2828 mono_class_interface_offset (klass, ic),
2833 g_ptr_array_free (ifaces, TRUE);
2836 klass = klass->parent;
2841 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2844 args [0] = &arg0->byval_arg;
2846 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2850 array_class_get_if_rank (MonoClass *class, guint rank)
2852 return rank ? mono_array_class_get (class, rank) : class;
2856 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2858 valuetype_types [0] = eclass;
2859 if (eclass == mono_defaults.int16_class)
2860 valuetype_types [1] = mono_defaults.uint16_class;
2861 else if (eclass == mono_defaults.uint16_class)
2862 valuetype_types [1] = mono_defaults.int16_class;
2863 else if (eclass == mono_defaults.int32_class)
2864 valuetype_types [1] = mono_defaults.uint32_class;
2865 else if (eclass == mono_defaults.uint32_class)
2866 valuetype_types [1] = mono_defaults.int32_class;
2867 else if (eclass == mono_defaults.int64_class)
2868 valuetype_types [1] = mono_defaults.uint64_class;
2869 else if (eclass == mono_defaults.uint64_class)
2870 valuetype_types [1] = mono_defaults.int64_class;
2871 else if (eclass == mono_defaults.byte_class)
2872 valuetype_types [1] = mono_defaults.sbyte_class;
2873 else if (eclass == mono_defaults.sbyte_class)
2874 valuetype_types [1] = mono_defaults.byte_class;
2875 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2876 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2879 /* this won't be needed once bug #325495 is completely fixed
2880 * though we'll need something similar to know which interfaces to allow
2881 * in arrays when they'll be lazyly created
2883 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2884 * MS returns diferrent types based on which instance is called. For example:
2885 * object obj = new byte[10][];
2886 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2887 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2890 * Fixing this should kill quite some code, save some bits and improve compatibility.
2893 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2895 MonoClass *eclass = class->element_class;
2896 static MonoClass* generic_icollection_class = NULL;
2897 static MonoClass* generic_ienumerable_class = NULL;
2898 static MonoClass* generic_ienumerator_class = NULL;
2899 static MonoClass* generic_ireadonlylist_class = NULL;
2900 static MonoClass* generic_ireadonlycollection_class = NULL;
2901 MonoClass *valuetype_types[2] = { NULL, NULL };
2902 MonoClass **interfaces = NULL;
2903 int i, nifaces, interface_count, real_count, original_rank;
2905 gboolean internal_enumerator;
2906 gboolean eclass_is_valuetype;
2908 if (!mono_defaults.generic_ilist_class) {
2912 internal_enumerator = FALSE;
2913 eclass_is_valuetype = FALSE;
2914 original_rank = eclass->rank;
2915 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2916 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2918 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2920 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2921 original_rank = eclass->rank;
2923 eclass = eclass->element_class;
2924 internal_enumerator = TRUE;
2925 *is_enumerator = TRUE;
2933 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2934 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2936 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2938 if (!generic_icollection_class) {
2939 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2940 "System.Collections.Generic", "ICollection`1");
2941 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2942 "System.Collections.Generic", "IEnumerable`1");
2943 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2944 "System.Collections.Generic", "IEnumerator`1");
2945 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2946 "System.Collections.Generic", "IReadOnlyList`1");
2947 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2948 "System.Collections.Generic", "IReadOnlyCollection`1");
2951 mono_class_init (eclass);
2954 * Arrays in 2.0 need to implement a number of generic interfaces
2955 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2956 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2957 * We collect the types needed to build the
2958 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2959 * the generic interfaces needed to implement.
2961 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2962 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2964 if (eclass->valuetype) {
2965 nifaces = generic_ireadonlylist_class ? 5 : 3;
2966 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2968 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2969 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2970 if (internal_enumerator) {
2972 if (valuetype_types [1])
2976 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2977 interfaces [0] = valuetype_types [0];
2978 if (valuetype_types [1])
2979 interfaces [nifaces] = valuetype_types [1];
2981 eclass_is_valuetype = TRUE;
2984 int idepth = eclass->idepth;
2985 if (!internal_enumerator)
2987 nifaces = generic_ireadonlylist_class ? 2 : 3;
2989 // FIXME: This doesn't seem to work/required for generic params
2990 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
2991 mono_class_setup_interface_offsets (eclass);
2993 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2994 /* we add object for interfaces and the supertypes for the other
2995 * types. The last of the supertypes is the element class itself which we
2996 * already created the explicit interfaces for (so we include it for IEnumerator
2997 * and exclude it for arrays).
2999 if (MONO_CLASS_IS_INTERFACE (eclass))
3002 interface_count += idepth;
3003 if (eclass->rank && eclass->element_class->valuetype) {
3004 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3005 if (valuetype_types [1])
3008 /* IList, ICollection, IEnumerable, IReadOnlyList */
3009 interface_count *= nifaces;
3010 real_count = interface_count;
3011 if (internal_enumerator) {
3012 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3013 if (valuetype_types [1])
3016 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3017 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3018 interfaces [0] = mono_defaults.object_class;
3022 for (i = 0; i < idepth; i++) {
3023 mono_class_init (eclass->supertypes [i]);
3024 interfaces [j] = eclass->supertypes [i];
3028 if (all_interfaces) {
3029 for (i = 0; i < eclass->interface_offsets_count; i++) {
3030 interfaces [j] = eclass->interfaces_packed [i];
3034 for (i = 0; i < eclass->interface_count; i++) {
3035 interfaces [j] = eclass->interfaces [i];
3039 if (valuetype_types [1]) {
3040 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3045 /* instantiate the generic interfaces */
3046 for (i = 0; i < interface_count; i += nifaces) {
3047 MonoClass *iface = interfaces [i];
3049 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3050 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3052 if (eclass->valuetype) {
3053 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3054 if (generic_ireadonlylist_class) {
3055 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3056 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3059 if (!generic_ireadonlylist_class)
3060 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3063 if (internal_enumerator) {
3065 /* instantiate IEnumerator<iface> */
3066 for (i = 0; i < interface_count; i++) {
3067 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3069 j = interface_count;
3070 if (!eclass_is_valuetype) {
3071 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3072 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3075 for (i = 0; i < eclass->idepth; i++) {
3076 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3080 for (i = 0; i < eclass->interface_offsets_count; i++) {
3081 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3085 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3087 if (valuetype_types [1])
3088 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3092 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3093 for (i = 0; i < real_count; ++i) {
3094 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3095 g_print ("%s implements %s\n", type_name, name);
3106 find_array_interface (MonoClass *klass, const char *name)
3109 for (i = 0; i < klass->interface_count; ++i) {
3110 if (strcmp (klass->interfaces [i]->name, name) == 0)
3117 * Return the number of virtual methods.
3118 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3119 * Return -1 on failure.
3120 * FIXME It would be nice if this information could be cached somewhere.
3123 count_virtual_methods (MonoClass *class)
3127 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3129 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3130 mono_class_setup_methods (class);
3131 if (class->exception_type)
3134 for (i = 0; i < class->method.count; ++i) {
3135 flags = class->methods [i]->flags;
3136 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3140 for (i = 0; i < class->method.count; ++i) {
3141 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3143 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3151 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3159 m = (l + num_ifaces) / 2;
3160 if (interfaces_full [m] == ic)
3162 if (l == num_ifaces)
3164 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3173 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3175 int i = find_interface (num_ifaces, interfaces_full, ic);
3177 return interface_offsets_full [i];
3182 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3184 int i = find_interface (num_ifaces, interfaces_full, ic);
3188 interface_offsets_full [i] = offset;
3191 for (i = 0; i < num_ifaces; ++i) {
3192 if (interfaces_full [i]) {
3194 if (interfaces_full [i]->interface_id < ic->interface_id)
3197 while (end < num_ifaces && interfaces_full [end]) end++;
3198 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3199 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3201 interfaces_full [i] = ic;
3202 interface_offsets_full [i] = offset;
3208 #ifdef COMPRESSED_INTERFACE_BITMAP
3211 * Compressed interface bitmap design.
3213 * Interface bitmaps take a large amount of memory, because their size is
3214 * linear with the maximum interface id assigned in the process (each interface
3215 * is assigned a unique id as it is loaded). The number of interface classes
3216 * is high because of the many implicit interfaces implemented by arrays (we'll
3217 * need to lazy-load them in the future).
3218 * Most classes implement a very small number of interfaces, so the bitmap is
3219 * sparse. This bitmap needs to be checked by interface casts, so access to the
3220 * needed bit must be fast and doable with few jit instructions.
3222 * The current compression format is as follows:
3223 * *) it is a sequence of one or more two-byte elements
3224 * *) the first byte in the element is the count of empty bitmap bytes
3225 * at the current bitmap position
3226 * *) the second byte in the element is an actual bitmap byte at the current
3229 * As an example, the following compressed bitmap bytes:
3230 * 0x07 0x01 0x00 0x7
3231 * correspond to the following bitmap:
3232 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3234 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3235 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3236 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3240 * mono_compress_bitmap:
3241 * @dest: destination buffer
3242 * @bitmap: bitmap buffer
3243 * @size: size of @bitmap in bytes
3245 * This is a mono internal function.
3246 * The @bitmap data is compressed into a format that is small but
3247 * still searchable in few instructions by the JIT and runtime.
3248 * The compressed data is stored in the buffer pointed to by the
3249 * @dest array. Passing a #NULL value for @dest allows to just compute
3250 * the size of the buffer.
3251 * This compression algorithm assumes the bits set in the bitmap are
3252 * few and far between, like in interface bitmaps.
3253 * Returns: the size of the compressed bitmap in bytes.
3256 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3260 const uint8_t *end = bitmap + size;
3261 while (bitmap < end) {
3262 if (*bitmap || numz == 255) {
3286 * mono_class_interface_match:
3287 * @bitmap: a compressed bitmap buffer
3288 * @id: the index to check in the bitmap
3290 * This is a mono internal function.
3291 * Checks if a bit is set in a compressed interface bitmap. @id must
3292 * be already checked for being smaller than the maximum id encoded in the
3295 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3299 mono_class_interface_match (const uint8_t *bitmap, int id)
3302 id -= bitmap [0] * 8;
3306 return bitmap [1] & (1 << id);
3315 * LOCKING: this is supposed to be called with the loader lock held.
3316 * Return -1 on failure and set exception_type
3319 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3323 int i, j, max_iid, num_ifaces;
3324 MonoClass **interfaces_full = NULL;
3325 int *interface_offsets_full = NULL;
3327 GPtrArray **ifaces_array = NULL;
3328 int interface_offsets_count;
3329 MonoClass **array_interfaces = NULL;
3330 int num_array_interfaces;
3331 int is_enumerator = FALSE;
3333 mono_class_setup_supertypes (class);
3335 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3336 * implicit interfaces have the property that they are assigned the same slot in the
3337 * vtables for compatible interfaces
3339 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3341 /* compute maximum number of slots and maximum interface id */
3343 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3344 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3345 for (j = 0; j < class->idepth; j++) {
3346 k = class->supertypes [j];
3347 num_ifaces += k->interface_count;
3348 for (i = 0; i < k->interface_count; i++) {
3349 ic = k->interfaces [i];
3352 mono_class_init (ic);
3354 if (max_iid < ic->interface_id)
3355 max_iid = ic->interface_id;
3357 ifaces = mono_class_get_implemented_interfaces (k, &error);
3358 if (!mono_error_ok (&error)) {
3359 char *name = mono_type_get_full_name (k);
3360 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)));
3362 mono_error_cleanup (&error);
3367 num_ifaces += ifaces->len;
3368 for (i = 0; i < ifaces->len; ++i) {
3369 ic = g_ptr_array_index (ifaces, i);
3370 if (max_iid < ic->interface_id)
3371 max_iid = ic->interface_id;
3373 ifaces_array [j] = ifaces;
3377 for (i = 0; i < num_array_interfaces; ++i) {
3378 ic = array_interfaces [i];
3379 mono_class_init (ic);
3380 if (max_iid < ic->interface_id)
3381 max_iid = ic->interface_id;
3384 if (MONO_CLASS_IS_INTERFACE (class)) {
3386 if (max_iid < class->interface_id)
3387 max_iid = class->interface_id;
3389 class->max_interface_id = max_iid;
3390 /* compute vtable offset for interfaces */
3391 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3392 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3394 for (i = 0; i < num_ifaces; i++) {
3395 interface_offsets_full [i] = -1;
3398 /* skip the current class */
3399 for (j = 0; j < class->idepth - 1; j++) {
3400 k = class->supertypes [j];
3401 ifaces = ifaces_array [j];
3404 for (i = 0; i < ifaces->len; ++i) {
3406 ic = g_ptr_array_index (ifaces, i);
3408 /*Force the sharing of interface offsets between parent and subtypes.*/
3409 io = mono_class_interface_offset (k, ic);
3411 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3416 g_assert (class == class->supertypes [class->idepth - 1]);
3417 ifaces = ifaces_array [class->idepth - 1];
3419 for (i = 0; i < ifaces->len; ++i) {
3421 ic = g_ptr_array_index (ifaces, i);
3422 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3424 count = count_virtual_methods (ic);
3426 char *name = mono_type_get_full_name (ic);
3427 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3436 if (MONO_CLASS_IS_INTERFACE (class))
3437 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3439 if (num_array_interfaces) {
3440 if (is_enumerator) {
3441 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3442 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3443 g_assert (ienumerator_offset >= 0);
3444 for (i = 0; i < num_array_interfaces; ++i) {
3445 ic = array_interfaces [i];
3446 if (strcmp (ic->name, "IEnumerator`1") == 0)
3447 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3449 g_assert_not_reached ();
3450 /*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);*/
3453 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3454 int ilist_iface_idx = find_array_interface (class, "IList`1");
3455 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3456 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3457 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3458 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3459 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3460 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3461 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3462 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3463 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3464 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3465 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3466 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3467 for (i = 0; i < num_array_interfaces; ++i) {
3469 ic = array_interfaces [i];
3470 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3471 offset = ilist_offset;
3472 else if (strcmp (ic->name, "ICollection`1") == 0)
3473 offset = icollection_offset;
3474 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3475 offset = ienumerable_offset;
3476 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3477 offset = ireadonlylist_offset;
3478 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3479 offset = ireadonlycollection_offset;
3481 g_assert_not_reached ();
3482 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3483 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3488 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3489 if (interface_offsets_full [i] != -1) {
3490 interface_offsets_count ++;
3495 * We might get called multiple times:
3496 * - mono_class_init ()
3497 * - mono_class_setup_vtable ().
3498 * - mono_class_setup_interface_offsets ().
3499 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3500 * means we have to overwrite those when called from other places (#4440).
3502 if (class->interfaces_packed && !overwrite) {
3503 g_assert (class->interface_offsets_count == interface_offsets_count);
3507 class->interface_offsets_count = interface_offsets_count;
3508 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3509 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3510 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3511 #ifdef COMPRESSED_INTERFACE_BITMAP
3512 bitmap = g_malloc0 (bsize);
3514 bitmap = mono_class_alloc0 (class, bsize);
3516 for (i = 0; i < interface_offsets_count; i++) {
3517 int id = interfaces_full [i]->interface_id;
3518 bitmap [id >> 3] |= (1 << (id & 7));
3519 class->interfaces_packed [i] = interfaces_full [i];
3520 class->interface_offsets_packed [i] = interface_offsets_full [i];
3521 /*if (num_array_interfaces)
3522 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]);*/
3524 #ifdef COMPRESSED_INTERFACE_BITMAP
3525 i = mono_compress_bitmap (NULL, bitmap, bsize);
3526 class->interface_bitmap = mono_class_alloc0 (class, i);
3527 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3530 class->interface_bitmap = bitmap;
3535 g_free (interfaces_full);
3536 g_free (interface_offsets_full);
3537 g_free (array_interfaces);
3538 for (i = 0; i < class->idepth; i++) {
3539 ifaces = ifaces_array [i];
3541 g_ptr_array_free (ifaces, TRUE);
3543 g_free (ifaces_array);
3545 //printf ("JUST DONE: ");
3546 //print_implemented_interfaces (class);
3552 * Setup interface offsets for interfaces.
3554 * - class->max_interface_id
3555 * - class->interface_offsets_count
3556 * - class->interfaces_packed
3557 * - class->interface_offsets_packed
3558 * - class->interface_bitmap
3560 * This function can fail @class.
3563 mono_class_setup_interface_offsets (MonoClass *class)
3565 mono_loader_lock ();
3567 setup_interface_offsets (class, 0, FALSE);
3569 mono_loader_unlock ();
3572 /*Checks if @klass has @parent as one of it's parents type gtd
3576 * Bar<T> : Foo<Bar<Bar<T>>>
3580 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3582 klass = mono_class_get_generic_type_definition (klass);
3583 parent = mono_class_get_generic_type_definition (parent);
3584 mono_class_setup_supertypes (klass);
3585 mono_class_setup_supertypes (parent);
3587 return klass->idepth >= parent->idepth &&
3588 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3592 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3594 MonoGenericInst *ginst;
3596 if (!class->generic_class) {
3597 mono_class_setup_vtable_full (class, in_setup);
3598 return class->exception_type == 0;
3601 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3602 if (class->generic_class->container_class->exception_type) {
3603 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3607 ginst = class->generic_class->context.class_inst;
3608 for (i = 0; i < ginst->type_argc; ++i) {
3610 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3612 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3613 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3614 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3616 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3617 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3625 * mono_class_setup_vtable:
3627 * Creates the generic vtable of CLASS.
3628 * Initializes the following fields in MonoClass:
3631 * Plus all the fields initialized by setup_interface_offsets ().
3632 * If there is an error during vtable construction, class->exception_type is set.
3634 * LOCKING: Acquires the loader lock.
3637 mono_class_setup_vtable (MonoClass *class)
3639 mono_class_setup_vtable_full (class, NULL);
3643 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3645 MonoMethod **overrides;
3646 MonoGenericContext *context;
3654 if (MONO_CLASS_IS_INTERFACE (class)) {
3655 /* This sets method->slot for all methods if this is an interface */
3656 mono_class_setup_methods (class);
3660 if (class->exception_type)
3663 if (g_list_find (in_setup, class))
3666 mono_loader_lock ();
3668 if (class->vtable) {
3669 mono_loader_unlock ();
3673 mono_stats.generic_vtable_count ++;
3674 in_setup = g_list_prepend (in_setup, class);
3676 if (class->generic_class) {
3677 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3678 mono_loader_unlock ();
3679 g_list_remove (in_setup, class);
3683 context = mono_class_get_context (class);
3684 type_token = class->generic_class->container_class->type_token;
3686 context = (MonoGenericContext *) class->generic_container;
3687 type_token = class->type_token;
3690 if (image_is_dynamic (class->image)) {
3691 /* Generic instances can have zero method overrides without causing any harm.
3692 * This is true since we don't do layout all over again for them, we simply inflate
3693 * the layout of the parent.
3695 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3697 /* The following call fails if there are missing methods in the type */
3698 /* FIXME it's probably a good idea to avoid this for generic instances. */
3699 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3703 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3705 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3709 mono_loader_unlock ();
3710 g_list_remove (in_setup, class);
3715 #define DEBUG_INTERFACE_VTABLE_CODE 0
3716 #define TRACE_INTERFACE_VTABLE_CODE 0
3717 #define VERIFY_INTERFACE_VTABLE_CODE 0
3718 #define VTABLE_SELECTOR (1)
3720 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3721 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3722 if (!(VTABLE_SELECTOR)) break; \
3726 #define DEBUG_INTERFACE_VTABLE(stmt)
3729 #if TRACE_INTERFACE_VTABLE_CODE
3730 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3731 if (!(VTABLE_SELECTOR)) break; \
3735 #define TRACE_INTERFACE_VTABLE(stmt)
3738 #if VERIFY_INTERFACE_VTABLE_CODE
3739 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3740 if (!(VTABLE_SELECTOR)) break; \
3744 #define VERIFY_INTERFACE_VTABLE(stmt)
3748 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3750 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3754 GString *res = g_string_new ("");
3756 g_string_append_c (res, '(');
3757 for (i = 0; i < sig->param_count; ++i) {
3759 g_string_append_c (res, ',');
3760 mono_type_get_desc (res, sig->params [i], include_namespace);
3762 g_string_append (res, ")=>");
3763 if (sig->ret != NULL) {
3764 mono_type_get_desc (res, sig->ret, include_namespace);
3766 g_string_append (res, "NULL");
3769 g_string_free (res, FALSE);
3773 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3774 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3775 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3776 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3784 is_wcf_hack_disabled (void)
3786 static gboolean disabled;
3787 static gboolean inited = FALSE;
3789 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3796 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) {
3797 MonoMethodSignature *cmsig, *imsig;
3798 if (strcmp (im->name, cm->name) == 0) {
3799 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3800 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3803 if (! slot_is_empty) {
3804 if (require_newslot) {
3805 if (! interface_is_explicitly_implemented_by_class) {
3806 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3809 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3810 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3814 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3817 cmsig = mono_method_signature (cm);
3818 imsig = mono_method_signature (im);
3819 if (!cmsig || !imsig) {
3820 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3824 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3825 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3826 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3827 TRACE_INTERFACE_VTABLE (printf ("]"));
3830 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3831 /* CAS - SecurityAction.InheritanceDemand on interface */
3832 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3833 mono_secman_inheritancedemand_method (cm, im);
3836 if (mono_security_core_clr_enabled ())
3837 mono_security_core_clr_check_override (class, cm, im);
3839 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3840 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3841 char *body_name = mono_method_full_name (cm, TRUE);
3842 char *decl_name = mono_method_full_name (im, TRUE);
3843 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));
3851 MonoClass *ic = im->klass;
3852 const char *ic_name_space = ic->name_space;
3853 const char *ic_name = ic->name;
3856 if (! require_newslot) {
3857 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3860 if (cm->klass->rank == 0) {
3861 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3864 cmsig = mono_method_signature (cm);
3865 imsig = mono_method_signature (im);
3866 if (!cmsig || !imsig) {
3867 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3871 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3872 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3873 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3874 TRACE_INTERFACE_VTABLE (printf ("]"));
3877 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3878 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3881 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3882 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3885 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))) {
3886 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3890 subname = strstr (cm->name, ic_name_space);
3891 if (subname != cm->name) {
3892 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3895 subname += strlen (ic_name_space);
3896 if (subname [0] != '.') {
3897 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3901 if (strstr (subname, ic_name) != subname) {
3902 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3905 subname += strlen (ic_name);
3906 if (subname [0] != '.') {
3907 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3911 if (strcmp (subname, im->name) != 0) {
3912 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3916 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3917 /* CAS - SecurityAction.InheritanceDemand on interface */
3918 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3919 mono_secman_inheritancedemand_method (cm, im);
3922 if (mono_security_core_clr_enabled ())
3923 mono_security_core_clr_check_override (class, cm, im);
3925 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3926 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3927 char *body_name = mono_method_full_name (cm, TRUE);
3928 char *decl_name = mono_method_full_name (im, TRUE);
3929 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));
3939 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3941 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3942 MonoMethod *method = key;
3943 MonoMethod *override = value;
3944 MonoClass *method_class = mono_method_get_class (method);
3945 MonoClass *override_class = mono_method_get_class (override);
3947 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3948 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3949 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3952 print_overrides (GHashTable *override_map, const char *message) {
3954 printf ("Override map \"%s\" START:\n", message);
3955 g_hash_table_foreach (override_map, foreach_override, NULL);
3956 printf ("Override map \"%s\" END.\n", message);
3958 printf ("Override map \"%s\" EMPTY.\n", message);
3962 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3963 char *full_name = mono_type_full_name (&class->byval_arg);
3967 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3969 if (print_interfaces) {
3970 print_implemented_interfaces (class);
3971 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3974 if (class->parent) {
3975 parent_size = class->parent->vtable_size;
3979 for (i = 0; i < size; ++i) {
3980 MonoMethod *cm = vtable [i];
3981 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3982 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3984 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3992 #if VERIFY_INTERFACE_VTABLE_CODE
3994 mono_method_try_get_vtable_index (MonoMethod *method)
3996 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3997 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3998 if (imethod->declaring->is_generic)
3999 return imethod->declaring->slot;
4001 return method->slot;
4005 mono_class_verify_vtable (MonoClass *class)
4008 char *full_name = mono_type_full_name (&class->byval_arg);
4010 printf ("*** Verifying VTable of class '%s' \n", full_name);
4014 if (!class->methods)
4017 for (i = 0; i < class->method.count; ++i) {
4018 MonoMethod *cm = class->methods [i];
4021 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4025 full_name = mono_method_full_name (cm, TRUE);
4027 slot = mono_method_try_get_vtable_index (cm);
4029 if (slot >= class->vtable_size) {
4030 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4034 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4035 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4036 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4037 g_free (other_name);
4040 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4047 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4049 char *method_signature;
4052 for (index = 0; index < onum; ++index) {
4053 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4054 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4056 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4057 type_name = mono_type_full_name (&class->byval_arg);
4058 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4059 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4060 g_free (method_signature);
4062 mono_class_setup_methods (class);
4063 if (class->exception_type) {
4064 char *name = mono_type_get_full_name (class);
4065 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4069 for (index = 0; index < class->method.count; ++index) {
4070 MonoMethod *cm = class->methods [index];
4071 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4073 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4074 g_free (method_signature);
4079 mono_method_get_method_definition (MonoMethod *method)
4081 while (method->is_inflated)
4082 method = ((MonoMethodInflated*)method)->declaring;
4087 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4091 for (i = 0; i < onum; ++i) {
4092 MonoMethod *decl = overrides [i * 2];
4093 MonoMethod *body = overrides [i * 2 + 1];
4095 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4096 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4100 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4101 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4102 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4104 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4108 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4109 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4110 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4112 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4116 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4117 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4121 body = mono_method_get_method_definition (body);
4122 decl = mono_method_get_method_definition (decl);
4124 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4125 char *body_name = mono_method_full_name (body, TRUE);
4126 char *decl_name = mono_method_full_name (decl, TRUE);
4127 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));
4137 mono_class_need_stelemref_method (MonoClass *class)
4139 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4143 * LOCKING: this is supposed to be called with the loader lock held.
4146 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4150 MonoMethod **vtable;
4151 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4152 GPtrArray *ifaces = NULL;
4153 GHashTable *override_map = NULL;
4154 gboolean security_enabled = mono_security_enabled ();
4156 gpointer class_iter;
4157 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4158 int first_non_interface_slot;
4160 GSList *virt_methods = NULL, *l;
4161 int stelemref_slot = 0;
4166 if (overrides && !verify_class_overrides (class, overrides, onum))
4169 ifaces = mono_class_get_implemented_interfaces (class, &error);
4170 if (!mono_error_ok (&error)) {
4171 char *name = mono_type_get_full_name (class);
4172 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)));
4174 mono_error_cleanup (&error);
4176 } else if (ifaces) {
4177 for (i = 0; i < ifaces->len; i++) {
4178 MonoClass *ic = g_ptr_array_index (ifaces, i);
4179 max_vtsize += ic->method.count;
4181 g_ptr_array_free (ifaces, TRUE);
4185 if (class->parent) {
4186 mono_class_init (class->parent);
4187 mono_class_setup_vtable_full (class->parent, in_setup);
4189 if (class->parent->exception_type) {
4190 char *name = mono_type_get_full_name (class->parent);
4191 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4196 max_vtsize += class->parent->vtable_size;
4197 cur_slot = class->parent->vtable_size;
4200 max_vtsize += class->method.count;
4202 /*Array have a slot for stelemref*/
4203 if (mono_class_need_stelemref_method (class)) {
4204 stelemref_slot = cur_slot;
4209 vtable = alloca (sizeof (gpointer) * max_vtsize);
4210 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4212 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4214 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4215 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4218 max_iid = class->max_interface_id;
4219 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4221 /* Optimized version for generic instances */
4222 if (class->generic_class) {
4224 MonoClass *gklass = class->generic_class->container_class;
4227 mono_class_setup_vtable_full (gklass, in_setup);
4228 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4229 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4233 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4234 class->vtable_size = gklass->vtable_size;
4235 for (i = 0; i < gklass->vtable_size; ++i)
4236 if (gklass->vtable [i]) {
4237 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4238 if (!mono_error_ok (&error)) {
4239 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4240 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4242 mono_error_cleanup (&error);
4246 tmp [i]->slot = gklass->vtable [i]->slot;
4248 mono_memory_barrier ();
4249 class->vtable = tmp;
4251 /* Have to set method->slot for abstract virtual methods */
4252 if (class->methods && gklass->methods) {
4253 for (i = 0; i < class->method.count; ++i)
4254 if (class->methods [i]->slot == -1)
4255 class->methods [i]->slot = gklass->methods [i]->slot;
4261 if (class->parent && class->parent->vtable_size) {
4262 MonoClass *parent = class->parent;
4265 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4267 // Also inherit parent interface vtables, just as a starting point.
4268 // This is needed otherwise bug-77127.exe fails when the property methods
4269 // have different names in the iterface and the class, because for child
4270 // classes the ".override" information is not used anymore.
4271 for (i = 0; i < parent->interface_offsets_count; i++) {
4272 MonoClass *parent_interface = parent->interfaces_packed [i];
4273 int interface_offset = mono_class_interface_offset (class, parent_interface);
4274 /*FIXME this is now dead code as this condition will never hold true.
4275 Since interface offsets are inherited then the offset of an interface implemented
4276 by a parent will never be the out of it's vtable boundary.
4278 if (interface_offset >= parent->vtable_size) {
4279 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4282 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4283 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4284 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4285 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4286 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4287 parent_interface_offset + j, parent_interface_offset, j,
4288 interface_offset + j, interface_offset, j));
4295 /*Array have a slot for stelemref*/
4296 if (mono_class_need_stelemref_method (class)) {
4297 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4299 method->slot = stelemref_slot;
4301 g_assert (method->slot == stelemref_slot);
4303 vtable [stelemref_slot] = method;
4306 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4307 /* override interface methods */
4308 for (i = 0; i < onum; i++) {
4309 MonoMethod *decl = overrides [i*2];
4310 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4312 dslot = mono_method_get_vtable_slot (decl);
4314 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4318 dslot += mono_class_interface_offset (class, decl->klass);
4319 vtable [dslot] = overrides [i*2 + 1];
4320 vtable [dslot]->slot = dslot;
4322 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4324 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4326 if (mono_security_core_clr_enabled ())
4327 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4330 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4331 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4334 * Create a list of virtual methods to avoid calling
4335 * mono_class_get_virtual_methods () which is slow because of the metadata
4339 gpointer iter = NULL;
4342 virt_methods = NULL;
4343 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4344 virt_methods = g_slist_prepend (virt_methods, cm);
4346 if (class->exception_type)
4350 // Loop on all implemented interfaces...
4351 for (i = 0; i < class->interface_offsets_count; i++) {
4352 MonoClass *parent = class->parent;
4354 gboolean interface_is_explicitly_implemented_by_class;
4357 ic = class->interfaces_packed [i];
4358 ic_offset = mono_class_interface_offset (class, ic);
4360 mono_class_setup_methods (ic);
4361 if (ic->exception_type)
4364 // Check if this interface is explicitly implemented (instead of just inherited)
4365 if (parent != NULL) {
4366 int implemented_interfaces_index;
4367 interface_is_explicitly_implemented_by_class = FALSE;
4368 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4369 if (ic == class->interfaces [implemented_interfaces_index]) {
4370 interface_is_explicitly_implemented_by_class = TRUE;
4375 interface_is_explicitly_implemented_by_class = TRUE;
4378 // Loop on all interface methods...
4379 for (im_index = 0; im_index < ic->method.count; im_index++) {
4380 MonoMethod *im = ic->methods [im_index];
4381 int im_slot = ic_offset + im->slot;
4382 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4384 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4387 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4389 // If there is an explicit implementation, just use it right away,
4390 // otherwise look for a matching method
4391 if (override_im == NULL) {
4396 // First look for a suitable method among the class methods
4398 for (l = virt_methods; l; l = l->next) {
4400 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)));
4401 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4402 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4403 vtable [im_slot] = cm;
4404 /* Why do we need this? */
4409 TRACE_INTERFACE_VTABLE (printf ("\n"));
4410 if (class->exception_type) /*Might be set by check_interface_method_override*/
4414 // If the slot is still empty, look in all the inherited virtual methods...
4415 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4416 MonoClass *parent = class->parent;
4417 // Reverse order, so that last added methods are preferred
4418 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4419 MonoMethod *cm = parent->vtable [cm_index];
4421 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));
4422 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4423 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4424 vtable [im_slot] = cm;
4425 /* Why do we need this? */
4431 if (class->exception_type) /*Might be set by check_interface_method_override*/
4433 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4437 g_assert (vtable [im_slot] == override_im);
4442 // If the class is not abstract, check that all its interface slots are full.
4443 // The check is done here and not directly at the end of the loop above because
4444 // it can happen (for injected generic array interfaces) that the same slot is
4445 // processed multiple times (those interfaces have overlapping slots), and it
4446 // will not always be the first pass the one that fills the slot.
4447 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4448 for (i = 0; i < class->interface_offsets_count; i++) {
4452 ic = class->interfaces_packed [i];
4453 ic_offset = mono_class_interface_offset (class, ic);
4455 for (im_index = 0; im_index < ic->method.count; im_index++) {
4456 MonoMethod *im = ic->methods [im_index];
4457 int im_slot = ic_offset + im->slot;
4459 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4462 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4463 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4464 if (vtable [im_slot] == NULL) {
4465 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4472 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4474 for (l = virt_methods; l; l = l->next) {
4477 * If the method is REUSE_SLOT, we must check in the
4478 * base class for a method to override.
4480 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4482 for (k = class->parent; k ; k = k->parent) {
4487 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4488 MonoMethodSignature *cmsig, *m1sig;
4490 cmsig = mono_method_signature (cm);
4491 m1sig = mono_method_signature (m1);
4493 if (!cmsig || !m1sig) {
4494 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4498 if (!strcmp(cm->name, m1->name) &&
4499 mono_metadata_signature_equal (cmsig, m1sig)) {
4501 /* CAS - SecurityAction.InheritanceDemand */
4502 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4503 mono_secman_inheritancedemand_method (cm, m1);
4506 if (mono_security_core_clr_enabled ())
4507 mono_security_core_clr_check_override (class, cm, m1);
4509 slot = mono_method_get_vtable_slot (m1);
4513 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4514 char *body_name = mono_method_full_name (cm, TRUE);
4515 char *decl_name = mono_method_full_name (m1, TRUE);
4516 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));
4522 g_assert (cm->slot < max_vtsize);
4524 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4525 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4526 mono_method_full_name (m1, 1), m1,
4527 mono_method_full_name (cm, 1), cm));
4528 g_hash_table_insert (override_map, m1, cm);
4532 if (k->exception_type)
4542 /*Non final newslot methods must be given a non-interface vtable slot*/
4543 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4547 cm->slot = cur_slot++;
4549 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4550 vtable [cm->slot] = cm;
4553 /* override non interface methods */
4554 for (i = 0; i < onum; i++) {
4555 MonoMethod *decl = overrides [i*2];
4556 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4557 g_assert (decl->slot != -1);
4558 vtable [decl->slot] = overrides [i*2 + 1];
4559 overrides [i * 2 + 1]->slot = decl->slot;
4561 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4562 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4563 mono_method_full_name (decl, 1), decl,
4564 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4565 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4567 if (mono_security_core_clr_enabled ())
4568 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4573 * If a method occupies more than one place in the vtable, and it is
4574 * overriden, then change the other occurances too.
4579 for (i = 0; i < max_vtsize; ++i)
4581 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4583 cm = g_hash_table_lookup (override_map, vtable [i]);
4588 g_hash_table_destroy (override_map);
4589 override_map = NULL;
4592 g_slist_free (virt_methods);
4593 virt_methods = NULL;
4595 /* Ensure that all vtable slots are filled with concrete instance methods */
4596 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4597 for (i = 0; i < cur_slot; ++i) {
4598 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4599 char *type_name = mono_type_get_full_name (class);
4600 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4601 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));
4603 g_free (method_name);
4609 if (class->generic_class) {
4610 MonoClass *gklass = class->generic_class->container_class;
4612 mono_class_init (gklass);
4614 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4616 /* Check that the vtable_size value computed in mono_class_init () is correct */
4617 if (class->vtable_size)
4618 g_assert (cur_slot == class->vtable_size);
4619 class->vtable_size = cur_slot;
4622 /* Try to share the vtable with our parent. */
4623 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4624 mono_memory_barrier ();
4625 class->vtable = class->parent->vtable;
4627 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4628 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4629 mono_memory_barrier ();
4630 class->vtable = tmp;
4633 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4634 if (mono_print_vtable) {
4637 print_implemented_interfaces (class);
4639 for (i = 0; i <= max_iid; i++)
4640 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4643 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4644 class->vtable_size, icount);
4646 for (i = 0; i < cur_slot; ++i) {
4651 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4652 mono_method_full_name (cm, TRUE));
4658 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4659 class->name, max_iid);
4661 for (i = 0; i < class->interface_count; i++) {
4662 ic = class->interfaces [i];
4663 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4664 mono_class_interface_offset (class, ic),
4665 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4668 for (k = class->parent; k ; k = k->parent) {
4669 for (i = 0; i < k->interface_count; i++) {
4670 ic = k->interfaces [i];
4671 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4672 mono_class_interface_offset (class, ic),
4673 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4679 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4684 char *name = mono_type_get_full_name (class);
4685 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4688 g_hash_table_destroy (override_map);
4690 g_slist_free (virt_methods);
4695 * mono_method_get_vtable_slot:
4697 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4698 * LOCKING: Acquires the loader lock.
4700 * FIXME Use proper MonoError machinery here.
4703 mono_method_get_vtable_slot (MonoMethod *method)
4705 if (method->slot == -1) {
4706 mono_class_setup_vtable (method->klass);
4707 if (method->klass->exception_type)
4709 if (method->slot == -1) {
4713 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4714 g_assert (method->klass->generic_class);
4715 gklass = method->klass->generic_class->container_class;
4716 mono_class_setup_methods (method->klass);
4717 g_assert (method->klass->methods);
4718 for (i = 0; i < method->klass->method.count; ++i) {
4719 if (method->klass->methods [i] == method)
4722 g_assert (i < method->klass->method.count);
4723 g_assert (gklass->methods);
4724 method->slot = gklass->methods [i]->slot;
4726 g_assert (method->slot != -1);
4728 return method->slot;
4732 * mono_method_get_vtable_index:
4735 * Returns the index into the runtime vtable to access the method or,
4736 * in the case of a virtual generic method, the virtual generic method
4737 * thunk. Returns -1 on failure.
4739 * FIXME Use proper MonoError machinery here.
4742 mono_method_get_vtable_index (MonoMethod *method)
4744 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4745 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4746 if (imethod->declaring->is_generic)
4747 return mono_method_get_vtable_slot (imethod->declaring);
4749 return mono_method_get_vtable_slot (method);
4752 static MonoMethod *default_ghc = NULL;
4753 static MonoMethod *default_finalize = NULL;
4754 static int finalize_slot = -1;
4755 static int ghc_slot = -1;
4758 initialize_object_slots (MonoClass *class)
4763 if (class == mono_defaults.object_class) {
4764 mono_class_setup_vtable (class);
4765 for (i = 0; i < class->vtable_size; ++i) {
4766 MonoMethod *cm = class->vtable [i];
4768 if (!strcmp (cm->name, "GetHashCode"))
4770 else if (!strcmp (cm->name, "Finalize"))
4774 g_assert (ghc_slot > 0);
4775 default_ghc = class->vtable [ghc_slot];
4777 g_assert (finalize_slot > 0);
4778 default_finalize = class->vtable [finalize_slot];
4783 MonoMethod *array_method;
4785 } GenericArrayMethodInfo;
4787 static int generic_array_method_num = 0;
4788 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4791 generic_array_methods (MonoClass *class)
4793 int i, count_generic = 0;
4794 GList *list = NULL, *tmp;
4795 if (generic_array_method_num)
4796 return generic_array_method_num;
4797 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4798 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4799 for (i = 0; i < class->parent->method.count; i++) {
4800 MonoMethod *m = class->parent->methods [i];
4801 if (!strncmp (m->name, "InternalArray__", 15)) {
4803 list = g_list_prepend (list, m);
4806 list = g_list_reverse (list);
4807 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4809 for (tmp = list; tmp; tmp = tmp->next) {
4810 const char *mname, *iname;
4812 MonoMethod *m = tmp->data;
4813 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4814 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4816 generic_array_method_info [i].array_method = m;
4817 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4818 iname = "System.Collections.Generic.ICollection`1.";
4819 mname = m->name + 27;
4820 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4821 iname = "System.Collections.Generic.IEnumerable`1.";
4822 mname = m->name + 27;
4823 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4824 iname = "System.Collections.Generic.IReadOnlyList`1.";
4825 mname = m->name + strlen (ireadonlylist_prefix);
4826 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4827 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4828 mname = m->name + strlen (ireadonlycollection_prefix);
4829 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4830 iname = "System.Collections.Generic.IList`1.";
4831 mname = m->name + 15;
4833 g_assert_not_reached ();
4836 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4837 strcpy (name, iname);
4838 strcpy (name + strlen (iname), mname);
4839 generic_array_method_info [i].name = name;
4842 /*g_print ("array generic methods: %d\n", count_generic);*/
4844 generic_array_method_num = count_generic;
4846 return generic_array_method_num;
4850 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4852 MonoGenericContext tmp_context;
4855 tmp_context.class_inst = NULL;
4856 tmp_context.method_inst = iface->generic_class->context.class_inst;
4857 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4859 for (i = 0; i < generic_array_method_num; i++) {
4860 MonoMethod *m = generic_array_method_info [i].array_method;
4861 MonoMethod *inflated;
4863 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4864 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4869 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4871 int null_length = strlen ("(null)");
4872 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4873 char *s = mono_image_alloc (image, len);
4876 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4877 g_assert (result == len - 1);
4883 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4885 gpointer exception_data = NULL;
4887 switch (error->exception_type) {
4888 case MONO_EXCEPTION_TYPE_LOAD:
4889 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4892 case MONO_EXCEPTION_MISSING_METHOD:
4893 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4896 case MONO_EXCEPTION_MISSING_FIELD: {
4897 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4898 const char *class_name;
4901 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4903 class_name = error->klass->name;
4905 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4908 g_free ((void*)class_name);
4912 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4915 if (error->ref_only)
4916 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.";
4918 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4920 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4924 case MONO_EXCEPTION_BAD_IMAGE:
4925 exception_data = error->msg;
4929 g_assert_not_reached ();
4932 mono_class_set_failure (class, error->exception_type, exception_data);
4937 * @class: the class to initialize
4939 * Compute the instance_size, class_size and other infos that cannot be
4940 * computed at mono_class_get() time. Also compute vtable_size if possible.
4941 * Returns TRUE on success or FALSE if there was a problem in loading
4942 * the type (incorrect assemblies, missing assemblies, methods, etc).
4944 * LOCKING: Acquires the loader lock.
4947 mono_class_init (MonoClass *class)
4950 MonoCachedClassInfo cached_info;
4951 gboolean has_cached_info;
4955 /* Double-checking locking pattern */
4956 if (class->inited || class->exception_type)
4957 return class->exception_type == MONO_EXCEPTION_NONE;
4959 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4961 /* We do everything inside the lock to prevent races */
4962 mono_loader_lock ();
4964 if (class->inited || class->exception_type) {
4965 mono_loader_unlock ();
4966 /* Somebody might have gotten in before us */
4967 return class->exception_type == MONO_EXCEPTION_NONE;
4970 if (class->init_pending) {
4971 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4975 class->init_pending = 1;
4977 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4978 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4983 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4984 MonoClass *element_class = class->element_class;
4985 if (!element_class->inited)
4986 mono_class_init (element_class);
4987 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4988 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4993 /* CAS - SecurityAction.InheritanceDemand */
4994 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4995 mono_secman_inheritancedemand_class (class, class->parent);
4998 mono_stats.initialized_class_count++;
5000 if (class->generic_class && !class->generic_class->is_dynamic) {
5001 MonoClass *gklass = class->generic_class->container_class;
5003 mono_stats.generic_class_count++;
5005 class->method = gklass->method;
5006 class->field = gklass->field;
5008 mono_class_init (gklass);
5009 // FIXME: Why is this needed ?
5010 if (!gklass->exception_type)
5011 mono_class_setup_methods (gklass);
5012 if (gklass->exception_type) {
5013 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5017 if (MONO_CLASS_IS_INTERFACE (class))
5018 class->interface_id = mono_get_unique_iid (class);
5021 if (class->parent && !class->parent->inited)
5022 mono_class_init (class->parent);
5024 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5026 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5027 class->nested_classes_inited = TRUE;
5030 * Computes the size used by the fields, and their locations
5032 if (has_cached_info) {
5033 class->instance_size = cached_info.instance_size;
5034 class->sizes.class_size = cached_info.class_size;
5035 class->packing_size = cached_info.packing_size;
5036 class->min_align = cached_info.min_align;
5037 class->blittable = cached_info.blittable;
5038 class->has_references = cached_info.has_references;
5039 class->has_static_refs = cached_info.has_static_refs;
5040 class->no_special_static_fields = cached_info.no_special_static_fields;
5043 if (!class->size_inited){
5044 mono_class_setup_fields (class);
5045 if (class->exception_type || mono_loader_get_last_error ())
5049 /* Initialize arrays */
5051 class->method.count = 3 + (class->rank > 1? 2: 1);
5053 if (class->interface_count) {
5054 int count_generic = generic_array_methods (class);
5055 class->method.count += class->interface_count * count_generic;
5059 mono_class_setup_supertypes (class);
5062 initialize_object_slots (class);
5065 * Initialize the rest of the data without creating a generic vtable if possible.
5066 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5067 * also avoid computing a generic vtable.
5069 if (has_cached_info) {
5071 class->vtable_size = cached_info.vtable_size;
5072 class->has_finalize = cached_info.has_finalize;
5073 class->has_finalize_inited = TRUE;
5074 class->ghcimpl = cached_info.ghcimpl;
5075 class->has_cctor = cached_info.has_cctor;
5076 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5077 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5078 * The first slot if for array with.
5080 static int szarray_vtable_size[2] = { 0 };
5082 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5085 if (!szarray_vtable_size [slot]) {
5086 mono_class_setup_vtable (class);
5087 szarray_vtable_size [slot] = class->vtable_size;
5089 class->vtable_size = szarray_vtable_size[slot];
5091 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5092 MonoClass *gklass = class->generic_class->container_class;
5094 /* Generic instance case */
5095 class->ghcimpl = gklass->ghcimpl;
5096 class->has_cctor = gklass->has_cctor;
5098 mono_class_setup_vtable (gklass);
5099 if (gklass->exception_type) {
5100 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5104 class->vtable_size = gklass->vtable_size;
5108 /* ghcimpl is not currently used
5110 if (class->parent) {
5111 MonoMethod *cmethod = class->vtable [ghc_slot];
5112 if (cmethod->is_inflated)
5113 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5114 if (cmethod == default_ghc) {
5120 /* C# doesn't allow interfaces to have cctors */
5121 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5122 MonoMethod *cmethod = NULL;
5124 if (class->type_token) {
5125 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5126 /* The find_method function ignores the 'flags' argument */
5127 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5128 class->has_cctor = 1;
5130 mono_class_setup_methods (class);
5131 if (class->exception_type)
5134 for (i = 0; i < class->method.count; ++i) {
5135 MonoMethod *method = class->methods [i];
5136 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5137 (strcmp (".cctor", method->name) == 0)) {
5138 class->has_cctor = 1;
5146 if (class->parent) {
5147 int first_iface_slot;
5148 /* This will compute class->parent->vtable_size for some classes */
5149 mono_class_init (class->parent);
5150 if (class->parent->exception_type) {
5151 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5154 if (mono_loader_get_last_error ())
5156 if (!class->parent->vtable_size) {
5157 /* FIXME: Get rid of this somehow */
5158 mono_class_setup_vtable (class->parent);
5159 if (class->parent->exception_type) {
5160 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5163 if (mono_loader_get_last_error ())
5166 first_iface_slot = class->parent->vtable_size;
5167 if (mono_class_need_stelemref_method (class))
5169 setup_interface_offsets (class, first_iface_slot, TRUE);
5171 setup_interface_offsets (class, 0, TRUE);
5174 if (mono_security_core_clr_enabled ())
5175 mono_security_core_clr_check_inheritance (class);
5177 if (mono_loader_get_last_error ()) {
5178 if (class->exception_type == MONO_EXCEPTION_NONE) {
5179 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5181 mono_loader_clear_error ();
5184 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5185 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5190 /* Because of the double-checking locking pattern */
5191 mono_memory_barrier ();
5193 class->init_pending = 0;
5195 mono_loader_unlock ();
5197 if (mono_debugger_class_init_func)
5198 mono_debugger_class_init_func (class);
5200 return class->exception_type == MONO_EXCEPTION_NONE;
5204 * mono_class_has_finalizer:
5206 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5210 mono_class_has_finalizer (MonoClass *klass)
5212 MonoClass *class = klass;
5213 gboolean has_finalize = FALSE;
5215 if (klass->has_finalize_inited)
5216 return klass->has_finalize;
5218 /* Interfaces and valuetypes are not supposed to have finalizers */
5219 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5220 MonoMethod *cmethod = NULL;
5222 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5223 } else if (class->generic_class) {
5224 MonoClass *gklass = class->generic_class->container_class;
5226 has_finalize = mono_class_has_finalizer (gklass);
5227 } else if (class->parent && class->parent->has_finalize) {
5228 has_finalize = TRUE;
5230 if (class->parent) {
5232 * Can't search in metadata for a method named Finalize, because that
5233 * ignores overrides.
5235 mono_class_setup_vtable (class);
5236 if (class->exception_type || mono_loader_get_last_error ())
5239 cmethod = class->vtable [finalize_slot];
5243 g_assert (class->vtable_size > finalize_slot);
5245 if (class->parent) {
5246 if (cmethod->is_inflated)
5247 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5248 if (cmethod != default_finalize)
5249 has_finalize = TRUE;
5255 mono_loader_lock ();
5257 if (!klass->has_finalize_inited) {
5258 klass->has_finalize = has_finalize ? 1 : 0;
5260 mono_memory_barrier ();
5261 klass->has_finalize_inited = TRUE;
5264 mono_loader_unlock ();
5266 return klass->has_finalize;
5270 mono_is_corlib_image (MonoImage *image)
5272 /* FIXME: allow the dynamic case for our compilers and with full trust */
5273 if (image_is_dynamic (image))
5274 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5276 return image == mono_defaults.corlib;
5280 * LOCKING: this assumes the loader lock is held
5283 mono_class_setup_mono_type (MonoClass *class)
5285 const char *name = class->name;
5286 const char *nspace = class->name_space;
5287 gboolean is_corlib = mono_is_corlib_image (class->image);
5289 class->this_arg.byref = 1;
5290 class->this_arg.data.klass = class;
5291 class->this_arg.type = MONO_TYPE_CLASS;
5292 class->byval_arg.data.klass = class;
5293 class->byval_arg.type = MONO_TYPE_CLASS;
5295 if (is_corlib && !strcmp (nspace, "System")) {
5296 if (!strcmp (name, "ValueType")) {
5298 * do not set the valuetype bit for System.ValueType.
5299 * class->valuetype = 1;
5301 class->blittable = TRUE;
5302 } else if (!strcmp (name, "Enum")) {
5304 * do not set the valuetype bit for System.Enum.
5305 * class->valuetype = 1;
5307 class->valuetype = 0;
5308 class->enumtype = 0;
5309 } else if (!strcmp (name, "Object")) {
5310 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5311 } else if (!strcmp (name, "String")) {
5312 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5313 } else if (!strcmp (name, "TypedReference")) {
5314 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5318 if (class->valuetype) {
5319 int t = MONO_TYPE_VALUETYPE;
5321 if (is_corlib && !strcmp (nspace, "System")) {
5324 if (!strcmp (name, "Boolean")) {
5325 t = MONO_TYPE_BOOLEAN;
5326 } else if (!strcmp(name, "Byte")) {
5328 class->blittable = TRUE;
5332 if (!strcmp (name, "Char")) {
5337 if (!strcmp (name, "Double")) {
5339 class->blittable = TRUE;
5343 if (!strcmp (name, "Int32")) {
5345 class->blittable = TRUE;
5346 } else if (!strcmp(name, "Int16")) {
5348 class->blittable = TRUE;
5349 } else if (!strcmp(name, "Int64")) {
5351 class->blittable = TRUE;
5352 } else if (!strcmp(name, "IntPtr")) {
5354 class->blittable = TRUE;
5358 if (!strcmp (name, "Single")) {
5360 class->blittable = TRUE;
5361 } else if (!strcmp(name, "SByte")) {
5363 class->blittable = TRUE;
5367 if (!strcmp (name, "UInt32")) {
5369 class->blittable = TRUE;
5370 } else if (!strcmp(name, "UInt16")) {
5372 class->blittable = TRUE;
5373 } else if (!strcmp(name, "UInt64")) {
5375 class->blittable = TRUE;
5376 } else if (!strcmp(name, "UIntPtr")) {
5378 class->blittable = TRUE;
5382 if (!strcmp (name, "TypedReference")) {
5383 t = MONO_TYPE_TYPEDBYREF;
5384 class->blittable = TRUE;
5388 if (!strcmp (name, "Void")) {
5396 class->this_arg.type = class->byval_arg.type = t;
5399 if (MONO_CLASS_IS_INTERFACE (class))
5400 class->interface_id = mono_get_unique_iid (class);
5406 * COM initialization is delayed until needed.
5407 * However when a [ComImport] attribute is present on a type it will trigger
5408 * the initialization. This is not a problem unless the BCL being executed
5409 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5412 init_com_from_comimport (MonoClass *class)
5414 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5415 if (mono_security_core_clr_enabled ()) {
5416 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5417 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5418 /* but it can not be made available for application (i.e. user code) since all COM calls
5419 * are considered native calls. In this case we fail with a TypeLoadException (just like
5420 * Silverlight 2 does */
5421 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5426 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5428 #endif /*DISABLE_COM*/
5431 * LOCKING: this assumes the loader lock is held
5434 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5436 gboolean system_namespace;
5437 gboolean is_corlib = mono_is_corlib_image (class->image);
5439 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5441 /* if root of the hierarchy */
5442 if (system_namespace && !strcmp (class->name, "Object")) {
5443 class->parent = NULL;
5444 class->instance_size = sizeof (MonoObject);
5447 if (!strcmp (class->name, "<Module>")) {
5448 class->parent = NULL;
5449 class->instance_size = 0;
5453 if (!MONO_CLASS_IS_INTERFACE (class)) {
5454 /* Imported COM Objects always derive from __ComObject. */
5456 if (MONO_CLASS_IS_IMPORT (class)) {
5457 init_com_from_comimport (class);
5458 if (parent == mono_defaults.object_class)
5459 parent = mono_class_get_com_object_class ();
5463 /* set the parent to something useful and safe, but mark the type as broken */
5464 parent = mono_defaults.object_class;
5465 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5468 class->parent = parent;
5470 if (parent->generic_class && !parent->name) {
5472 * If the parent is a generic instance, we may get
5473 * called before it is fully initialized, especially
5474 * before it has its name.
5479 #ifndef DISABLE_REMOTING
5480 class->marshalbyref = parent->marshalbyref;
5481 class->contextbound = parent->contextbound;
5484 class->delegate = parent->delegate;
5486 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5487 mono_class_set_is_com_object (class);
5489 if (system_namespace) {
5490 #ifndef DISABLE_REMOTING
5491 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5492 class->marshalbyref = 1;
5494 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5495 class->contextbound = 1;
5497 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5498 class->delegate = 1;
5501 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5502 (strcmp (class->parent->name_space, "System") == 0)))
5503 class->valuetype = 1;
5504 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5505 class->valuetype = class->enumtype = 1;
5507 /*class->enumtype = class->parent->enumtype; */
5509 /* initialize com types if COM interfaces are present */
5511 if (MONO_CLASS_IS_IMPORT (class))
5512 init_com_from_comimport (class);
5514 class->parent = NULL;
5520 * mono_class_setup_supertypes:
5523 * Build the data structure needed to make fast type checks work.
5524 * This currently sets two fields in @class:
5525 * - idepth: distance between @class and System.Object in the type
5527 * - supertypes: array of classes: each element has a class in the hierarchy
5528 * starting from @class up to System.Object
5530 * LOCKING: This function is atomic, in case of contention we waste memory.
5533 mono_class_setup_supertypes (MonoClass *class)
5536 MonoClass **supertypes;
5538 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5542 if (class->parent && !class->parent->supertypes)
5543 mono_class_setup_supertypes (class->parent);
5545 class->idepth = class->parent->idepth + 1;
5549 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5550 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5552 if (class->parent) {
5553 supertypes [class->idepth - 1] = class;
5554 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5556 supertypes [0] = class;
5559 mono_atomic_store_release (&class->supertypes, supertypes);
5563 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5565 MonoClass *gtd = (MonoClass*)user_data;
5566 /* Only try to fix generic instances of @gtd */
5567 if (gclass->generic_class->container_class != gtd)
5570 /* Check if the generic instance has no parent. */
5571 if (gtd->parent && !gclass->parent)
5572 mono_generic_class_setup_parent (gclass, gtd);
5578 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5580 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5581 mono_error_set_type_load_class (error, class, msg);
5585 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5587 MonoLoaderError *lerror = mono_loader_get_last_error ();
5590 set_failure_from_loader_error (class, lerror);
5591 mono_error_set_from_loader_error (error);
5595 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5596 mono_error_set_type_load_class (error, class, msg);
5601 * mono_class_create_from_typedef:
5602 * @image: image where the token is valid
5603 * @type_token: typedef token
5604 * @error: used to return any error found while creating the type
5606 * Create the MonoClass* representing the specified type token.
5607 * @type_token must be a TypeDef token.
5609 * FIXME: don't return NULL on failure, just the the caller figure it out.
5612 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5614 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5615 MonoClass *class, *parent = NULL;
5616 guint32 cols [MONO_TYPEDEF_SIZE];
5617 guint32 cols_next [MONO_TYPEDEF_SIZE];
5618 guint tidx = mono_metadata_token_index (type_token);
5619 MonoGenericContext *context = NULL;
5620 const char *name, *nspace;
5622 MonoClass **interfaces;
5623 guint32 field_last, method_last;
5624 guint32 nesting_tokeen;
5626 mono_error_init (error);
5628 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5629 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5630 g_assert (!mono_loader_get_last_error ());
5634 mono_loader_lock ();
5636 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5637 mono_loader_unlock ();
5638 g_assert (!mono_loader_get_last_error ());
5642 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5644 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5645 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5647 class = mono_image_alloc0 (image, sizeof (MonoClass));
5650 class->name_space = nspace;
5652 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5654 class->image = image;
5655 class->type_token = type_token;
5656 class->flags = cols [MONO_TYPEDEF_FLAGS];
5658 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5660 classes_size += sizeof (MonoClass);
5663 * Check whether we're a generic type definition.
5665 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5666 if (class->generic_container) {
5667 class->is_generic = 1;
5668 class->generic_container->owner.klass = class;
5669 context = &class->generic_container->context;
5672 if (class->generic_container)
5673 enable_gclass_recording ();
5675 if (cols [MONO_TYPEDEF_EXTENDS]) {
5677 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5679 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5680 /*WARNING: this must satisfy mono_metadata_type_hash*/
5681 class->this_arg.byref = 1;
5682 class->this_arg.data.klass = class;
5683 class->this_arg.type = MONO_TYPE_CLASS;
5684 class->byval_arg.data.klass = class;
5685 class->byval_arg.type = MONO_TYPE_CLASS;
5687 parent = mono_class_get_full (image, parent_token, context);
5689 if (parent == NULL) {
5690 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5691 goto parent_failure;
5694 for (tmp = parent; tmp; tmp = tmp->parent) {
5696 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5697 goto parent_failure;
5699 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5700 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5701 goto parent_failure;
5706 mono_class_setup_parent (class, parent);
5708 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5709 mono_class_setup_mono_type (class);
5711 if (class->generic_container)
5712 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5715 * This might access class->byval_arg for recursion generated by generic constraints,
5716 * so it has to come after setup_mono_type ().
5718 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5719 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5720 if (!mono_error_ok (error)) {
5721 /*FIXME implement a mono_class_set_failure_from_mono_error */
5722 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5723 mono_loader_unlock ();
5724 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5725 g_assert (!mono_loader_get_last_error ());
5730 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5734 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5738 class->cast_class = class->element_class = class;
5740 if (!class->enumtype) {
5741 if (!mono_metadata_interfaces_from_typedef_full (
5742 image, type_token, &interfaces, &icount, FALSE, context)){
5743 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5744 mono_loader_unlock ();
5745 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5749 class->interfaces = interfaces;
5750 class->interface_count = icount;
5751 class->interfaces_inited = 1;
5754 /*g_print ("Load class %s\n", name);*/
5757 * Compute the field and method lists
5759 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5760 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5762 if (tt->rows > tidx){
5763 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5764 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5765 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5767 field_last = image->tables [MONO_TABLE_FIELD].rows;
5768 method_last = image->tables [MONO_TABLE_METHOD].rows;
5771 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5772 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5773 class->field.count = field_last - class->field.first;
5775 class->field.count = 0;
5777 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5778 class->method.count = method_last - class->method.first;
5780 class->method.count = 0;
5782 /* reserve space to store vector pointer in arrays */
5783 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5784 class->instance_size += 2 * sizeof (gpointer);
5785 g_assert (class->field.count == 0);
5788 if (class->enumtype) {
5789 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5790 if (!enum_basetype) {
5791 /*set it to a default value as the whole runtime can't handle this to be null*/
5792 class->cast_class = class->element_class = mono_defaults.int32_class;
5793 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5794 mono_loader_unlock ();
5795 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5796 g_assert (!mono_loader_get_last_error ());
5799 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5803 * If we're a generic type definition, load the constraints.
5804 * We must do this after the class has been constructed to make certain recursive scenarios
5807 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5808 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5809 mono_loader_unlock ();
5810 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5811 g_assert (!mono_loader_get_last_error ());
5815 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5816 if (!strncmp (name, "Vector", 6))
5817 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");
5820 mono_loader_unlock ();
5822 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5823 g_assert (!mono_loader_get_last_error ());
5828 mono_class_setup_mono_type (class);
5829 mono_loader_unlock ();
5830 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5831 g_assert (!mono_loader_get_last_error ());
5835 /** is klass Nullable<T>? */
5837 mono_class_is_nullable (MonoClass *klass)
5839 return klass->generic_class != NULL &&
5840 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5844 /** if klass is T? return T */
5846 mono_class_get_nullable_param (MonoClass *klass)
5848 g_assert (mono_class_is_nullable (klass));
5849 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5853 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5857 MonoGenericClass *gclass = klass->generic_class;
5859 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5860 if (!mono_error_ok (&error)) {
5861 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5862 klass->parent = mono_defaults.object_class;
5863 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5864 mono_error_cleanup (&error);
5868 mono_class_setup_parent (klass, klass->parent);
5870 if (klass->enumtype) {
5871 klass->cast_class = gtd->cast_class;
5872 klass->element_class = gtd->element_class;
5878 * Create the `MonoClass' for an instantiation of a generic type.
5879 * We only do this if we actually need it.
5882 mono_generic_class_get_class (MonoGenericClass *gclass)
5884 MonoClass *klass, *gklass;
5886 if (gclass->cached_class)
5887 return gclass->cached_class;
5889 mono_loader_lock ();
5890 if (gclass->cached_class) {
5891 mono_loader_unlock ();
5892 return gclass->cached_class;
5895 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5897 gklass = gclass->container_class;
5899 if (record_gclass_instantiation > 0)
5900 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5902 if (gklass->nested_in) {
5903 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5904 klass->nested_in = gklass->nested_in;
5907 klass->name = gklass->name;
5908 klass->name_space = gklass->name_space;
5910 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5912 klass->image = gklass->image;
5913 klass->flags = gklass->flags;
5914 klass->type_token = gklass->type_token;
5915 klass->field.count = gklass->field.count;
5917 klass->is_inflated = 1;
5918 klass->generic_class = gclass;
5920 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5921 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5922 klass->this_arg.byref = TRUE;
5923 klass->enumtype = gklass->enumtype;
5924 klass->valuetype = gklass->valuetype;
5926 klass->cast_class = klass->element_class = klass;
5928 if (mono_class_is_nullable (klass))
5929 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5932 * We're not interested in the nested classes of a generic instance.
5933 * We use the generic type definition to look for nested classes.
5936 mono_generic_class_setup_parent (klass, gklass);
5938 if (gclass->is_dynamic) {
5941 mono_class_setup_supertypes (klass);
5943 if (klass->enumtype) {
5945 * For enums, gklass->fields might not been set, but instance_size etc. is
5946 * already set in mono_reflection_create_internal_class (). For non-enums,
5947 * these will be computed normally in mono_class_layout_fields ().
5949 klass->instance_size = gklass->instance_size;
5950 klass->sizes.class_size = gklass->sizes.class_size;
5951 mono_memory_barrier ();
5952 klass->size_inited = 1;
5956 mono_memory_barrier ();
5957 gclass->cached_class = klass;
5959 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5961 inflated_classes ++;
5962 inflated_classes_size += sizeof (MonoClass);
5964 mono_loader_unlock ();
5970 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5972 MonoClass *klass, **ptr;
5974 MonoGenericContainer *container = mono_generic_param_owner (param);
5978 image = mono_defaults.corlib;
5980 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5981 classes_size += sizeof (MonoClass);
5984 klass->name = pinfo->name;
5986 int n = mono_generic_param_num (param);
5987 klass->name = mono_image_alloc0 (image, 16);
5988 sprintf ((char*)klass->name, "%d", n);
5993 MonoMethod *omethod = container->owner.method;
5994 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5996 MonoClass *oklass = container->owner.klass;
5997 klass->name_space = oklass ? oklass->name_space : "";
6000 klass->name_space = "";
6003 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6007 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6011 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6012 klass->parent = pinfo->constraints [0];
6014 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6015 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6017 klass->parent = mono_defaults.object_class;
6020 if (count - pos > 0) {
6021 klass->interface_count = count - pos;
6022 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6023 klass->interfaces_inited = TRUE;
6024 for (i = pos; i < count; i++)
6025 klass->interfaces [i - pos] = pinfo->constraints [i];
6028 klass->image = image;
6030 klass->inited = TRUE;
6031 klass->cast_class = klass->element_class = klass;
6032 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6034 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6035 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6036 klass->this_arg.byref = TRUE;
6038 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6039 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6041 /*Init these fields to sane values*/
6042 klass->min_align = 1;
6043 klass->instance_size = sizeof (gpointer);
6044 mono_memory_barrier ();
6045 klass->size_inited = 1;
6047 mono_class_setup_supertypes (klass);
6049 if (count - pos > 0) {
6050 mono_class_setup_vtable (klass->parent);
6051 if (klass->parent->exception_type)
6052 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6054 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6060 #define FAST_CACHE_SIZE 16
6063 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6065 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6066 MonoImage *image = param->image;
6071 if (n < FAST_CACHE_SIZE) {
6073 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6075 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6077 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6078 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6083 * LOCKING: Acquires the loader lock.
6086 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6088 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6089 MonoImage *image = param->image;
6094 if (n < FAST_CACHE_SIZE) {
6096 /* No locking needed */
6097 if (!image->mvar_cache_fast)
6098 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6099 image->mvar_cache_fast [n] = klass;
6101 if (!image->var_cache_fast)
6102 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6103 image->var_cache_fast [n] = klass;
6107 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6109 mono_loader_lock ();
6110 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6112 ht = g_hash_table_new (NULL, NULL);
6113 mono_memory_barrier ();
6115 image->mvar_cache_slow = ht;
6117 image->var_cache_slow = ht;
6119 mono_loader_unlock ();
6122 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6126 * LOCKING: Acquires the loader lock.
6129 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6131 MonoGenericContainer *container = mono_generic_param_owner (param);
6132 MonoGenericParamInfo *pinfo;
6135 mono_loader_lock ();
6138 pinfo = mono_generic_param_info (param);
6139 if (pinfo->pklass) {
6140 mono_loader_unlock ();
6141 return pinfo->pklass;
6147 klass = get_anon_gparam_class (param, is_mvar);
6149 mono_loader_unlock ();
6154 if (!image && container) {
6156 MonoMethod *method = container->owner.method;
6157 image = (method && method->klass) ? method->klass->image : NULL;
6159 MonoClass *klass = container->owner.klass;
6160 // FIXME: 'klass' should not be null
6161 // But, monodis creates GenericContainers without associating a owner to it
6162 image = klass ? klass->image : NULL;
6166 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6168 mono_memory_barrier ();
6171 pinfo->pklass = klass;
6173 set_anon_gparam_class (param, is_mvar, klass);
6175 mono_loader_unlock ();
6177 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6178 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6184 mono_ptr_class_get (MonoType *type)
6187 MonoClass *el_class;
6191 el_class = mono_class_from_mono_type (type);
6192 image = el_class->image;
6194 mono_loader_lock ();
6196 if (!image->ptr_cache)
6197 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6199 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6200 mono_loader_unlock ();
6203 result = mono_image_alloc0 (image, sizeof (MonoClass));
6205 classes_size += sizeof (MonoClass);
6207 result->parent = NULL; /* no parent for PTR types */
6208 result->name_space = el_class->name_space;
6209 name = g_strdup_printf ("%s*", el_class->name);
6210 result->name = mono_image_strdup (image, name);
6213 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6215 result->image = el_class->image;
6216 result->inited = TRUE;
6217 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6218 /* Can pointers get boxed? */
6219 result->instance_size = sizeof (gpointer);
6220 result->cast_class = result->element_class = el_class;
6221 result->blittable = TRUE;
6223 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6224 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6225 result->this_arg.byref = TRUE;
6227 mono_class_setup_supertypes (result);
6229 g_hash_table_insert (image->ptr_cache, el_class, result);
6231 mono_loader_unlock ();
6233 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6239 mono_fnptr_class_get (MonoMethodSignature *sig)
6242 static GHashTable *ptr_hash = NULL;
6244 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6246 mono_loader_lock ();
6249 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6251 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6252 mono_loader_unlock ();
6255 result = g_new0 (MonoClass, 1);
6257 result->parent = NULL; /* no parent for PTR types */
6258 result->name_space = "System";
6259 result->name = "MonoFNPtrFakeClass";
6261 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6263 result->image = mono_defaults.corlib; /* need to fix... */
6264 result->inited = TRUE;
6265 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6266 /* Can pointers get boxed? */
6267 result->instance_size = sizeof (gpointer);
6268 result->cast_class = result->element_class = result;
6269 result->blittable = TRUE;
6271 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6272 result->this_arg.data.method = result->byval_arg.data.method = sig;
6273 result->this_arg.byref = TRUE;
6274 result->blittable = TRUE;
6276 mono_class_setup_supertypes (result);
6278 g_hash_table_insert (ptr_hash, sig, result);
6280 mono_loader_unlock ();
6282 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6288 mono_class_from_mono_type (MonoType *type)
6290 switch (type->type) {
6291 case MONO_TYPE_OBJECT:
6292 return type->data.klass? type->data.klass: mono_defaults.object_class;
6293 case MONO_TYPE_VOID:
6294 return type->data.klass? type->data.klass: mono_defaults.void_class;
6295 case MONO_TYPE_BOOLEAN:
6296 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6297 case MONO_TYPE_CHAR:
6298 return type->data.klass? type->data.klass: mono_defaults.char_class;
6300 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6302 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6304 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6306 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6308 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6310 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6312 return type->data.klass? type->data.klass: mono_defaults.int_class;
6314 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6316 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6318 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6320 return type->data.klass? type->data.klass: mono_defaults.single_class;
6322 return type->data.klass? type->data.klass: mono_defaults.double_class;
6323 case MONO_TYPE_STRING:
6324 return type->data.klass? type->data.klass: mono_defaults.string_class;
6325 case MONO_TYPE_TYPEDBYREF:
6326 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6327 case MONO_TYPE_ARRAY:
6328 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6330 return mono_ptr_class_get (type->data.type);
6331 case MONO_TYPE_FNPTR:
6332 return mono_fnptr_class_get (type->data.method);
6333 case MONO_TYPE_SZARRAY:
6334 return mono_array_class_get (type->data.klass, 1);
6335 case MONO_TYPE_CLASS:
6336 case MONO_TYPE_VALUETYPE:
6337 return type->data.klass;
6338 case MONO_TYPE_GENERICINST:
6339 return mono_generic_class_get_class (type->data.generic_class);
6341 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6342 case MONO_TYPE_MVAR:
6343 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6345 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6346 g_assert_not_reached ();
6353 * mono_type_retrieve_from_typespec
6354 * @image: context where the image is created
6355 * @type_spec: typespec token
6356 * @context: the generic context used to evaluate generic instantiations in
6359 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6361 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6363 mono_error_init (error);
6364 *did_inflate = FALSE;
6367 char *name = mono_class_name_from_token (image, type_spec);
6368 char *assembly = mono_assembly_name_from_token (image, type_spec);
6369 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6373 if (context && (context->class_inst || context->method_inst)) {
6374 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6376 if (!mono_error_ok (error))
6381 *did_inflate = TRUE;
6388 * mono_class_create_from_typespec
6389 * @image: context where the image is created
6390 * @type_spec: typespec token
6391 * @context: the generic context used to evaluate generic instantiations in
6394 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6397 gboolean inflated = FALSE;
6398 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6399 if (!mono_error_ok (error))
6401 ret = mono_class_from_mono_type (t);
6403 mono_metadata_free_type (t);
6408 * mono_bounded_array_class_get:
6409 * @element_class: element class
6410 * @rank: the dimension of the array class
6411 * @bounded: whenever the array has non-zero bounds
6413 * Returns: a class object describing the array with element type @element_type and
6417 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6421 MonoClass *parent = NULL;
6422 GSList *list, *rootlist = NULL;
6425 gboolean corlib_type = FALSE;
6427 g_assert (rank <= 255);
6430 /* bounded only matters for one-dimensional arrays */
6433 image = eclass->image;
6435 if (rank == 1 && !bounded) {
6437 * This case is very frequent not just during compilation because of calls
6438 * from mono_class_from_mono_type (), mono_array_new (),
6439 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6441 mono_mutex_lock (&image->szarray_cache_lock);
6442 if (!image->szarray_cache)
6443 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6444 class = g_hash_table_lookup (image->szarray_cache, eclass);
6445 mono_mutex_unlock (&image->szarray_cache_lock);
6449 mono_loader_lock ();
6451 mono_loader_lock ();
6453 if (!image->array_cache)
6454 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6456 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6457 for (; list; list = list->next) {
6459 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6460 mono_loader_unlock ();
6467 /* for the building corlib use System.Array from it */
6468 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6469 parent = mono_class_from_name (image, "System", "Array");
6472 parent = mono_defaults.array_class;
6473 if (!parent->inited)
6474 mono_class_init (parent);
6477 class = mono_image_alloc0 (image, sizeof (MonoClass));
6479 class->image = image;
6480 class->name_space = eclass->name_space;
6481 nsize = strlen (eclass->name);
6482 name = g_malloc (nsize + 2 + rank + 1);
6483 memcpy (name, eclass->name, nsize);
6486 memset (name + nsize + 1, ',', rank - 1);
6488 name [nsize + rank] = '*';
6489 name [nsize + rank + bounded] = ']';
6490 name [nsize + rank + bounded + 1] = 0;
6491 class->name = mono_image_strdup (image, name);
6494 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6496 classes_size += sizeof (MonoClass);
6498 class->type_token = 0;
6499 /* all arrays are marked serializable and sealed, bug #42779 */
6500 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6501 class->parent = parent;
6502 class->instance_size = mono_class_instance_size (class->parent);
6504 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6505 /*Arrays of those two types are invalid.*/
6506 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6507 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6508 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6509 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6510 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6512 /* element_size -1 is ok as this is not an instantitable type*/
6513 class->sizes.element_size = -1;
6515 class->sizes.element_size = mono_class_array_element_size (eclass);
6517 mono_class_setup_supertypes (class);
6519 if (eclass->generic_class)
6520 mono_class_init (eclass);
6521 if (!eclass->size_inited)
6522 mono_class_setup_fields (eclass);
6523 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6524 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6526 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6530 if (eclass->enumtype)
6531 class->cast_class = eclass->element_class;
6533 class->cast_class = eclass;
6535 switch (class->cast_class->byval_arg.type) {
6537 class->cast_class = mono_defaults.byte_class;
6540 class->cast_class = mono_defaults.int16_class;
6543 #if SIZEOF_VOID_P == 4
6547 class->cast_class = mono_defaults.int32_class;
6550 #if SIZEOF_VOID_P == 8
6554 class->cast_class = mono_defaults.int64_class;
6558 class->element_class = eclass;
6560 if ((rank > 1) || bounded) {
6561 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6562 class->byval_arg.type = MONO_TYPE_ARRAY;
6563 class->byval_arg.data.array = at;
6564 at->eklass = eclass;
6566 /* FIXME: complete.... */
6568 class->byval_arg.type = MONO_TYPE_SZARRAY;
6569 class->byval_arg.data.klass = eclass;
6571 class->this_arg = class->byval_arg;
6572 class->this_arg.byref = 1;
6577 class->generic_container = eclass->generic_container;
6579 if (rank == 1 && !bounded) {
6580 MonoClass *prev_class;
6582 mono_mutex_lock (&image->szarray_cache_lock);
6583 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6585 /* Someone got in before us */
6588 g_hash_table_insert (image->szarray_cache, eclass, class);
6589 mono_mutex_unlock (&image->szarray_cache_lock);
6591 list = g_slist_append (rootlist, class);
6592 g_hash_table_insert (image->array_cache, eclass, list);
6595 mono_loader_unlock ();
6597 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6603 * mono_array_class_get:
6604 * @element_class: element class
6605 * @rank: the dimension of the array class
6607 * Returns: a class object describing the array with element type @element_type and
6611 mono_array_class_get (MonoClass *eclass, guint32 rank)
6613 return mono_bounded_array_class_get (eclass, rank, FALSE);
6617 * mono_class_instance_size:
6620 * Returns: the size of an object instance
6623 mono_class_instance_size (MonoClass *klass)
6625 if (!klass->size_inited)
6626 mono_class_init (klass);
6628 return klass->instance_size;
6632 * mono_class_min_align:
6635 * Returns: minimm alignment requirements
6638 mono_class_min_align (MonoClass *klass)
6640 if (!klass->size_inited)
6641 mono_class_init (klass);
6643 return klass->min_align;
6647 * mono_class_value_size:
6650 * This function is used for value types, and return the
6651 * space and the alignment to store that kind of value object.
6653 * Returns: the size of a value of kind @klass
6656 mono_class_value_size (MonoClass *klass, guint32 *align)
6660 /* fixme: check disable, because we still have external revereces to
6661 * mscorlib and Dummy Objects
6663 /*g_assert (klass->valuetype);*/
6665 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6668 *align = klass->min_align;
6674 * mono_class_data_size:
6677 * Returns: the size of the static class data
6680 mono_class_data_size (MonoClass *klass)
6683 mono_class_init (klass);
6684 /* This can happen with dynamically created types */
6685 if (!klass->fields_inited)
6686 mono_class_setup_fields_locking (klass);
6688 /* in arrays, sizes.class_size is unioned with element_size
6689 * and arrays have no static fields
6693 return klass->sizes.class_size;
6697 * Auxiliary routine to mono_class_get_field
6699 * Takes a field index instead of a field token.
6701 static MonoClassField *
6702 mono_class_get_field_idx (MonoClass *class, int idx)
6704 mono_class_setup_fields_locking (class);
6705 if (class->exception_type)
6709 if (class->image->uncompressed_metadata) {
6711 * class->field.first points to the FieldPtr table, while idx points into the
6712 * Field table, so we have to do a search.
6714 /*FIXME this is broken for types with multiple fields with the same name.*/
6715 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6718 for (i = 0; i < class->field.count; ++i)
6719 if (mono_field_get_name (&class->fields [i]) == name)
6720 return &class->fields [i];
6721 g_assert_not_reached ();
6723 if (class->field.count) {
6724 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6725 return &class->fields [idx - class->field.first];
6729 class = class->parent;
6735 * mono_class_get_field:
6736 * @class: the class to lookup the field.
6737 * @field_token: the field token
6739 * Returns: A MonoClassField representing the type and offset of
6740 * the field, or a NULL value if the field does not belong to this
6744 mono_class_get_field (MonoClass *class, guint32 field_token)
6746 int idx = mono_metadata_token_index (field_token);
6748 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6750 return mono_class_get_field_idx (class, idx - 1);
6754 * mono_class_get_field_from_name:
6755 * @klass: the class to lookup the field.
6756 * @name: the field name
6758 * Search the class @klass and it's parents for a field with the name @name.
6760 * Returns: the MonoClassField pointer of the named field or NULL
6763 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6765 return mono_class_get_field_from_name_full (klass, name, NULL);
6769 * mono_class_get_field_from_name_full:
6770 * @klass: the class to lookup the field.
6771 * @name: the field name
6772 * @type: the type of the fields. This optional.
6774 * Search the class @klass and it's parents for a field with the name @name and type @type.
6776 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6777 * of its generic type definition.
6779 * Returns: the MonoClassField pointer of the named field or NULL
6782 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6786 mono_class_setup_fields_locking (klass);
6787 if (klass->exception_type)
6791 for (i = 0; i < klass->field.count; ++i) {
6792 MonoClassField *field = &klass->fields [i];
6794 if (strcmp (name, mono_field_get_name (field)) != 0)
6798 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6799 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6804 klass = klass->parent;
6810 * mono_class_get_field_token:
6811 * @field: the field we need the token of
6813 * Get the token of a field. Note that the tokesn is only valid for the image
6814 * the field was loaded from. Don't use this function for fields in dynamic types.
6816 * Returns: the token representing the field in the image it was loaded from.
6819 mono_class_get_field_token (MonoClassField *field)
6821 MonoClass *klass = field->parent;
6824 mono_class_setup_fields_locking (klass);
6829 for (i = 0; i < klass->field.count; ++i) {
6830 if (&klass->fields [i] == field) {
6831 int idx = klass->field.first + i + 1;
6833 if (klass->image->uncompressed_metadata)
6834 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6835 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6838 klass = klass->parent;
6841 g_assert_not_reached ();
6846 mono_field_get_index (MonoClassField *field)
6848 int index = field - field->parent->fields;
6850 g_assert (index >= 0 && index < field->parent->field.count);
6856 * mono_class_get_field_default_value:
6858 * Return the default value of the field as a pointer into the metadata blob.
6861 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6864 guint32 constant_cols [MONO_CONSTANT_SIZE];
6866 MonoClass *klass = field->parent;
6868 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6870 if (!klass->ext || !klass->ext->field_def_values) {
6871 mono_loader_lock ();
6872 mono_class_alloc_ext (klass);
6873 if (!klass->ext->field_def_values)
6874 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6875 mono_loader_unlock ();
6878 field_index = mono_field_get_index (field);
6880 if (!klass->ext->field_def_values [field_index].data) {
6881 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6885 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6887 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6888 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6889 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6892 *def_type = klass->ext->field_def_values [field_index].def_type;
6893 return klass->ext->field_def_values [field_index].data;
6897 mono_property_get_index (MonoProperty *prop)
6899 int index = prop - prop->parent->ext->properties;
6901 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6907 * mono_class_get_property_default_value:
6909 * Return the default value of the field as a pointer into the metadata blob.
6912 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6915 guint32 constant_cols [MONO_CONSTANT_SIZE];
6916 MonoClass *klass = property->parent;
6918 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6920 * We don't cache here because it is not used by C# so it's quite rare, but
6921 * we still do the lookup in klass->ext because that is where the data
6922 * is stored for dynamic assemblies.
6925 if (image_is_dynamic (klass->image)) {
6926 int prop_index = mono_property_get_index (property);
6927 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6928 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6929 return klass->ext->prop_def_values [prop_index].data;
6933 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6937 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6938 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6939 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6943 mono_class_get_event_token (MonoEvent *event)
6945 MonoClass *klass = event->parent;
6950 for (i = 0; i < klass->ext->event.count; ++i) {
6951 if (&klass->ext->events [i] == event)
6952 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6955 klass = klass->parent;
6958 g_assert_not_reached ();
6963 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6967 gpointer iter = NULL;
6968 while ((p = mono_class_get_properties (klass, &iter))) {
6969 if (! strcmp (name, p->name))
6972 klass = klass->parent;
6978 mono_class_get_property_token (MonoProperty *prop)
6980 MonoClass *klass = prop->parent;
6984 gpointer iter = NULL;
6985 while ((p = mono_class_get_properties (klass, &iter))) {
6986 if (&klass->ext->properties [i] == prop)
6987 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6991 klass = klass->parent;
6994 g_assert_not_reached ();
6999 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7001 const char *name, *nspace;
7002 if (image_is_dynamic (image))
7003 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7005 switch (type_token & 0xff000000){
7006 case MONO_TOKEN_TYPE_DEF: {
7007 guint32 cols [MONO_TYPEDEF_SIZE];
7008 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7009 guint tidx = mono_metadata_token_index (type_token);
7011 if (tidx > tt->rows)
7012 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7014 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7015 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7016 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7017 if (strlen (nspace) == 0)
7018 return g_strdup_printf ("%s", name);
7020 return g_strdup_printf ("%s.%s", nspace, name);
7023 case MONO_TOKEN_TYPE_REF: {
7025 guint32 cols [MONO_TYPEREF_SIZE];
7026 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7027 guint tidx = mono_metadata_token_index (type_token);
7030 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7032 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7033 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7034 mono_error_cleanup (&error);
7038 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7039 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7040 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7041 if (strlen (nspace) == 0)
7042 return g_strdup_printf ("%s", name);
7044 return g_strdup_printf ("%s.%s", nspace, name);
7047 case MONO_TOKEN_TYPE_SPEC:
7048 return g_strdup_printf ("Typespec 0x%08x", type_token);
7050 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7055 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7057 if (image_is_dynamic (image))
7058 return g_strdup_printf ("DynamicAssembly %s", image->name);
7060 switch (type_token & 0xff000000){
7061 case MONO_TOKEN_TYPE_DEF:
7062 if (image->assembly)
7063 return mono_stringify_assembly_name (&image->assembly->aname);
7064 else if (image->assembly_name)
7065 return g_strdup (image->assembly_name);
7066 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7067 case MONO_TOKEN_TYPE_REF: {
7069 MonoAssemblyName aname;
7070 guint32 cols [MONO_TYPEREF_SIZE];
7071 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7072 guint32 idx = mono_metadata_token_index (type_token);
7075 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7077 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7078 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7079 mono_error_cleanup (&error);
7082 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7084 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7085 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7086 case MONO_RESOLTION_SCOPE_MODULE:
7088 return g_strdup ("");
7089 case MONO_RESOLTION_SCOPE_MODULEREF:
7091 return g_strdup ("");
7092 case MONO_RESOLTION_SCOPE_TYPEREF:
7094 return g_strdup ("");
7095 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7096 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7097 return mono_stringify_assembly_name (&aname);
7099 g_assert_not_reached ();
7103 case MONO_TOKEN_TYPE_SPEC:
7105 return g_strdup ("");
7107 g_assert_not_reached ();
7114 * mono_class_get_full:
7115 * @image: the image where the class resides
7116 * @type_token: the token for the class
7117 * @context: the generic context used to evaluate generic instantiations in
7119 * Returns: the MonoClass that represents @type_token in @image
7122 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7125 MonoClass *class = NULL;
7127 if (image_is_dynamic (image)) {
7128 int table = mono_metadata_token_table (type_token);
7130 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7131 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7134 return mono_lookup_dynamic_token (image, type_token, context);
7137 switch (type_token & 0xff000000){
7138 case MONO_TOKEN_TYPE_DEF:
7139 class = mono_class_create_from_typedef (image, type_token, &error);
7140 if (!mono_error_ok (&error)) {
7141 mono_loader_set_error_from_mono_error (&error);
7142 /*FIXME don't swallow the error message*/
7143 mono_error_cleanup (&error);
7147 case MONO_TOKEN_TYPE_REF:
7148 class = mono_class_from_typeref (image, type_token);
7150 case MONO_TOKEN_TYPE_SPEC:
7151 class = mono_class_create_from_typespec (image, type_token, context, &error);
7152 if (!mono_error_ok (&error)) {
7153 /*FIXME don't swallow the error message*/
7154 mono_error_cleanup (&error);
7158 g_warning ("unknown token type %x", type_token & 0xff000000);
7159 g_assert_not_reached ();
7163 char *name = mono_class_name_from_token (image, type_token);
7164 char *assembly = mono_assembly_name_from_token (image, type_token);
7165 mono_loader_set_error_type_load (name, assembly);
7175 * mono_type_get_full:
7176 * @image: the image where the type resides
7177 * @type_token: the token for the type
7178 * @context: the generic context used to evaluate generic instantiations in
7180 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7182 * Returns: the MonoType that represents @type_token in @image
7185 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7188 MonoType *type = NULL;
7189 gboolean inflated = FALSE;
7191 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7192 if (image_is_dynamic (image))
7193 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7195 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7196 MonoClass *class = mono_class_get_full (image, type_token, context);
7197 return class ? mono_class_get_type (class) : NULL;
7200 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7202 if (!mono_error_ok (&error)) {
7203 /*FIXME don't swalloc the error message.*/
7204 char *name = mono_class_name_from_token (image, type_token);
7205 char *assembly = mono_assembly_name_from_token (image, type_token);
7207 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7209 mono_error_cleanup (&error);
7210 mono_loader_set_error_type_load (name, assembly);
7215 MonoType *tmp = type;
7216 type = mono_class_get_type (mono_class_from_mono_type (type));
7217 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7218 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7219 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7221 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7223 if (type->type != tmp->type)
7226 mono_metadata_free_type (tmp);
7233 mono_class_get (MonoImage *image, guint32 type_token)
7235 return mono_class_get_full (image, type_token, NULL);
7239 * mono_image_init_name_cache:
7241 * Initializes the class name cache stored in image->name_cache.
7243 * LOCKING: Acquires the corresponding image lock.
7246 mono_image_init_name_cache (MonoImage *image)
7248 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7249 guint32 cols [MONO_TYPEDEF_SIZE];
7252 guint32 i, visib, nspace_index;
7253 GHashTable *name_cache2, *nspace_table;
7255 mono_image_lock (image);
7257 if (image->name_cache) {
7258 mono_image_unlock (image);
7262 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7264 if (image_is_dynamic (image)) {
7265 mono_image_unlock (image);
7269 /* Temporary hash table to avoid lookups in the nspace_table */
7270 name_cache2 = g_hash_table_new (NULL, NULL);
7272 for (i = 1; i <= t->rows; ++i) {
7273 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7274 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7276 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7277 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7279 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7281 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7282 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7284 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7285 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7286 if (!nspace_table) {
7287 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7288 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7289 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7292 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7295 /* Load type names from EXPORTEDTYPES table */
7297 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7298 guint32 cols [MONO_EXP_TYPE_SIZE];
7301 for (i = 0; i < t->rows; ++i) {
7302 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7303 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7304 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7306 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7307 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7308 if (!nspace_table) {
7309 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7310 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7311 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7314 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7318 g_hash_table_destroy (name_cache2);
7319 mono_image_unlock (image);
7322 /*FIXME Only dynamic assemblies should allow this operation.*/
7324 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7325 const char *name, guint32 index)
7327 GHashTable *nspace_table;
7328 GHashTable *name_cache;
7331 mono_image_lock (image);
7333 if (!image->name_cache)
7334 mono_image_init_name_cache (image);
7336 name_cache = image->name_cache;
7337 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7338 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7339 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7342 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7343 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7345 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7347 mono_image_unlock (image);
7356 find_nocase (gpointer key, gpointer value, gpointer user_data)
7358 char *name = (char*)key;
7359 FindUserData *data = (FindUserData*)user_data;
7361 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7362 data->value = value;
7366 * mono_class_from_name_case:
7367 * @image: The MonoImage where the type is looked up in
7368 * @name_space: the type namespace
7369 * @name: the type short name.
7371 * Obtains a MonoClass with a given namespace and a given name which
7372 * is located in the given MonoImage. The namespace and name
7373 * lookups are case insensitive.
7376 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7378 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7379 guint32 cols [MONO_TYPEDEF_SIZE];
7384 if (image_is_dynamic (image)) {
7386 FindUserData user_data;
7388 mono_image_lock (image);
7390 if (!image->name_cache)
7391 mono_image_init_name_cache (image);
7393 user_data.key = name_space;
7394 user_data.value = NULL;
7395 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7397 if (user_data.value) {
7398 GHashTable *nspace_table = (GHashTable*)user_data.value;
7400 user_data.key = name;
7401 user_data.value = NULL;
7403 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7405 if (user_data.value)
7406 token = GPOINTER_TO_UINT (user_data.value);
7409 mono_image_unlock (image);
7412 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7418 /* add a cache if needed */
7419 for (i = 1; i <= t->rows; ++i) {
7420 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7421 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7423 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7424 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7426 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7428 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7429 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7430 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7431 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7437 return_nested_in (MonoClass *class, char *nested)
7440 char *s = strchr (nested, '/');
7441 gpointer iter = NULL;
7448 while ((found = mono_class_get_nested_types (class, &iter))) {
7449 if (strcmp (found->name, nested) == 0) {
7451 return return_nested_in (found, s);
7459 search_modules (MonoImage *image, const char *name_space, const char *name)
7461 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7462 MonoImage *file_image;
7467 * The EXPORTEDTYPES table only contains public types, so have to search the
7469 * Note: image->modules contains the contents of the MODULEREF table, while
7470 * the real module list is in the FILE table.
7472 for (i = 0; i < file_table->rows; i++) {
7473 guint32 cols [MONO_FILE_SIZE];
7474 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7475 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7478 file_image = mono_image_load_file_for_image (image, i + 1);
7480 class = mono_class_from_name (file_image, name_space, name);
7490 * mono_class_from_name:
7491 * @image: The MonoImage where the type is looked up in
7492 * @name_space: the type namespace
7493 * @name: the type short name.
7495 * Obtains a MonoClass with a given namespace and a given name which
7496 * is located in the given MonoImage.
7498 * To reference nested classes, use the "/" character as a separator.
7499 * For example use "Foo/Bar" to reference the class Bar that is nested
7500 * inside Foo, like this: "class Foo { class Bar {} }".
7503 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7505 GHashTable *nspace_table;
7506 MonoImage *loaded_image;
7513 if ((nested = strchr (name, '/'))) {
7514 int pos = nested - name;
7515 int len = strlen (name);
7518 memcpy (buf, name, len + 1);
7520 nested = buf + pos + 1;
7524 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7525 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7526 gboolean res = get_class_from_name (image, name_space, name, &class);
7529 class = search_modules (image, name_space, name);
7531 return class ? return_nested_in (class, nested) : NULL;
7537 mono_image_lock (image);
7539 if (!image->name_cache)
7540 mono_image_init_name_cache (image);
7542 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7545 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7547 mono_image_unlock (image);
7549 if (!token && image_is_dynamic (image) && image->modules) {
7550 /* Search modules as well */
7551 for (i = 0; i < image->module_count; ++i) {
7552 MonoImage *module = image->modules [i];
7554 class = mono_class_from_name (module, name_space, name);
7561 class = search_modules (image, name_space, name);
7569 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7570 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7571 guint32 cols [MONO_EXP_TYPE_SIZE];
7574 idx = mono_metadata_token_index (token);
7576 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7578 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7579 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7580 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7583 class = mono_class_from_name (loaded_image, name_space, name);
7585 return return_nested_in (class, nested);
7587 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7588 guint32 assembly_idx;
7590 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7592 mono_assembly_load_reference (image, assembly_idx - 1);
7593 g_assert (image->references [assembly_idx - 1]);
7594 if (image->references [assembly_idx - 1] == (gpointer)-1)
7597 /* FIXME: Cycle detection */
7598 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7600 g_error ("not yet implemented");
7604 token = MONO_TOKEN_TYPE_DEF | token;
7606 class = mono_class_get (image, token);
7608 return return_nested_in (class, nested);
7613 * mono_class_is_subclass_of:
7614 * @klass: class to probe if it is a subclass of another one
7615 * @klassc: the class we suspect is the base class
7616 * @check_interfaces: whether we should perform interface checks
7618 * This method determines whether @klass is a subclass of @klassc.
7620 * If the @check_interfaces flag is set, then if @klassc is an interface
7621 * this method return true if the @klass implements the interface or
7622 * if @klass is an interface, if one of its base classes is @klass.
7624 * If @check_interfaces is false then, then if @klass is not an interface
7625 * then it returns true if the @klass is a subclass of @klassc.
7627 * if @klass is an interface and @klassc is System.Object, then this function
7632 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7633 gboolean check_interfaces)
7635 /*FIXME test for interfaces with variant generic arguments*/
7637 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7638 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7640 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7643 for (i = 0; i < klass->interface_count; i ++) {
7644 MonoClass *ic = klass->interfaces [i];
7649 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7654 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7657 if (klassc == mono_defaults.object_class)
7664 mono_type_is_generic_argument (MonoType *type)
7666 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7670 mono_class_has_variant_generic_params (MonoClass *klass)
7673 MonoGenericContainer *container;
7675 if (!klass->generic_class)
7678 container = klass->generic_class->container_class->generic_container;
7680 for (i = 0; i < container->type_argc; ++i)
7681 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7688 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7690 if (target == candidate)
7693 if (check_for_reference_conv &&
7694 mono_type_is_generic_argument (&target->byval_arg) &&
7695 mono_type_is_generic_argument (&candidate->byval_arg)) {
7696 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7697 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7699 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7702 if (!mono_class_is_assignable_from (target, candidate))
7708 * @container the generic container from the GTD
7709 * @klass: the class to be assigned to
7710 * @oklass: the source class
7712 * Both klass and oklass must be instances of the same generic interface.
7713 * Return true if @klass can be assigned to a @klass variable
7716 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7719 MonoType **klass_argv, **oklass_argv;
7720 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7721 MonoGenericContainer *container = klass_gtd->generic_container;
7723 if (klass == oklass)
7726 /*Viable candidates are instances of the same generic interface*/
7727 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7730 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7731 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7733 for (j = 0; j < container->type_argc; ++j) {
7734 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7735 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7737 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7741 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7742 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7744 if (param1_class != param2_class) {
7745 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7746 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7748 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7749 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7759 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7761 MonoGenericParam *gparam, *ogparam;
7762 MonoGenericParamInfo *tinfo, *cinfo;
7763 MonoClass **candidate_class;
7764 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7767 if (target == candidate)
7769 if (target->byval_arg.type != candidate->byval_arg.type)
7772 gparam = target->byval_arg.data.generic_param;
7773 ogparam = candidate->byval_arg.data.generic_param;
7774 tinfo = mono_generic_param_info (gparam);
7775 cinfo = mono_generic_param_info (ogparam);
7777 class_constraint_satisfied = FALSE;
7778 valuetype_constraint_satisfied = FALSE;
7780 /*candidate must have a super set of target's special constraints*/
7781 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7782 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7784 if (cinfo->constraints) {
7785 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7786 MonoClass *cc = *candidate_class;
7788 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7789 class_constraint_satisfied = TRUE;
7790 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7791 valuetype_constraint_satisfied = TRUE;
7794 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7795 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7797 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7799 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7801 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7802 valuetype_constraint_satisfied)) {
7807 /*candidate type constraints must be a superset of target's*/
7808 if (tinfo->constraints) {
7809 MonoClass **target_class;
7810 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7811 MonoClass *tc = *target_class;
7814 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7815 * check it's constraints since it satisfy the constraint by itself.
7817 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7820 if (!cinfo->constraints)
7823 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7824 MonoClass *cc = *candidate_class;
7826 if (mono_class_is_assignable_from (tc, cc))
7830 * This happens when we have the following:
7832 * Bar<K> where K : IFace
7833 * Foo<T, U> where T : U where U : IFace
7835 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7838 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7839 if (mono_gparam_is_assignable_from (target, cc))
7843 if (!*candidate_class)
7848 /*candidate itself must have a constraint that satisfy target*/
7849 if (cinfo->constraints) {
7850 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7851 MonoClass *cc = *candidate_class;
7852 if (mono_class_is_assignable_from (target, cc))
7860 * mono_class_is_assignable_from:
7861 * @klass: the class to be assigned to
7862 * @oklass: the source class
7864 * Return: true if an instance of object oklass can be assigned to an
7865 * instance of object @klass
7868 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7870 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7872 mono_class_init (klass);
7874 if (!oklass->inited)
7875 mono_class_init (oklass);
7877 if (klass->exception_type || oklass->exception_type)
7880 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7881 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7883 return mono_gparam_is_assignable_from (klass, oklass);
7886 if (MONO_CLASS_IS_INTERFACE (klass)) {
7887 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7888 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7889 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7893 for (i = 0; constraints [i]; ++i) {
7894 if (mono_class_is_assignable_from (klass, constraints [i]))
7902 /* interface_offsets might not be set for dynamic classes */
7903 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7905 * oklass might be a generic type parameter but they have
7906 * interface_offsets set.
7908 return mono_reflection_call_is_assignable_to (oklass, klass);
7909 if (!oklass->interface_bitmap)
7910 /* Happens with generic instances of not-yet created dynamic types */
7912 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7915 if (mono_class_has_variant_generic_params (klass)) {
7918 mono_class_setup_interfaces (oklass, &error);
7919 if (!mono_error_ok (&error)) {
7920 mono_error_cleanup (&error);
7924 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7925 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7926 MonoClass *iface = oklass->interfaces_packed [i];
7928 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7933 } else if (klass->delegate) {
7934 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7936 }else if (klass->rank) {
7937 MonoClass *eclass, *eoclass;
7939 if (oklass->rank != klass->rank)
7942 /* vectors vs. one dimensional arrays */
7943 if (oklass->byval_arg.type != klass->byval_arg.type)
7946 eclass = klass->cast_class;
7947 eoclass = oklass->cast_class;
7950 * a is b does not imply a[] is b[] when a is a valuetype, and
7951 * b is a reference type.
7954 if (eoclass->valuetype) {
7955 if ((eclass == mono_defaults.enum_class) ||
7956 (eclass == mono_defaults.enum_class->parent) ||
7957 (eclass == mono_defaults.object_class))
7961 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7962 } else if (mono_class_is_nullable (klass)) {
7963 if (mono_class_is_nullable (oklass))
7964 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7966 return mono_class_is_assignable_from (klass->cast_class, oklass);
7967 } else if (klass == mono_defaults.object_class)
7970 return mono_class_has_parent (oklass, klass);
7973 /*Check if @oklass is variant compatible with @klass.*/
7975 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7978 MonoType **klass_argv, **oklass_argv;
7979 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7980 MonoGenericContainer *container = klass_gtd->generic_container;
7982 /*Viable candidates are instances of the same generic interface*/
7983 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7986 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7987 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7989 for (j = 0; j < container->type_argc; ++j) {
7990 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7991 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7993 if (param1_class->valuetype != param2_class->valuetype)
7997 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7998 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8000 if (param1_class != param2_class) {
8001 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8002 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8004 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8005 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8013 /*Check if @candidate implements the interface @target*/
8015 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8019 gboolean is_variant = mono_class_has_variant_generic_params (target);
8021 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8022 if (mono_class_is_variant_compatible_slow (target, candidate))
8027 if (candidate == target)
8030 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8031 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8032 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8034 if (tb && tb->interfaces) {
8035 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8036 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8037 MonoClass *iface_class;
8039 /* we can't realize the type here since it can do pretty much anything. */
8042 iface_class = mono_class_from_mono_type (iface->type);
8043 if (iface_class == target)
8045 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8047 if (mono_class_implement_interface_slow (target, iface_class))
8052 /*setup_interfaces don't mono_class_init anything*/
8053 /*FIXME this doesn't handle primitive type arrays.
8054 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8055 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8057 mono_class_setup_interfaces (candidate, &error);
8058 if (!mono_error_ok (&error)) {
8059 mono_error_cleanup (&error);
8063 for (i = 0; i < candidate->interface_count; ++i) {
8064 if (candidate->interfaces [i] == target)
8067 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8070 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8074 candidate = candidate->parent;
8075 } while (candidate);
8081 * Check if @oklass can be assigned to @klass.
8082 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8085 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8087 if (candidate == target)
8089 if (target == mono_defaults.object_class)
8092 if (mono_class_has_parent (candidate, target))
8095 /*If target is not an interface there is no need to check them.*/
8096 if (MONO_CLASS_IS_INTERFACE (target))
8097 return mono_class_implement_interface_slow (target, candidate);
8099 if (target->delegate && mono_class_has_variant_generic_params (target))
8100 return mono_class_is_variant_compatible (target, candidate, FALSE);
8103 MonoClass *eclass, *eoclass;
8105 if (target->rank != candidate->rank)
8108 /* vectors vs. one dimensional arrays */
8109 if (target->byval_arg.type != candidate->byval_arg.type)
8112 eclass = target->cast_class;
8113 eoclass = candidate->cast_class;
8116 * a is b does not imply a[] is b[] when a is a valuetype, and
8117 * b is a reference type.
8120 if (eoclass->valuetype) {
8121 if ((eclass == mono_defaults.enum_class) ||
8122 (eclass == mono_defaults.enum_class->parent) ||
8123 (eclass == mono_defaults.object_class))
8127 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8129 /*FIXME properly handle nullables */
8130 /*FIXME properly handle (M)VAR */
8135 * mono_class_get_cctor:
8136 * @klass: A MonoClass pointer
8138 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8141 mono_class_get_cctor (MonoClass *klass)
8143 MonoCachedClassInfo cached_info;
8145 if (image_is_dynamic (klass->image)) {
8147 * has_cctor is not set for these classes because mono_class_init () is
8150 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8153 if (!klass->has_cctor)
8156 if (mono_class_get_cached_class_info (klass, &cached_info))
8157 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8159 if (klass->generic_class && !klass->methods)
8160 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8162 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8166 * mono_class_get_finalizer:
8167 * @klass: The MonoClass pointer
8169 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8172 mono_class_get_finalizer (MonoClass *klass)
8174 MonoCachedClassInfo cached_info;
8177 mono_class_init (klass);
8178 if (!mono_class_has_finalizer (klass))
8181 if (mono_class_get_cached_class_info (klass, &cached_info))
8182 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8184 mono_class_setup_vtable (klass);
8185 return klass->vtable [finalize_slot];
8190 * mono_class_needs_cctor_run:
8191 * @klass: the MonoClass pointer
8192 * @caller: a MonoMethod describing the caller
8194 * Determines whenever the class has a static constructor and whenever it
8195 * needs to be called when executing CALLER.
8198 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8202 method = mono_class_get_cctor (klass);
8204 return (method == caller) ? FALSE : TRUE;
8210 * mono_class_array_element_size:
8213 * Returns: the number of bytes an element of type @klass
8214 * uses when stored into an array.
8217 mono_class_array_element_size (MonoClass *klass)
8219 MonoType *type = &klass->byval_arg;
8222 switch (type->type) {
8225 case MONO_TYPE_BOOLEAN:
8229 case MONO_TYPE_CHAR:
8238 case MONO_TYPE_CLASS:
8239 case MONO_TYPE_STRING:
8240 case MONO_TYPE_OBJECT:
8241 case MONO_TYPE_SZARRAY:
8242 case MONO_TYPE_ARRAY:
8244 case MONO_TYPE_MVAR:
8245 return sizeof (gpointer);
8250 case MONO_TYPE_VALUETYPE:
8251 if (type->data.klass->enumtype) {
8252 type = mono_class_enum_basetype (type->data.klass);
8253 klass = klass->element_class;
8256 return mono_class_instance_size (klass) - sizeof (MonoObject);
8257 case MONO_TYPE_GENERICINST:
8258 type = &type->data.generic_class->container_class->byval_arg;
8261 case MONO_TYPE_VOID:
8265 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8271 * mono_array_element_size:
8272 * @ac: pointer to a #MonoArrayClass
8274 * Returns: the size of single array element.
8277 mono_array_element_size (MonoClass *ac)
8279 g_assert (ac->rank);
8280 return ac->sizes.element_size;
8284 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8285 MonoGenericContext *context)
8287 if (image_is_dynamic (image)) {
8288 MonoClass *tmp_handle_class;
8289 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8291 g_assert (tmp_handle_class);
8293 *handle_class = tmp_handle_class;
8295 if (tmp_handle_class == mono_defaults.typehandle_class)
8296 return &((MonoClass*)obj)->byval_arg;
8301 switch (token & 0xff000000) {
8302 case MONO_TOKEN_TYPE_DEF:
8303 case MONO_TOKEN_TYPE_REF:
8304 case MONO_TOKEN_TYPE_SPEC: {
8307 *handle_class = mono_defaults.typehandle_class;
8308 type = mono_type_get_full (image, token, context);
8311 mono_class_init (mono_class_from_mono_type (type));
8312 /* We return a MonoType* as handle */
8315 case MONO_TOKEN_FIELD_DEF: {
8317 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8321 *handle_class = mono_defaults.fieldhandle_class;
8322 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8325 mono_class_init (class);
8326 return mono_class_get_field (class, token);
8328 case MONO_TOKEN_METHOD_DEF:
8329 case MONO_TOKEN_METHOD_SPEC: {
8331 meth = mono_get_method_full (image, token, NULL, context);
8333 *handle_class = mono_defaults.methodhandle_class;
8336 case MONO_TOKEN_MEMBER_REF: {
8337 guint32 cols [MONO_MEMBERREF_SIZE];
8339 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8340 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8341 mono_metadata_decode_blob_size (sig, &sig);
8342 if (*sig == 0x6) { /* it's a field */
8344 MonoClassField *field;
8345 field = mono_field_from_token (image, token, &klass, context);
8347 *handle_class = mono_defaults.fieldhandle_class;
8351 meth = mono_get_method_full (image, token, NULL, context);
8353 *handle_class = mono_defaults.methodhandle_class;
8358 g_warning ("Unknown token 0x%08x in ldtoken", token);
8365 * This function might need to call runtime functions so it can't be part
8366 * of the metadata library.
8368 static MonoLookupDynamicToken lookup_dynamic = NULL;
8371 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8373 lookup_dynamic = func;
8377 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8379 MonoClass *handle_class;
8381 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8385 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8387 return lookup_dynamic (image, token, valid_token, handle_class, context);
8390 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8393 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8395 get_cached_class_info = func;
8399 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8401 if (!get_cached_class_info)
8404 return get_cached_class_info (klass, res);
8408 mono_install_get_class_from_name (MonoGetClassFromName func)
8410 get_class_from_name = func;
8414 mono_class_get_image (MonoClass *klass)
8416 return klass->image;
8420 * mono_class_get_element_class:
8421 * @klass: the MonoClass to act on
8423 * Returns: the element class of an array or an enumeration.
8426 mono_class_get_element_class (MonoClass *klass)
8428 return klass->element_class;
8432 * mono_class_is_valuetype:
8433 * @klass: the MonoClass to act on
8435 * Returns: true if the MonoClass represents a ValueType.
8438 mono_class_is_valuetype (MonoClass *klass)
8440 return klass->valuetype;
8444 * mono_class_is_enum:
8445 * @klass: the MonoClass to act on
8447 * Returns: true if the MonoClass represents an enumeration.
8450 mono_class_is_enum (MonoClass *klass)
8452 return klass->enumtype;
8456 * mono_class_enum_basetype:
8457 * @klass: the MonoClass to act on
8459 * Returns: the underlying type representation for an enumeration.
8462 mono_class_enum_basetype (MonoClass *klass)
8464 if (klass->element_class == klass)
8465 /* SRE or broken types */
8468 return &klass->element_class->byval_arg;
8472 * mono_class_get_parent
8473 * @klass: the MonoClass to act on
8475 * Returns: the parent class for this class.
8478 mono_class_get_parent (MonoClass *klass)
8480 return klass->parent;
8484 * mono_class_get_nesting_type;
8485 * @klass: the MonoClass to act on
8487 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8490 mono_class_get_nesting_type (MonoClass *klass)
8492 return klass->nested_in;
8496 * mono_class_get_rank:
8497 * @klass: the MonoClass to act on
8499 * Returns: the rank for the array (the number of dimensions).
8502 mono_class_get_rank (MonoClass *klass)
8508 * mono_class_get_flags:
8509 * @klass: the MonoClass to act on
8511 * The type flags from the TypeDef table from the metadata.
8512 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8515 * Returns: the flags from the TypeDef table.
8518 mono_class_get_flags (MonoClass *klass)
8520 return klass->flags;
8524 * mono_class_get_name
8525 * @klass: the MonoClass to act on
8527 * Returns: the name of the class.
8530 mono_class_get_name (MonoClass *klass)
8536 * mono_class_get_namespace:
8537 * @klass: the MonoClass to act on
8539 * Returns: the namespace of the class.
8542 mono_class_get_namespace (MonoClass *klass)
8544 return klass->name_space;
8548 * mono_class_get_type:
8549 * @klass: the MonoClass to act on
8551 * This method returns the internal Type representation for the class.
8553 * Returns: the MonoType from the class.
8556 mono_class_get_type (MonoClass *klass)
8558 return &klass->byval_arg;
8562 * mono_class_get_type_token
8563 * @klass: the MonoClass to act on
8565 * This method returns type token for the class.
8567 * Returns: the type token for the class.
8570 mono_class_get_type_token (MonoClass *klass)
8572 return klass->type_token;
8576 * mono_class_get_byref_type:
8577 * @klass: the MonoClass to act on
8582 mono_class_get_byref_type (MonoClass *klass)
8584 return &klass->this_arg;
8588 * mono_class_num_fields:
8589 * @klass: the MonoClass to act on
8591 * Returns: the number of static and instance fields in the class.
8594 mono_class_num_fields (MonoClass *klass)
8596 return klass->field.count;
8600 * mono_class_num_methods:
8601 * @klass: the MonoClass to act on
8603 * Returns: the number of methods in the class.
8606 mono_class_num_methods (MonoClass *klass)
8608 return klass->method.count;
8612 * mono_class_num_properties
8613 * @klass: the MonoClass to act on
8615 * Returns: the number of properties in the class.
8618 mono_class_num_properties (MonoClass *klass)
8620 mono_class_setup_properties (klass);
8622 return klass->ext->property.count;
8626 * mono_class_num_events:
8627 * @klass: the MonoClass to act on
8629 * Returns: the number of events in the class.
8632 mono_class_num_events (MonoClass *klass)
8634 mono_class_setup_events (klass);
8636 return klass->ext->event.count;
8640 * mono_class_get_fields:
8641 * @klass: the MonoClass to act on
8643 * This routine is an iterator routine for retrieving the fields in a class.
8645 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8646 * iterate over all of the elements. When no more values are
8647 * available, the return value is NULL.
8649 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8652 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8654 MonoClassField* field;
8658 mono_class_setup_fields_locking (klass);
8659 if (klass->exception_type)
8661 /* start from the first */
8662 if (klass->field.count) {
8663 return *iter = &klass->fields [0];
8671 if (field < &klass->fields [klass->field.count]) {
8672 return *iter = field;
8678 * mono_class_get_methods
8679 * @klass: the MonoClass to act on
8681 * This routine is an iterator routine for retrieving the fields in a class.
8683 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8684 * iterate over all of the elements. When no more values are
8685 * available, the return value is NULL.
8687 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8690 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8692 MonoMethod** method;
8696 mono_class_setup_methods (klass);
8699 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8700 * FIXME we should better report this error to the caller
8702 if (!klass->methods)
8704 /* start from the first */
8705 if (klass->method.count) {
8706 *iter = &klass->methods [0];
8707 return klass->methods [0];
8715 if (method < &klass->methods [klass->method.count]) {
8723 * mono_class_get_virtual_methods:
8725 * Iterate over the virtual methods of KLASS.
8727 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8730 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8732 MonoMethod** method;
8735 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8737 mono_class_setup_methods (klass);
8739 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8740 * FIXME we should better report this error to the caller
8742 if (!klass->methods)
8744 /* start from the first */
8745 method = &klass->methods [0];
8750 while (method < &klass->methods [klass->method.count]) {
8751 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8755 if (method < &klass->methods [klass->method.count]) {
8762 /* Search directly in metadata to avoid calling setup_methods () */
8763 MonoMethod *res = NULL;
8769 start_index = GPOINTER_TO_UINT (*iter);
8772 for (i = start_index; i < klass->method.count; ++i) {
8775 /* class->method.first points into the methodptr table */
8776 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8778 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8782 if (i < klass->method.count) {
8783 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8784 /* Add 1 here so the if (*iter) check fails */
8785 *iter = GUINT_TO_POINTER (i + 1);
8794 * mono_class_get_properties:
8795 * @klass: the MonoClass to act on
8797 * This routine is an iterator routine for retrieving the properties in a class.
8799 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8800 * iterate over all of the elements. When no more values are
8801 * available, the return value is NULL.
8803 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8806 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8808 MonoProperty* property;
8812 mono_class_setup_properties (klass);
8813 /* start from the first */
8814 if (klass->ext->property.count) {
8815 return *iter = &klass->ext->properties [0];
8823 if (property < &klass->ext->properties [klass->ext->property.count]) {
8824 return *iter = property;
8830 * mono_class_get_events:
8831 * @klass: the MonoClass to act on
8833 * This routine is an iterator routine for retrieving the properties in a class.
8835 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8836 * iterate over all of the elements. When no more values are
8837 * available, the return value is NULL.
8839 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8842 mono_class_get_events (MonoClass* klass, gpointer *iter)
8848 mono_class_setup_events (klass);
8849 /* start from the first */
8850 if (klass->ext->event.count) {
8851 return *iter = &klass->ext->events [0];
8859 if (event < &klass->ext->events [klass->ext->event.count]) {
8860 return *iter = event;
8866 * mono_class_get_interfaces
8867 * @klass: the MonoClass to act on
8869 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8871 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8872 * iterate over all of the elements. When no more values are
8873 * available, the return value is NULL.
8875 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8878 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8886 mono_class_init (klass);
8887 if (!klass->interfaces_inited) {
8888 mono_class_setup_interfaces (klass, &error);
8889 if (!mono_error_ok (&error)) {
8890 mono_error_cleanup (&error);
8894 /* start from the first */
8895 if (klass->interface_count) {
8896 *iter = &klass->interfaces [0];
8897 return klass->interfaces [0];
8905 if (iface < &klass->interfaces [klass->interface_count]) {
8913 setup_nested_types (MonoClass *klass)
8919 if (klass->nested_classes_inited)
8922 if (!klass->type_token)
8923 klass->nested_classes_inited = TRUE;
8925 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8929 guint32 cols [MONO_NESTED_CLASS_SIZE];
8930 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8931 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8932 if (!mono_error_ok (&error)) {
8933 /*FIXME don't swallow the error message*/
8934 mono_error_cleanup (&error);
8936 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8940 classes = g_list_prepend (classes, nclass);
8942 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8945 mono_loader_lock ();
8946 if (klass->nested_classes_inited) {
8947 g_list_free (classes);
8948 mono_loader_unlock ();
8952 mono_class_alloc_ext (klass);
8954 for (l = classes; l; l = l->next)
8955 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, l->data);
8956 g_list_free (classes);
8958 mono_memory_barrier ();
8960 klass->nested_classes_inited = TRUE;
8961 mono_loader_unlock ();
8965 * mono_class_get_nested_types
8966 * @klass: the MonoClass to act on
8968 * This routine is an iterator routine for retrieving the nested types of a class.
8969 * This works only if @klass is non-generic, or a generic type definition.
8971 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8972 * iterate over all of the elements. When no more values are
8973 * available, the return value is NULL.
8975 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8978 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8984 if (!klass->nested_classes_inited)
8985 setup_nested_types (klass);
8988 /* start from the first */
8989 if (klass->ext && klass->ext->nested_classes) {
8990 *iter = klass->ext->nested_classes;
8991 return klass->ext->nested_classes->data;
8993 /* no nested types */
9008 * mono_class_is_delegate
9009 * @klass: the MonoClass to act on
9011 * Returns: true if the MonoClass represents a System.Delegate.
9014 mono_class_is_delegate (MonoClass *klass)
9016 return klass->delegate;
9020 * mono_class_implements_interface
9021 * @klass: The MonoClass to act on
9022 * @interface: The interface to check if @klass implements.
9024 * Returns: true if @klass implements @interface.
9027 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9029 return mono_class_is_assignable_from (iface, klass);
9033 * mono_field_get_name:
9034 * @field: the MonoClassField to act on
9036 * Returns: the name of the field.
9039 mono_field_get_name (MonoClassField *field)
9045 * mono_field_get_type:
9046 * @field: the MonoClassField to act on
9048 * Returns: MonoType of the field.
9051 mono_field_get_type (MonoClassField *field)
9054 MonoType *type = mono_field_get_type_checked (field, &error);
9055 if (!mono_error_ok (&error)) {
9056 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9057 mono_error_cleanup (&error);
9064 * mono_field_get_type_checked:
9065 * @field: the MonoClassField to act on
9066 * @error: used to return any erro found while retrieving @field type
9068 * Returns: MonoType of the field.
9071 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9073 mono_error_init (error);
9075 mono_field_resolve_type (field, error);
9080 * mono_field_get_parent:
9081 * @field: the MonoClassField to act on
9083 * Returns: MonoClass where the field was defined.
9086 mono_field_get_parent (MonoClassField *field)
9088 return field->parent;
9092 * mono_field_get_flags;
9093 * @field: the MonoClassField to act on
9095 * The metadata flags for a field are encoded using the
9096 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9098 * Returns: the flags for the field.
9101 mono_field_get_flags (MonoClassField *field)
9104 return mono_field_resolve_flags (field);
9105 return field->type->attrs;
9109 * mono_field_get_offset;
9110 * @field: the MonoClassField to act on
9112 * Returns: the field offset.
9115 mono_field_get_offset (MonoClassField *field)
9117 return field->offset;
9121 mono_field_get_rva (MonoClassField *field)
9125 MonoClass *klass = field->parent;
9127 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9129 if (!klass->ext || !klass->ext->field_def_values) {
9130 mono_loader_lock ();
9131 mono_class_alloc_ext (klass);
9132 if (!klass->ext->field_def_values)
9133 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9134 mono_loader_unlock ();
9137 field_index = mono_field_get_index (field);
9139 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9140 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9142 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9143 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9146 return klass->ext->field_def_values [field_index].data;
9150 * mono_field_get_data;
9151 * @field: the MonoClassField to act on
9153 * Returns: pointer to the metadata constant value or to the field
9154 * data if it has an RVA flag.
9157 mono_field_get_data (MonoClassField *field)
9159 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9160 MonoTypeEnum def_type;
9162 return mono_class_get_field_default_value (field, &def_type);
9163 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9164 return mono_field_get_rva (field);
9171 * mono_property_get_name:
9172 * @prop: the MonoProperty to act on
9174 * Returns: the name of the property
9177 mono_property_get_name (MonoProperty *prop)
9183 * mono_property_get_set_method
9184 * @prop: the MonoProperty to act on.
9186 * Returns: the setter method of the property (A MonoMethod)
9189 mono_property_get_set_method (MonoProperty *prop)
9195 * mono_property_get_get_method
9196 * @prop: the MonoProperty to act on.
9198 * Returns: the setter method of the property (A MonoMethod)
9201 mono_property_get_get_method (MonoProperty *prop)
9207 * mono_property_get_parent:
9208 * @prop: the MonoProperty to act on.
9210 * Returns: the MonoClass where the property was defined.
9213 mono_property_get_parent (MonoProperty *prop)
9215 return prop->parent;
9219 * mono_property_get_flags:
9220 * @prop: the MonoProperty to act on.
9222 * The metadata flags for a property are encoded using the
9223 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9225 * Returns: the flags for the property.
9228 mono_property_get_flags (MonoProperty *prop)
9234 * mono_event_get_name:
9235 * @event: the MonoEvent to act on
9237 * Returns: the name of the event.
9240 mono_event_get_name (MonoEvent *event)
9246 * mono_event_get_add_method:
9247 * @event: The MonoEvent to act on.
9249 * Returns: the @add' method for the event (a MonoMethod).
9252 mono_event_get_add_method (MonoEvent *event)
9258 * mono_event_get_remove_method:
9259 * @event: The MonoEvent to act on.
9261 * Returns: the @remove method for the event (a MonoMethod).
9264 mono_event_get_remove_method (MonoEvent *event)
9266 return event->remove;
9270 * mono_event_get_raise_method:
9271 * @event: The MonoEvent to act on.
9273 * Returns: the @raise method for the event (a MonoMethod).
9276 mono_event_get_raise_method (MonoEvent *event)
9278 return event->raise;
9282 * mono_event_get_parent:
9283 * @event: the MonoEvent to act on.
9285 * Returns: the MonoClass where the event is defined.
9288 mono_event_get_parent (MonoEvent *event)
9290 return event->parent;
9294 * mono_event_get_flags
9295 * @event: the MonoEvent to act on.
9297 * The metadata flags for an event are encoded using the
9298 * EVENT_* constants. See the tabledefs.h file for details.
9300 * Returns: the flags for the event.
9303 mono_event_get_flags (MonoEvent *event)
9305 return event->attrs;
9309 * mono_class_get_method_from_name:
9310 * @klass: where to look for the method
9311 * @name: name of the method
9312 * @param_count: number of parameters. -1 for any number.
9314 * Obtains a MonoMethod with a given name and number of parameters.
9315 * It only works if there are no multiple signatures for any given method name.
9318 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9320 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9324 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9326 MonoMethod *res = NULL;
9329 /* Search directly in the metadata to avoid calling setup_methods () */
9330 for (i = 0; i < klass->method.count; ++i) {
9331 guint32 cols [MONO_METHOD_SIZE];
9333 MonoMethodSignature *sig;
9335 /* class->method.first points into the methodptr table */
9336 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9338 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9339 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9340 if (param_count == -1) {
9344 sig = mono_method_signature (method);
9345 if (sig && sig->param_count == param_count) {
9356 * mono_class_get_method_from_name_flags:
9357 * @klass: where to look for the method
9358 * @name_space: name of the method
9359 * @param_count: number of parameters. -1 for any number.
9360 * @flags: flags which must be set in the method
9362 * Obtains a MonoMethod with a given name and number of parameters.
9363 * It only works if there are no multiple signatures for any given method name.
9366 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9368 MonoMethod *res = NULL;
9371 mono_class_init (klass);
9373 if (klass->generic_class && !klass->methods) {
9374 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9376 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9380 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9381 mono_class_setup_methods (klass);
9383 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9384 See mono/tests/array_load_exception.il
9385 FIXME we should better report this error to the caller
9387 if (!klass->methods)
9389 for (i = 0; i < klass->method.count; ++i) {
9390 MonoMethod *method = klass->methods [i];
9392 if (method->name[0] == name [0] &&
9393 !strcmp (name, method->name) &&
9394 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9395 ((method->flags & flags) == flags)) {
9402 res = find_method_in_metadata (klass, name, param_count, flags);
9409 * mono_class_set_failure:
9410 * @klass: class in which the failure was detected
9411 * @ex_type: the kind of exception/error to be thrown (later)
9412 * @ex_data: exception data (specific to each type of exception/error)
9414 * Keep a detected failure informations in the class for later processing.
9415 * Note that only the first failure is kept.
9417 * LOCKING: Acquires the loader lock.
9420 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9422 if (klass->exception_type)
9425 mono_loader_lock ();
9426 klass->exception_type = ex_type;
9428 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9429 mono_loader_unlock ();
9435 * mono_class_get_exception_data:
9437 * Return the exception_data property of KLASS.
9439 * LOCKING: Acquires the loader lock.
9442 mono_class_get_exception_data (MonoClass *klass)
9444 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9448 * mono_classes_init:
9450 * Initialize the resources used by this module.
9453 mono_classes_init (void)
9455 mono_mutex_init (&classes_mutex);
9457 mono_counters_register ("Inflated methods size",
9458 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9459 mono_counters_register ("Inflated classes",
9460 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9461 mono_counters_register ("Inflated classes size",
9462 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9463 mono_counters_register ("MonoClass size",
9464 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9465 mono_counters_register ("MonoClassExt size",
9466 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9470 * mono_classes_cleanup:
9472 * Free the resources used by this module.
9475 mono_classes_cleanup (void)
9477 if (global_interface_bitset)
9478 mono_bitset_free (global_interface_bitset);
9479 global_interface_bitset = NULL;
9480 mono_mutex_destroy (&classes_mutex);
9484 * mono_class_get_exception_for_failure:
9485 * @klass: class in which the failure was detected
9487 * Return a constructed MonoException than the caller can then throw
9488 * using mono_raise_exception - or NULL if no failure is present (or
9489 * doesn't result in an exception).
9492 mono_class_get_exception_for_failure (MonoClass *klass)
9494 gpointer exception_data = mono_class_get_exception_data (klass);
9496 switch (klass->exception_type) {
9497 #ifndef DISABLE_SECURITY
9498 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9499 MonoDomain *domain = mono_domain_get ();
9500 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9501 MonoMethod *method = exception_data;
9502 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9503 MonoObject *exc = NULL;
9507 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9508 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9509 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9511 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9512 return (MonoException*) exc;
9515 case MONO_EXCEPTION_TYPE_LOAD: {
9518 char *str = mono_type_get_full_name (klass);
9519 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9520 name = mono_string_new (mono_domain_get (), str);
9522 ex = mono_get_exception_type_load (name, astr);
9526 case MONO_EXCEPTION_MISSING_METHOD: {
9527 char *class_name = exception_data;
9528 char *assembly_name = class_name + strlen (class_name) + 1;
9530 return mono_get_exception_missing_method (class_name, assembly_name);
9532 case MONO_EXCEPTION_MISSING_FIELD: {
9533 char *class_name = exception_data;
9534 char *member_name = class_name + strlen (class_name) + 1;
9536 return mono_get_exception_missing_field (class_name, member_name);
9538 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9539 char *msg_format = exception_data;
9540 char *assembly_name = msg_format + strlen (msg_format) + 1;
9541 char *msg = g_strdup_printf (msg_format, assembly_name);
9544 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9550 case MONO_EXCEPTION_BAD_IMAGE: {
9551 return mono_get_exception_bad_image_format (exception_data);
9554 MonoLoaderError *error;
9557 error = mono_loader_get_last_error ();
9559 ex = mono_loader_error_prepare_exception (error);
9563 /* TODO - handle other class related failures */
9570 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9572 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9573 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9575 if (outer_klass == inner_klass)
9577 inner_klass = inner_klass->nested_in;
9578 } while (inner_klass);
9583 mono_class_get_generic_type_definition (MonoClass *klass)
9585 return klass->generic_class ? klass->generic_class->container_class : klass;
9589 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9591 * Generic instantiations are ignored for all super types of @klass.
9593 * Visibility checks ignoring generic instantiations.
9596 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9599 klass = mono_class_get_generic_type_definition (klass);
9600 parent = mono_class_get_generic_type_definition (parent);
9601 mono_class_setup_supertypes (klass);
9603 for (i = 0; i < klass->idepth; ++i) {
9604 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9610 * Subtype can only access parent members with family protection if the site object
9611 * is subclass of Subtype. For example:
9612 * class A { protected int x; }
9614 * void valid_access () {
9618 * void invalid_access () {
9625 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9627 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9630 if (context_klass == NULL)
9632 /*if access_klass is not member_klass context_klass must be type compat*/
9633 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9639 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9642 if (accessing == accessed)
9644 if (!accessed || !accessing)
9647 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9648 * anywhere so untrusted friends are not safe to access platform's code internals */
9649 if (mono_security_core_clr_enabled ()) {
9650 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9654 mono_assembly_load_friends (accessed);
9655 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9656 MonoAssemblyName *friend = tmp->data;
9657 /* Be conservative with checks */
9660 if (strcmp (accessing->aname.name, friend->name))
9662 if (friend->public_key_token [0]) {
9663 if (!accessing->aname.public_key_token [0])
9665 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9674 * If klass is a generic type or if it is derived from a generic type, return the
9675 * MonoClass of the generic definition
9676 * Returns NULL if not found
9679 get_generic_definition_class (MonoClass *klass)
9682 if (klass->generic_class && klass->generic_class->container_class)
9683 return klass->generic_class->container_class;
9684 klass = klass->parent;
9690 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9693 for (i = 0; i < ginst->type_argc; ++i) {
9694 MonoType *type = ginst->type_argv[i];
9695 switch (type->type) {
9696 case MONO_TYPE_SZARRAY:
9697 if (!can_access_type (access_klass, type->data.klass))
9700 case MONO_TYPE_ARRAY:
9701 if (!can_access_type (access_klass, type->data.array->eklass))
9705 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9708 case MONO_TYPE_CLASS:
9709 case MONO_TYPE_VALUETYPE:
9710 case MONO_TYPE_GENERICINST:
9711 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9719 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9723 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9726 if (access_klass->element_class && !access_klass->enumtype)
9727 access_klass = access_klass->element_class;
9729 if (member_klass->element_class && !member_klass->enumtype)
9730 member_klass = member_klass->element_class;
9732 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9734 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9737 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9740 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9743 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9746 /*Non nested type with nested visibility. We just fail it.*/
9747 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9750 switch (access_level) {
9751 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9752 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9754 case TYPE_ATTRIBUTE_PUBLIC:
9757 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9760 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9761 return is_nesting_type (member_klass, access_klass);
9763 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9764 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9766 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9767 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9769 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9770 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9771 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9773 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9774 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9775 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9780 /* FIXME: check visibility of type, too */
9782 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9784 MonoClass *member_generic_def;
9785 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9788 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9789 access_klass->generic_container) &&
9790 (member_generic_def = get_generic_definition_class (member_klass))) {
9791 MonoClass *access_container;
9793 if (access_klass->generic_container)
9794 access_container = access_klass;
9796 access_container = access_klass->generic_class->container_class;
9798 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9802 /* Partition I 8.5.3.2 */
9803 /* the access level values are the same for fields and methods */
9804 switch (access_level) {
9805 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9806 /* same compilation unit */
9807 return access_klass->image == member_klass->image;
9808 case FIELD_ATTRIBUTE_PRIVATE:
9809 return access_klass == member_klass;
9810 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9811 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9812 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9815 case FIELD_ATTRIBUTE_ASSEMBLY:
9816 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9817 case FIELD_ATTRIBUTE_FAMILY:
9818 if (is_valid_family_access (access_klass, member_klass, context_klass))
9821 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9822 if (is_valid_family_access (access_klass, member_klass, context_klass))
9824 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9825 case FIELD_ATTRIBUTE_PUBLIC:
9832 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9834 /* FIXME: check all overlapping fields */
9835 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9837 MonoClass *nested = method->klass->nested_in;
9839 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9842 nested = nested->nested_in;
9849 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9851 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9853 MonoClass *nested = method->klass->nested_in;
9855 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9858 nested = nested->nested_in;
9863 * with generics calls to explicit interface implementations can be expressed
9864 * directly: the method is private, but we must allow it. This may be opening
9865 * a hole or the generics code should handle this differently.
9866 * Maybe just ensure the interface type is public.
9868 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9874 * mono_method_can_access_method_full:
9875 * @method: The caller method
9876 * @called: The called method
9877 * @context_klass: The static type on stack of the owner @called object used
9879 * This function must be used with instance calls, as they have more strict family accessibility.
9880 * It can be used with static methods, but context_klass should be NULL.
9882 * Returns: TRUE if caller have proper visibility and acessibility to @called
9885 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9887 MonoClass *access_class = method->klass;
9888 MonoClass *member_class = called->klass;
9889 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9891 MonoClass *nested = access_class->nested_in;
9893 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9896 nested = nested->nested_in;
9903 can = can_access_type (access_class, member_class);
9905 MonoClass *nested = access_class->nested_in;
9907 can = can_access_type (nested, member_class);
9910 nested = nested->nested_in;
9917 if (called->is_inflated) {
9918 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9919 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9928 * mono_method_can_access_field_full:
9929 * @method: The caller method
9930 * @field: The accessed field
9931 * @context_klass: The static type on stack of the owner @field object used
9933 * This function must be used with instance fields, as they have more strict family accessibility.
9934 * It can be used with static fields, but context_klass should be NULL.
9936 * Returns: TRUE if caller have proper visibility and acessibility to @field
9939 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9941 MonoClass *access_class = method->klass;
9942 MonoClass *member_class = field->parent;
9943 /* FIXME: check all overlapping fields */
9944 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9946 MonoClass *nested = access_class->nested_in;
9948 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9951 nested = nested->nested_in;
9958 can = can_access_type (access_class, member_class);
9960 MonoClass *nested = access_class->nested_in;
9962 can = can_access_type (nested, member_class);
9965 nested = nested->nested_in;
9975 * mono_class_can_access_class:
9976 * @source_class: The source class
9977 * @target_class: The accessed class
9979 * This function returns is @target_class is visible to @source_class
9981 * Returns: TRUE if source have proper visibility and acessibility to target
9984 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9986 return can_access_type (source_class, target_class);
9990 * mono_type_is_valid_enum_basetype:
9991 * @type: The MonoType to check
9993 * Returns: TRUE if the type can be used as the basetype of an enum
9995 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9996 switch (type->type) {
9999 case MONO_TYPE_BOOLEAN:
10002 case MONO_TYPE_CHAR:
10015 * mono_class_is_valid_enum:
10016 * @klass: An enum class to be validated
10018 * This method verify the required properties an enum should have.
10020 * Returns: TRUE if the informed enum class is valid
10022 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10023 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10024 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10026 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10027 MonoClassField * field;
10028 gpointer iter = NULL;
10029 gboolean found_base_field = FALSE;
10031 g_assert (klass->enumtype);
10032 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10033 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10037 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10040 while ((field = mono_class_get_fields (klass, &iter))) {
10041 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10042 if (found_base_field)
10044 found_base_field = TRUE;
10045 if (!mono_type_is_valid_enum_basetype (field->type))
10050 if (!found_base_field)
10053 if (klass->method.count > 0)
10060 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10062 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10066 * mono_class_setup_interface_id:
10068 * Initializes MonoClass::interface_id if required.
10070 * LOCKING: Acquires the loader lock.
10073 mono_class_setup_interface_id (MonoClass *class)
10075 mono_loader_lock ();
10076 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10077 class->interface_id = mono_get_unique_iid (class);
10078 mono_loader_unlock ();
10082 * mono_class_alloc_ext:
10084 * Allocate klass->ext if not already done.
10085 * LOCKING: Assumes the loader lock is held.
10088 mono_class_alloc_ext (MonoClass *klass)
10091 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10092 class_ext_size += sizeof (MonoClassExt);
10097 * mono_class_setup_interfaces:
10099 * Initialize class->interfaces/interfaces_count.
10100 * LOCKING: Acquires the loader lock.
10101 * This function can fail the type.
10104 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10106 int i, interface_count;
10107 MonoClass **interfaces;
10109 mono_error_init (error);
10111 if (klass->interfaces_inited)
10114 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10115 MonoType *args [1];
10117 /* generic IList, ICollection, IEnumerable */
10118 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10119 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10121 args [0] = &klass->element_class->byval_arg;
10122 interfaces [0] = mono_class_bind_generic_parameters (
10123 mono_defaults.generic_ilist_class, 1, args, FALSE);
10124 if (interface_count > 1)
10125 interfaces [1] = mono_class_bind_generic_parameters (
10126 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10127 } else if (klass->generic_class) {
10128 MonoClass *gklass = klass->generic_class->container_class;
10130 mono_class_setup_interfaces (gklass, error);
10131 if (!mono_error_ok (error)) {
10132 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10136 interface_count = gklass->interface_count;
10137 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10138 for (i = 0; i < interface_count; i++) {
10139 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10140 if (!mono_error_ok (error)) {
10141 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10146 interface_count = 0;
10150 mono_image_lock (klass->image);
10152 if (klass->interfaces_inited) {
10153 mono_image_unlock (klass->image);
10157 klass->interface_count = interface_count;
10158 klass->interfaces = interfaces;
10160 mono_memory_barrier ();
10162 klass->interfaces_inited = TRUE;
10164 mono_image_unlock (klass->image);
10168 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10170 MonoClass *class = field->parent;
10171 MonoImage *image = class->image;
10172 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10173 int field_idx = field - class->fields;
10175 mono_error_init (error);
10178 MonoClassField *gfield = >d->fields [field_idx];
10179 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10180 if (!mono_error_ok (error)) {
10181 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10182 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10186 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10187 if (!mono_error_ok (error)) {
10188 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10189 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10194 guint32 cols [MONO_FIELD_SIZE];
10195 MonoGenericContainer *container = NULL;
10196 int idx = class->field.first + field_idx;
10198 /*FIXME, in theory we do not lazy load SRE fields*/
10199 g_assert (!image_is_dynamic (image));
10201 if (class->generic_container) {
10202 container = class->generic_container;
10204 container = gtd->generic_container;
10205 g_assert (container);
10208 /* class->field.first and idx points into the fieldptr table */
10209 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10211 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10212 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10213 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10217 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10219 mono_metadata_decode_value (sig, &sig);
10220 /* FIELD signature == 0x06 */
10221 g_assert (*sig == 0x06);
10222 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10224 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10229 mono_field_resolve_flags (MonoClassField *field)
10231 MonoClass *class = field->parent;
10232 MonoImage *image = class->image;
10233 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10234 int field_idx = field - class->fields;
10238 MonoClassField *gfield = >d->fields [field_idx];
10239 return mono_field_get_flags (gfield);
10241 int idx = class->field.first + field_idx;
10243 /*FIXME, in theory we do not lazy load SRE fields*/
10244 g_assert (!image_is_dynamic (image));
10246 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10251 * mono_class_setup_basic_field_info:
10252 * @class: The class to initialize
10254 * Initializes the class->fields array of fields.
10255 * Aquires the loader lock.
10258 mono_class_setup_basic_field_info_locking (MonoClass *class)
10260 mono_loader_lock ();
10261 mono_class_setup_basic_field_info (class);
10262 mono_loader_unlock ();
10266 * mono_class_get_fields_lazy:
10267 * @klass: the MonoClass to act on
10269 * This routine is an iterator routine for retrieving the fields in a class.
10270 * Only minimal information about fields are loaded. Accessors must be used
10271 * for all MonoClassField returned.
10273 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10274 * iterate over all of the elements. When no more values are
10275 * available, the return value is NULL.
10277 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10280 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10282 MonoClassField* field;
10286 mono_class_setup_basic_field_info_locking (klass);
10287 if (!klass->fields)
10289 /* start from the first */
10290 if (klass->field.count) {
10291 return *iter = &klass->fields [0];
10299 if (field < &klass->fields [klass->field.count]) {
10300 return *iter = field;
10306 mono_class_full_name (MonoClass *klass)
10308 return mono_type_full_name (&klass->byval_arg);