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 /* Function supplied by the runtime to find classes by name using information from the AOT file */
56 static MonoGetClassFromName get_class_from_name = NULL;
58 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
59 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
60 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
61 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
62 static int generic_array_methods (MonoClass *class);
63 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
65 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
66 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
67 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
68 static guint32 mono_field_resolve_flags (MonoClassField *field);
69 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
70 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
73 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
77 We use gclass recording to allow recursive system f types to be referenced by a parent.
79 Given the following type hierarchy:
81 class TextBox : TextBoxBase<TextBox> {}
82 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
83 class TextInput<T> : Input<T> where T: TextInput<T> {}
86 The runtime tries to load TextBoxBase<>.
87 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
88 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
89 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
91 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
92 at this point, iow, both are registered in the type map and both and a NULL parent. This means
93 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
95 To fix that what we do is to record all generic instantes created while resolving the parent of
96 any generic type definition and, after resolved, correct the parent field if needed.
99 static int record_gclass_instantiation;
100 static GSList *gclass_recorded_list;
101 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
104 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
107 enable_gclass_recording (void)
109 ++record_gclass_instantiation;
113 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
116 disable_gclass_recording (gclass_record_func func, void *user_data)
118 GSList **head = &gclass_recorded_list;
120 g_assert (record_gclass_instantiation > 0);
121 --record_gclass_instantiation;
124 GSList *node = *head;
125 if (func ((MonoClass*)node->data, user_data)) {
127 g_slist_free_1 (node);
133 /* We automatically discard all recorded gclasses when disabled. */
134 if (!record_gclass_instantiation && gclass_recorded_list) {
135 g_slist_free (gclass_recorded_list);
136 gclass_recorded_list = NULL;
141 * mono_class_from_typeref:
142 * @image: a MonoImage
143 * @type_token: a TypeRef token
145 * Creates the MonoClass* structure representing the type defined by
146 * the typeref token valid inside @image.
147 * Returns: the MonoClass* representing the typeref token, NULL ifcould
151 mono_class_from_typeref (MonoImage *image, guint32 type_token)
154 guint32 cols [MONO_TYPEREF_SIZE];
155 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
157 const char *name, *nspace;
161 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, &error)) {
162 mono_trace_warning (MONO_TRACE_TYPE, "Failed to resolve typeref from %s due to '%s'", image->name, mono_error_get_message (&error));
166 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
168 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
169 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
171 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
172 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
173 case MONO_RESOLTION_SCOPE_MODULE:
175 g_error ("null ResolutionScope not yet handled");
176 /* a typedef in disguise */
177 return mono_class_from_name (image, nspace, name);
178 case MONO_RESOLTION_SCOPE_MODULEREF:
179 module = mono_image_load_module (image, idx);
181 return mono_class_from_name (module, nspace, name);
183 char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
186 human_name = mono_stringify_assembly_name (&image->assembly->aname);
187 mono_loader_set_error_type_load (msg, human_name);
193 case MONO_RESOLTION_SCOPE_TYPEREF: {
194 MonoClass *enclosing;
197 if (idx == mono_metadata_token_index (type_token)) {
198 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token));
202 enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
206 if (enclosing->nested_classes_inited && enclosing->ext) {
207 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
208 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
210 if (strcmp (res->name, name) == 0)
214 /* Don't call mono_class_init as we might've been called by it recursively */
215 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
217 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
218 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
219 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
221 if (strcmp (nname, name) == 0) {
222 MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
223 if (!mono_error_ok (&error)) {
224 mono_loader_set_error_from_mono_error (&error);
225 mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
231 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
234 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
237 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
241 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
242 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
246 if (!image->references || !image->references [idx - 1])
247 mono_assembly_load_reference (image, idx - 1);
248 g_assert (image->references [idx - 1]);
250 /* If the assembly did not load, register this as a type load exception */
251 if (image->references [idx - 1] == REFERENCE_MISSING){
252 MonoAssemblyName aname;
255 mono_assembly_get_assemblyref (image, idx - 1, &aname);
256 human_name = mono_stringify_assembly_name (&aname);
257 mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
263 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
268 mono_image_memdup (MonoImage *image, void *data, guint size)
270 void *res = mono_image_alloc (image, size);
271 memcpy (res, data, size);
275 /* Copy everything mono_metadata_free_array free. */
277 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
280 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
282 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
284 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
286 a = g_memdup (a, sizeof (MonoArrayType));
288 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
290 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
295 /* Copy everything mono_metadata_free_method_signature free. */
297 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
301 sig = mono_metadata_signature_dup_full (image, sig);
303 sig->ret = mono_metadata_type_dup (image, sig->ret);
304 for (i = 0; i < sig->param_count; ++i)
305 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
311 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
313 MonoAssembly *ta = klass->image->assembly;
316 name = mono_stringify_assembly_name (&ta->aname);
317 g_string_append_printf (str, ", %s", name);
322 mono_type_name_check_byref (MonoType *type, GString *str)
325 g_string_append_c (str, '&');
329 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
330 MonoTypeNameFormat format)
334 switch (type->type) {
335 case MONO_TYPE_ARRAY: {
336 int i, rank = type->data.array->rank;
337 MonoTypeNameFormat nested_format;
339 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
340 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
342 mono_type_get_name_recurse (
343 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
344 g_string_append_c (str, '[');
346 g_string_append_c (str, '*');
347 for (i = 1; i < rank; i++)
348 g_string_append_c (str, ',');
349 g_string_append_c (str, ']');
351 mono_type_name_check_byref (type, str);
353 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
354 _mono_type_get_assembly_name (type->data.array->eklass, str);
357 case MONO_TYPE_SZARRAY: {
358 MonoTypeNameFormat nested_format;
360 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
361 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
363 mono_type_get_name_recurse (
364 &type->data.klass->byval_arg, str, FALSE, nested_format);
365 g_string_append (str, "[]");
367 mono_type_name_check_byref (type, str);
369 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
370 _mono_type_get_assembly_name (type->data.klass, str);
373 case MONO_TYPE_PTR: {
374 MonoTypeNameFormat nested_format;
376 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
377 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
379 mono_type_get_name_recurse (
380 type->data.type, str, FALSE, nested_format);
381 g_string_append_c (str, '*');
383 mono_type_name_check_byref (type, str);
385 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
386 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
391 if (!mono_generic_param_info (type->data.generic_param))
392 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
394 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
396 mono_type_name_check_byref (type, str);
400 klass = mono_class_from_mono_type (type);
401 if (klass->nested_in) {
402 mono_type_get_name_recurse (
403 &klass->nested_in->byval_arg, str, TRUE, format);
404 if (format == MONO_TYPE_NAME_FORMAT_IL)
405 g_string_append_c (str, '.');
407 g_string_append_c (str, '+');
408 } else if (*klass->name_space) {
409 g_string_append (str, klass->name_space);
410 g_string_append_c (str, '.');
412 if (format == MONO_TYPE_NAME_FORMAT_IL) {
413 char *s = strchr (klass->name, '`');
414 int len = s ? s - klass->name : strlen (klass->name);
416 g_string_append_len (str, klass->name, len);
418 g_string_append (str, klass->name);
421 if (klass->generic_class) {
422 MonoGenericClass *gclass = klass->generic_class;
423 MonoGenericInst *inst = gclass->context.class_inst;
424 MonoTypeNameFormat nested_format;
427 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
428 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
430 if (format == MONO_TYPE_NAME_FORMAT_IL)
431 g_string_append_c (str, '<');
433 g_string_append_c (str, '[');
434 for (i = 0; i < inst->type_argc; i++) {
435 MonoType *t = inst->type_argv [i];
438 g_string_append_c (str, ',');
439 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
440 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
441 g_string_append_c (str, '[');
442 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
443 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
444 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
445 g_string_append_c (str, ']');
447 if (format == MONO_TYPE_NAME_FORMAT_IL)
448 g_string_append_c (str, '>');
450 g_string_append_c (str, ']');
451 } else if (klass->generic_container &&
452 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
453 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
456 if (format == MONO_TYPE_NAME_FORMAT_IL)
457 g_string_append_c (str, '<');
459 g_string_append_c (str, '[');
460 for (i = 0; i < klass->generic_container->type_argc; i++) {
462 g_string_append_c (str, ',');
463 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
465 if (format == MONO_TYPE_NAME_FORMAT_IL)
466 g_string_append_c (str, '>');
468 g_string_append_c (str, ']');
471 mono_type_name_check_byref (type, str);
473 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
474 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
475 _mono_type_get_assembly_name (klass, str);
481 * mono_type_get_name_full:
483 * @format: the format for the return string.
486 * Returns: the string representation in a number of formats:
488 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
489 * returned in the formatrequired by System.Reflection, this is the
490 * inverse of mono_reflection_parse_type ().
492 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
493 * be used by the IL assembler.
495 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
497 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
500 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
504 result = g_string_new ("");
506 mono_type_get_name_recurse (type, result, FALSE, format);
508 return g_string_free (result, FALSE);
512 * mono_type_get_full_name:
515 * Returns: the string representation for type as required by System.Reflection.
516 * The inverse of mono_reflection_parse_type ().
519 mono_type_get_full_name (MonoClass *class)
521 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
525 * mono_type_get_name:
528 * Returns: the string representation for type as it would be represented in IL code.
531 mono_type_get_name (MonoType *type)
533 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
537 * mono_type_get_underlying_type:
540 * Returns: the MonoType for the underlying integer type if @type
541 * is an enum and byref is false, otherwise the type itself.
544 mono_type_get_underlying_type (MonoType *type)
546 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
547 return mono_class_enum_basetype (type->data.klass);
548 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
549 return mono_class_enum_basetype (type->data.generic_class->container_class);
554 * mono_class_is_open_constructed_type:
557 * Returns TRUE if type represents a generics open constructed type.
558 * IOW, not all type parameters required for the instantiation have
559 * been provided or it's a generic type definition.
561 * An open constructed type means it's a non realizable type. Not to
562 * be mixed up with an abstract type - we can't cast or dispatch to
563 * an open type, for example.
566 mono_class_is_open_constructed_type (MonoType *t)
572 case MONO_TYPE_SZARRAY:
573 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
574 case MONO_TYPE_ARRAY:
575 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
577 return mono_class_is_open_constructed_type (t->data.type);
578 case MONO_TYPE_GENERICINST:
579 return t->data.generic_class->context.class_inst->is_open;
580 case MONO_TYPE_CLASS:
581 case MONO_TYPE_VALUETYPE:
582 return t->data.klass->generic_container != NULL;
589 This is a simple function to catch the most common bad instances of generic types.
590 Specially those that might lead to further failures in the runtime.
593 is_valid_generic_argument (MonoType *type)
595 switch (type->type) {
597 //case MONO_TYPE_TYPEDBYREF:
604 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
606 mono_error_init (error);
608 switch (type->type) {
609 case MONO_TYPE_MVAR: {
611 int num = mono_type_get_generic_param_num (type);
612 MonoGenericInst *inst = context->method_inst;
613 if (!inst || !inst->type_argv)
615 if (num >= inst->type_argc) {
616 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
617 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
618 num, info ? info->name : "", inst->type_argc);
622 if (!is_valid_generic_argument (inst->type_argv [num])) {
623 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
624 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
625 num, info ? info->name : "", inst->type_argv [num]->type);
629 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
630 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
631 * ->byref and ->attrs from @type are propagated to the returned type.
633 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
634 nt->byref = type->byref;
635 nt->attrs = type->attrs;
638 case MONO_TYPE_VAR: {
640 int num = mono_type_get_generic_param_num (type);
641 MonoGenericInst *inst = context->class_inst;
644 if (num >= inst->type_argc) {
645 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
646 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
647 num, info ? info->name : "", inst->type_argc);
650 if (!is_valid_generic_argument (inst->type_argv [num])) {
651 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
652 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
653 num, info ? info->name : "", inst->type_argv [num]->type);
656 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
657 nt->byref = type->byref;
658 nt->attrs = type->attrs;
661 case MONO_TYPE_SZARRAY: {
662 MonoClass *eclass = type->data.klass;
663 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
664 if (!inflated || !mono_error_ok (error))
666 nt = mono_metadata_type_dup (image, type);
667 nt->data.klass = mono_class_from_mono_type (inflated);
668 mono_metadata_free_type (inflated);
671 case MONO_TYPE_ARRAY: {
672 MonoClass *eclass = type->data.array->eklass;
673 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
674 if (!inflated || !mono_error_ok (error))
676 nt = mono_metadata_type_dup (image, type);
677 nt->data.array->eklass = mono_class_from_mono_type (inflated);
678 mono_metadata_free_type (inflated);
681 case MONO_TYPE_GENERICINST: {
682 MonoGenericClass *gclass = type->data.generic_class;
683 MonoGenericInst *inst;
685 if (!gclass->context.class_inst->is_open)
688 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
689 if (!mono_error_ok (error))
691 if (inst != gclass->context.class_inst)
692 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
694 if (gclass == type->data.generic_class)
697 nt = mono_metadata_type_dup (image, type);
698 nt->data.generic_class = gclass;
701 case MONO_TYPE_CLASS:
702 case MONO_TYPE_VALUETYPE: {
703 MonoClass *klass = type->data.klass;
704 MonoGenericContainer *container = klass->generic_container;
705 MonoGenericInst *inst;
706 MonoGenericClass *gclass = NULL;
712 /* We can't use context->class_inst directly, since it can have more elements */
713 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
714 if (!mono_error_ok (error))
716 if (inst == container->context.class_inst)
719 gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
721 nt = mono_metadata_type_dup (image, type);
722 nt->type = MONO_TYPE_GENERICINST;
723 nt->data.generic_class = gclass;
733 mono_generic_class_get_context (MonoGenericClass *gclass)
735 return &gclass->context;
739 mono_class_get_context (MonoClass *class)
741 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
745 * mono_class_get_generic_container:
747 * Return the generic container of KLASS which should be a generic type definition.
749 MonoGenericContainer*
750 mono_class_get_generic_container (MonoClass *klass)
752 g_assert (klass->is_generic);
754 return klass->generic_container;
758 * mono_class_get_generic_class:
760 * Return the MonoGenericClass of KLASS, which should be a generic instance.
763 mono_class_get_generic_class (MonoClass *klass)
765 g_assert (klass->is_inflated);
767 return klass->generic_class;
771 * mono_class_inflate_generic_type_with_mempool:
772 * @mempool: a mempool
774 * @context: a generics context
775 * @error: error context
777 * The same as mono_class_inflate_generic_type, but allocates the MonoType
778 * from mempool if it is non-NULL. If it is NULL, the MonoType is
779 * allocated on the heap and is owned by the caller.
780 * The returned type can potentially be the same as TYPE, so it should not be
781 * modified by the caller, and it should be freed using mono_metadata_free_type ().
784 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
786 MonoType *inflated = NULL;
787 mono_error_init (error);
790 inflated = inflate_generic_type (image, type, context, error);
791 if (!mono_error_ok (error))
795 MonoType *shared = mono_metadata_get_shared_type (type);
800 return mono_metadata_type_dup (image, type);
804 mono_stats.inflated_type_count++;
809 * mono_class_inflate_generic_type:
811 * @context: a generics context
813 * If @type is a generic type and @context is not NULL, instantiate it using the
814 * generics context @context.
816 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
817 * on the heap and is owned by the caller. Returns NULL on error.
819 * @deprecated Please use mono_class_inflate_generic_type_checked instead
822 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
826 result = mono_class_inflate_generic_type_checked (type, context, &error);
828 if (!mono_error_ok (&error)) {
829 mono_error_cleanup (&error);
836 * mono_class_inflate_generic_type:
838 * @context: a generics context
839 * @error: error context to use
841 * If @type is a generic type and @context is not NULL, instantiate it using the
842 * generics context @context.
844 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
845 * on the heap and is owned by the caller.
848 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
850 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
854 * mono_class_inflate_generic_type_no_copy:
856 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
860 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
862 MonoType *inflated = NULL;
864 mono_error_init (error);
866 inflated = inflate_generic_type (image, type, context, error);
867 if (!mono_error_ok (error))
874 mono_stats.inflated_type_count++;
879 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
884 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
885 if (!mono_error_ok (error))
888 res = mono_class_from_mono_type (inflated);
889 mono_metadata_free_type (inflated);
894 * mono_class_inflate_generic_class:
896 * Inflate the class GKLASS with CONTEXT.
899 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
904 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
905 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
912 static MonoGenericContext
913 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
915 MonoGenericInst *class_inst = NULL;
916 MonoGenericInst *method_inst = NULL;
917 MonoGenericContext res = { NULL, NULL };
919 mono_error_init (error);
921 if (context->class_inst) {
922 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
923 if (!mono_error_ok (error))
927 if (context->method_inst) {
928 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
929 if (!mono_error_ok (error))
933 res.class_inst = class_inst;
934 res.method_inst = method_inst;
940 * mono_class_inflate_generic_method:
941 * @method: a generic method
942 * @context: a generics context
944 * Instantiate the generic method @method using the generics context @context.
946 * Returns: the new instantiated method
949 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
951 return mono_class_inflate_generic_method_full (method, NULL, context);
955 * mono_class_inflate_generic_method_full:
957 * Instantiate method @method with the generic context @context.
958 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
959 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
962 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
965 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
966 if (!mono_error_ok (&error))
967 /*FIXME do proper error handling - on this case, kill this function. */
968 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
974 * mono_class_inflate_generic_method_full_checked:
975 * Same as mono_class_inflate_generic_method_full but return failure using @error.
978 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
981 MonoMethodInflated *iresult, *cached;
982 MonoMethodSignature *sig;
983 MonoGenericContext tmp_context;
984 gboolean is_mb_open = FALSE;
986 mono_error_init (error);
988 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
989 while (method->is_inflated) {
990 MonoGenericContext *method_context = mono_method_get_context (method);
991 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
993 tmp_context = inflate_generic_context (method_context, context, error);
994 if (!mono_error_ok (error))
996 context = &tmp_context;
998 if (mono_metadata_generic_context_equal (method_context, context))
1001 method = imethod->declaring;
1005 * A method only needs to be inflated if the context has argument for which it is
1008 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1009 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1012 if (!((method->is_generic && context->method_inst) ||
1013 (method->klass->generic_container && context->class_inst)))
1017 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1018 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1019 * This is opposite to the way non-SRE MethodInfos behave.
1021 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1023 * void Example<T> () {
1027 * In Example, the method token must be encoded as: "void Example<!!0>()"
1029 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1030 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1032 * On the other hand, inflating a non-SRE generic method with its own arguments should
1033 * return itself. For example:
1035 * MethodInfo m = ... //m is a generic method definition
1036 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1039 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1040 * what happens with regular methods.
1042 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1043 * everything should behave like a regular type or method.
1046 is_mb_open = method->is_generic &&
1047 method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1048 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1050 iresult = g_new0 (MonoMethodInflated, 1);
1051 iresult->context = *context;
1052 iresult->declaring = method;
1053 iresult->method.method.is_mb_open = is_mb_open;
1055 if (!context->method_inst && method->is_generic)
1056 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1058 if (!context->class_inst) {
1059 g_assert (!iresult->declaring->klass->generic_class);
1060 if (iresult->declaring->klass->generic_container)
1061 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1062 else if (iresult->declaring->klass->generic_class)
1063 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1066 mono_loader_lock ();
1067 cached = mono_method_inflated_lookup (iresult, FALSE);
1069 mono_loader_unlock ();
1071 return (MonoMethod*)cached;
1074 mono_stats.inflated_method_count++;
1076 inflated_methods_size += sizeof (MonoMethodInflated);
1078 sig = mono_method_signature (method);
1080 char *name = mono_type_get_full_name (method->klass);
1081 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1087 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1089 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1092 result = (MonoMethod *) iresult;
1093 result->is_inflated = TRUE;
1094 result->is_generic = FALSE;
1095 result->sre_method = FALSE;
1096 result->signature = NULL;
1097 result->is_mb_open = is_mb_open;
1099 if (!context->method_inst) {
1100 /* Set the generic_container of the result to the generic_container of method */
1101 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1103 if (generic_container) {
1104 result->is_generic = 1;
1105 mono_method_set_generic_container (result, generic_container);
1109 if (!klass_hint || !klass_hint->generic_class ||
1110 klass_hint->generic_class->container_class != method->klass ||
1111 klass_hint->generic_class->context.class_inst != context->class_inst)
1114 if (method->klass->generic_container)
1115 result->klass = klass_hint;
1117 if (!result->klass) {
1118 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1119 if (!mono_error_ok (error))
1122 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1124 mono_metadata_free_type (inflated);
1128 * FIXME: This should hold, but it doesn't:
1130 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1131 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1132 * g_assert (result->is_generic);
1135 * Fixing this here causes other things to break, hence a very
1136 * ugly hack in mini-trampolines.c - see
1137 * is_generic_method_definition().
1140 mono_method_inflated_lookup (iresult, TRUE);
1141 mono_loader_unlock ();
1145 mono_loader_unlock ();
1151 * mono_get_inflated_method:
1153 * Obsolete. We keep it around since it's mentioned in the public API.
1156 mono_get_inflated_method (MonoMethod *method)
1162 * mono_method_get_context_general:
1164 * @uninflated: handle uninflated methods?
1166 * Returns the generic context of a method or NULL if it doesn't have
1167 * one. For an inflated method that's the context stored in the
1168 * method. Otherwise it's in the method's generic container or in the
1169 * generic container of the method's class.
1172 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1174 if (method->is_inflated) {
1175 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1176 return &imethod->context;
1180 if (method->is_generic)
1181 return &(mono_method_get_generic_container (method)->context);
1182 if (method->klass->generic_container)
1183 return &method->klass->generic_container->context;
1188 * mono_method_get_context:
1191 * Returns the generic context for method if it's inflated, otherwise
1195 mono_method_get_context (MonoMethod *method)
1197 return mono_method_get_context_general (method, FALSE);
1201 * mono_method_get_generic_container:
1203 * Returns the generic container of METHOD, which should be a generic method definition.
1204 * Returns NULL if METHOD is not a generic method definition.
1205 * LOCKING: Acquires the loader lock.
1207 MonoGenericContainer*
1208 mono_method_get_generic_container (MonoMethod *method)
1210 MonoGenericContainer *container;
1212 if (!method->is_generic)
1215 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1216 g_assert (container);
1222 * mono_method_set_generic_container:
1224 * Sets the generic container of METHOD to CONTAINER.
1225 * LOCKING: Acquires the loader lock.
1228 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1230 g_assert (method->is_generic);
1232 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1236 * mono_class_find_enum_basetype:
1237 * @class: The enum class
1239 * Determine the basetype of an enum by iterating through its fields. We do this
1240 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1243 mono_class_find_enum_basetype (MonoClass *class)
1245 MonoGenericContainer *container = NULL;
1246 MonoImage *m = class->image;
1247 const int top = class->field.count;
1250 g_assert (class->enumtype);
1252 if (class->generic_container)
1253 container = class->generic_container;
1254 else if (class->generic_class) {
1255 MonoClass *gklass = class->generic_class->container_class;
1257 container = gklass->generic_container;
1258 g_assert (container);
1262 * Fetch all the field information.
1264 for (i = 0; i < top; i++){
1266 guint32 cols [MONO_FIELD_SIZE];
1267 int idx = class->field.first + i;
1270 /* class->field.first and idx points into the fieldptr table */
1271 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1273 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1276 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1279 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1280 mono_metadata_decode_value (sig, &sig);
1281 /* FIELD signature == 0x06 */
1285 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1288 if (class->generic_class) {
1289 //FIXME do we leak here?
1290 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1291 ftype->attrs = cols [MONO_FIELD_FLAGS];
1301 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1304 mono_type_has_exceptions (MonoType *type)
1306 switch (type->type) {
1307 case MONO_TYPE_CLASS:
1308 case MONO_TYPE_VALUETYPE:
1309 case MONO_TYPE_SZARRAY:
1310 return type->data.klass->exception_type;
1311 case MONO_TYPE_ARRAY:
1312 return type->data.array->eklass->exception_type;
1313 case MONO_TYPE_GENERICINST:
1314 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1322 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1326 mono_class_alloc (MonoClass *class, int size)
1328 if (class->generic_class)
1329 return mono_image_set_alloc (class->generic_class->owner, size);
1331 return mono_image_alloc (class->image, size);
1335 mono_class_alloc0 (MonoClass *class, int size)
1339 res = mono_class_alloc (class, size);
1340 memset (res, 0, size);
1344 #define mono_class_new0(class,struct_type, n_structs) \
1345 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1348 * mono_class_setup_basic_field_info:
1349 * @class: The class to initialize
1351 * Initializes the class->fields.
1352 * LOCKING: Assumes the loader lock is held.
1355 mono_class_setup_basic_field_info (MonoClass *class)
1357 MonoClassField *field;
1365 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1366 image = class->image;
1367 top = class->field.count;
1369 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1371 * This happens when a generic instance of an unfinished generic typebuilder
1372 * is used as an element type for creating an array type. We can't initialize
1373 * the fields of this class using the fields of gklass, since gklass is not
1374 * finished yet, fields could be added to it later.
1380 mono_class_setup_basic_field_info (gtd);
1382 top = gtd->field.count;
1383 class->field.first = gtd->field.first;
1384 class->field.count = gtd->field.count;
1387 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1390 * Fetch all the field information.
1392 for (i = 0; i < top; i++){
1393 field = &class->fields [i];
1394 field->parent = class;
1397 field->name = mono_field_get_name (>d->fields [i]);
1399 int idx = class->field.first + i;
1400 /* class->field.first and idx points into the fieldptr table */
1401 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1402 /* The name is needed for fieldrefs */
1403 field->name = mono_metadata_string_heap (image, name_idx);
1409 * mono_class_setup_fields:
1410 * @class: The class to initialize
1412 * Initializes the class->fields.
1413 * LOCKING: Assumes the loader lock is held.
1416 mono_class_setup_fields (MonoClass *class)
1419 MonoImage *m = class->image;
1421 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1422 int i, blittable = TRUE;
1423 guint32 real_size = 0;
1424 guint32 packing_size = 0;
1425 gboolean explicit_size;
1426 MonoClassField *field;
1427 MonoGenericContainer *container = NULL;
1428 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1431 * FIXME: We have a race condition here. It's possible that this function returns
1432 * to its caller with `instance_size` set to `0` instead of the actual size. This
1433 * is not a problem when the function is called recursively on the same class,
1434 * because the size will be initialized by the outer invocation. What follows is a
1435 * description of how it can occur in other cases, too. There it is a problem,
1436 * because it can lead to the GC being asked to allocate an object of size `0`,
1437 * which SGen chokes on. The race condition is triggered infrequently by
1438 * `tests/sgen-suspend.cs`.
1440 * This function is called for a class whenever one of its subclasses is inited.
1441 * For example, it's called for every subclass of Object. What it does is this:
1443 * if (class->setup_fields_called)
1446 * class->instance_size = 0;
1448 * class->setup_fields_called = 1;
1449 * ... critical point
1450 * class->instance_size = actual_instance_size;
1452 * The last two steps are sometimes reversed, but that only changes the way in which
1453 * the race condition works.
1455 * Assume thread A goes through this function and makes it to the critical point.
1456 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1457 * immediately, but `instance_size` is incorrect.
1459 * The other case looks like this:
1461 * if (class->setup_fields_called)
1463 * ... critical point X
1464 * class->instance_size = 0;
1465 * ... critical point Y
1466 * class->instance_size = actual_instance_size;
1468 * class->setup_fields_called = 1;
1470 * Assume thread A goes through the function and makes it to critical point X. Now
1471 * thread B runs through the whole of the function, returning, assuming
1472 * `instance_size` is set. At that point thread A gets to run and makes it to
1473 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1476 if (class->setup_fields_called)
1479 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1481 * This happens when a generic instance of an unfinished generic typebuilder
1482 * is used as an element type for creating an array type. We can't initialize
1483 * the fields of this class using the fields of gklass, since gklass is not
1484 * finished yet, fields could be added to it later.
1489 mono_class_setup_basic_field_info (class);
1490 top = class->field.count;
1493 mono_class_setup_fields (gtd);
1494 if (gtd->exception_type) {
1495 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1500 class->instance_size = 0;
1502 class->sizes.class_size = 0;
1504 if (class->parent) {
1505 /* For generic instances, class->parent might not have been initialized */
1506 mono_class_init (class->parent);
1507 if (!class->parent->size_inited) {
1508 mono_class_setup_fields (class->parent);
1509 if (class->parent->exception_type) {
1510 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1514 class->instance_size += class->parent->instance_size;
1515 class->min_align = class->parent->min_align;
1516 /* we use |= since it may have been set already */
1517 class->has_references |= class->parent->has_references;
1518 blittable = class->parent->blittable;
1520 class->instance_size = sizeof (MonoObject);
1521 class->min_align = 1;
1524 /* We can't really enable 16 bytes alignment until the GC supports it.
1525 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1526 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1527 Bug #506144 is an example of this issue.
1529 if (class->simd_type)
1530 class->min_align = 16;
1532 /* Get the real size */
1533 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1535 if (explicit_size) {
1536 if ((packing_size & 0xfffffff0) != 0) {
1537 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1538 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1541 class->packing_size = packing_size;
1542 real_size += class->instance_size;
1546 if (explicit_size && real_size) {
1547 class->instance_size = MAX (real_size, class->instance_size);
1549 class->blittable = blittable;
1550 mono_memory_barrier ();
1551 class->size_inited = 1;
1552 class->fields_inited = 1;
1553 class->setup_fields_called = 1;
1557 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1560 /* Prevent infinite loops if the class references itself */
1561 class->setup_fields_called = 1;
1563 if (class->generic_container) {
1564 container = class->generic_container;
1566 container = gtd->generic_container;
1567 g_assert (container);
1571 * Fetch all the field information.
1573 for (i = 0; i < top; i++){
1574 int idx = class->field.first + i;
1575 field = &class->fields [i];
1577 field->parent = class;
1580 mono_field_resolve_type (field, &error);
1581 if (!mono_error_ok (&error)) {
1582 /*mono_field_resolve_type already failed class*/
1583 mono_error_cleanup (&error);
1587 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1588 g_assert (field->type);
1591 if (mono_field_is_deleted (field))
1594 MonoClassField *gfield = >d->fields [i];
1595 field->offset = gfield->offset;
1597 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1599 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1600 field->offset = offset;
1602 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1603 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1606 if (field->offset < -1) { /*-1 is used to encode special static fields */
1607 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1613 /* Only do these checks if we still think this type is blittable */
1614 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1615 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1618 MonoClass *field_class = mono_class_from_mono_type (field->type);
1620 mono_class_setup_fields (field_class);
1621 if (field_class->exception_type) {
1622 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1626 if (!field_class || !field_class->blittable)
1631 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1632 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1633 blittable = class->element_class->blittable;
1636 if (mono_type_has_exceptions (field->type)) {
1637 char *class_name = mono_type_get_full_name (class);
1638 char *type_name = mono_type_full_name (field->type);
1640 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1641 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1642 g_free (class_name);
1646 /* The def_value of fields is compute lazily during vtable creation */
1649 if (class == mono_defaults.string_class)
1652 class->blittable = blittable;
1654 if (class->enumtype && !mono_class_enum_basetype (class)) {
1655 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1658 if (explicit_size && real_size) {
1659 class->instance_size = MAX (real_size, class->instance_size);
1662 if (class->exception_type)
1664 mono_class_layout_fields (class);
1666 /*valuetypes can't be neither bigger than 1Mb or empty. */
1667 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1668 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1670 mono_memory_barrier ();
1671 class->fields_inited = 1;
1675 * mono_class_setup_fields_locking:
1676 * @class: The class to initialize
1678 * Initializes the class->fields array of fields.
1679 * Aquires the loader lock.
1682 mono_class_setup_fields_locking (MonoClass *class)
1684 /* This can be checked without locks */
1685 if (class->fields_inited)
1687 mono_loader_lock ();
1688 mono_class_setup_fields (class);
1689 mono_loader_unlock ();
1693 * mono_class_has_references:
1695 * Returns whenever @klass->has_references is set, initializing it if needed.
1696 * Aquires the loader lock.
1699 mono_class_has_references (MonoClass *klass)
1701 if (klass->init_pending) {
1702 /* Be conservative */
1705 mono_class_init (klass);
1707 return klass->has_references;
1712 * mono_type_get_basic_type_from_generic:
1715 * Returns a closed type corresponding to the possibly open type
1719 mono_type_get_basic_type_from_generic (MonoType *type)
1721 /* When we do generic sharing we let type variables stand for reference types. */
1722 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1723 return &mono_defaults.object_class->byval_arg;
1728 * mono_class_layout_fields:
1731 * Compute the placement of fields inside an object or struct, according to
1732 * the layout rules and set the following fields in @class:
1733 * - has_references (if the class contains instance references firled or structs that contain references)
1734 * - has_static_refs (same, but for static fields)
1735 * - instance_size (size of the object in memory)
1736 * - class_size (size needed for the static fields)
1737 * - size_inited (flag set when the instance_size is set)
1739 * LOCKING: this is supposed to be called with the loader lock held.
1742 mono_class_layout_fields (MonoClass *class)
1745 const int top = class->field.count;
1746 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1747 guint32 pass, passes, real_size;
1748 gboolean gc_aware_layout = FALSE;
1749 MonoClassField *field;
1752 * When we do generic sharing we need to have layout
1753 * information for open generic classes (either with a generic
1754 * context containing type variables or with a generic
1755 * container), so we don't return in that case anymore.
1759 * Enable GC aware auto layout: in this mode, reference
1760 * fields are grouped together inside objects, increasing collector
1762 * Requires that all classes whose layout is known to native code be annotated
1763 * with [StructLayout (LayoutKind.Sequential)]
1764 * Value types have gc_aware_layout disabled by default, as per
1765 * what the default is for other runtimes.
1767 /* corlib is missing [StructLayout] directives in many places */
1768 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1769 if (!class->valuetype)
1770 gc_aware_layout = TRUE;
1773 /* Compute klass->has_references */
1775 * Process non-static fields first, since static fields might recursively
1776 * refer to the class itself.
1778 for (i = 0; i < top; i++) {
1781 field = &class->fields [i];
1783 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1784 ftype = mono_type_get_underlying_type (field->type);
1785 ftype = mono_type_get_basic_type_from_generic (ftype);
1786 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1787 class->has_references = TRUE;
1791 for (i = 0; i < top; i++) {
1794 field = &class->fields [i];
1796 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1797 ftype = mono_type_get_underlying_type (field->type);
1798 ftype = mono_type_get_basic_type_from_generic (ftype);
1799 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1800 class->has_static_refs = TRUE;
1804 for (i = 0; i < top; i++) {
1807 field = &class->fields [i];
1809 ftype = mono_type_get_underlying_type (field->type);
1810 ftype = mono_type_get_basic_type_from_generic (ftype);
1811 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1812 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1813 class->has_static_refs = TRUE;
1815 class->has_references = TRUE;
1820 * Compute field layout and total size (not considering static fields)
1824 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1825 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1827 if (gc_aware_layout)
1832 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1835 if (class->parent) {
1836 mono_class_setup_fields (class->parent);
1837 if (class->parent->exception_type) {
1838 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1841 real_size = class->parent->instance_size;
1843 real_size = sizeof (MonoObject);
1846 for (pass = 0; pass < passes; ++pass) {
1847 for (i = 0; i < top; i++){
1852 field = &class->fields [i];
1854 if (mono_field_is_deleted (field))
1856 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1859 ftype = mono_type_get_underlying_type (field->type);
1860 ftype = mono_type_get_basic_type_from_generic (ftype);
1861 if (gc_aware_layout) {
1862 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1871 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1872 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1873 /* This field is a hack inserted by MCS to empty structures */
1877 size = mono_type_size (field->type, &align);
1879 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1880 align = class->packing_size ? MIN (class->packing_size, align): align;
1881 /* if the field has managed references, we need to force-align it
1884 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1885 align = MAX (align, sizeof (gpointer));
1887 class->min_align = MAX (align, class->min_align);
1888 field->offset = real_size;
1890 field->offset += align - 1;
1891 field->offset &= ~(align - 1);
1893 /*TypeBuilders produce all sort of weird things*/
1894 g_assert (class->image->dynamic || field->offset > 0);
1895 real_size = field->offset + size;
1898 class->instance_size = MAX (real_size, class->instance_size);
1900 if (class->instance_size & (class->min_align - 1)) {
1901 class->instance_size += class->min_align - 1;
1902 class->instance_size &= ~(class->min_align - 1);
1906 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1908 for (i = 0; i < top; i++) {
1913 field = &class->fields [i];
1916 * There must be info about all the fields in a type if it
1917 * uses explicit layout.
1920 if (mono_field_is_deleted (field))
1922 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1925 size = mono_type_size (field->type, &align);
1926 align = class->packing_size ? MIN (class->packing_size, align): align;
1927 class->min_align = MAX (align, class->min_align);
1930 * When we get here, field->offset is already set by the
1931 * loader (for either runtime fields or fields loaded from metadata).
1932 * The offset is from the start of the object: this works for both
1933 * classes and valuetypes.
1935 field->offset += sizeof (MonoObject);
1936 ftype = mono_type_get_underlying_type (field->type);
1937 ftype = mono_type_get_basic_type_from_generic (ftype);
1938 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1939 if (field->offset % sizeof (gpointer)) {
1940 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1947 real_size = MAX (real_size, size + field->offset);
1949 class->instance_size = MAX (real_size, class->instance_size);
1950 if (class->instance_size & (class->min_align - 1)) {
1951 class->instance_size += class->min_align - 1;
1952 class->instance_size &= ~(class->min_align - 1);
1957 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1959 * For small structs, set min_align to at least the struct size to improve
1960 * performance, and since the JIT memset/memcpy code assumes this and generates
1961 * unaligned accesses otherwise. See #78990 for a testcase.
1963 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1964 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1967 mono_memory_barrier ();
1968 class->size_inited = 1;
1971 * Compute static field layout and size
1973 for (i = 0; i < top; i++){
1977 field = &class->fields [i];
1979 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1981 if (mono_field_is_deleted (field))
1984 if (mono_type_has_exceptions (field->type)) {
1985 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1989 size = mono_type_size (field->type, &align);
1990 field->offset = class->sizes.class_size;
1991 /*align is always non-zero here*/
1992 field->offset += align - 1;
1993 field->offset &= ~(align - 1);
1994 class->sizes.class_size = field->offset + size;
1999 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2003 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2004 method->klass = class;
2005 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2006 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2007 method->signature = sig;
2008 method->name = name;
2011 if (name [0] == '.') {
2012 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2014 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2020 * mono_class_setup_methods:
2023 * Initializes the 'methods' array in the klass.
2024 * Calling this method should be avoided if possible since it allocates a lot
2025 * of long-living MonoMethod structures.
2026 * Methods belonging to an interface are assigned a sequential slot starting
2029 * On failure this function sets class->exception_type
2032 mono_class_setup_methods (MonoClass *class)
2035 MonoMethod **methods;
2040 mono_loader_lock ();
2042 if (class->methods) {
2043 mono_loader_unlock ();
2047 if (class->generic_class) {
2049 MonoClass *gklass = class->generic_class->container_class;
2051 mono_class_init (gklass);
2052 if (!gklass->exception_type)
2053 mono_class_setup_methods (gklass);
2054 if (gklass->exception_type) {
2055 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2056 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2057 mono_loader_unlock ();
2061 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2062 class->method.count = gklass->method.count;
2063 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2065 for (i = 0; i < class->method.count; i++) {
2066 methods [i] = mono_class_inflate_generic_method_full_checked (
2067 gklass->methods [i], class, mono_class_get_context (class), &error);
2068 if (!mono_error_ok (&error)) {
2069 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2070 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)));
2073 mono_error_cleanup (&error);
2074 mono_loader_unlock ();
2078 } else if (class->rank) {
2080 MonoMethod *amethod;
2081 MonoMethodSignature *sig;
2082 int count_generic = 0, first_generic = 0;
2085 class->method.count = 3 + (class->rank > 1? 2: 1);
2087 mono_class_setup_interfaces (class, &error);
2088 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2090 if (class->interface_count) {
2091 count_generic = generic_array_methods (class);
2092 first_generic = class->method.count;
2093 class->method.count += class->interface_count * count_generic;
2096 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2098 sig = mono_metadata_signature_alloc (class->image, class->rank);
2099 sig->ret = &mono_defaults.void_class->byval_arg;
2100 sig->pinvoke = TRUE;
2101 sig->hasthis = TRUE;
2102 for (i = 0; i < class->rank; ++i)
2103 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2105 amethod = create_array_method (class, ".ctor", sig);
2106 methods [method_num++] = amethod;
2107 if (class->rank > 1) {
2108 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2109 sig->ret = &mono_defaults.void_class->byval_arg;
2110 sig->pinvoke = TRUE;
2111 sig->hasthis = TRUE;
2112 for (i = 0; i < class->rank * 2; ++i)
2113 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2115 amethod = create_array_method (class, ".ctor", sig);
2116 methods [method_num++] = amethod;
2118 /* element Get (idx11, [idx2, ...]) */
2119 sig = mono_metadata_signature_alloc (class->image, class->rank);
2120 sig->ret = &class->element_class->byval_arg;
2121 sig->pinvoke = TRUE;
2122 sig->hasthis = TRUE;
2123 for (i = 0; i < class->rank; ++i)
2124 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2125 amethod = create_array_method (class, "Get", sig);
2126 methods [method_num++] = amethod;
2127 /* element& Address (idx11, [idx2, ...]) */
2128 sig = mono_metadata_signature_alloc (class->image, class->rank);
2129 sig->ret = &class->element_class->this_arg;
2130 sig->pinvoke = TRUE;
2131 sig->hasthis = TRUE;
2132 for (i = 0; i < class->rank; ++i)
2133 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2134 amethod = create_array_method (class, "Address", sig);
2135 methods [method_num++] = amethod;
2136 /* void Set (idx11, [idx2, ...], element) */
2137 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2138 sig->ret = &mono_defaults.void_class->byval_arg;
2139 sig->pinvoke = TRUE;
2140 sig->hasthis = TRUE;
2141 for (i = 0; i < class->rank; ++i)
2142 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2143 sig->params [i] = &class->element_class->byval_arg;
2144 amethod = create_array_method (class, "Set", sig);
2145 methods [method_num++] = amethod;
2147 for (i = 0; i < class->interface_count; i++)
2148 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2150 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2151 for (i = 0; i < class->method.count; ++i) {
2152 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2153 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2157 if (MONO_CLASS_IS_INTERFACE (class)) {
2159 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2160 for (i = 0; i < class->method.count; ++i) {
2161 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2162 methods [i]->slot = slot++;
2166 /* Needed because of the double-checking locking pattern */
2167 mono_memory_barrier ();
2169 class->methods = methods;
2171 mono_loader_unlock ();
2175 * mono_class_get_method_by_index:
2177 * Returns class->methods [index], initializing class->methods if neccesary.
2179 * LOCKING: Acquires the loader lock.
2182 mono_class_get_method_by_index (MonoClass *class, int index)
2184 /* Avoid calling setup_methods () if possible */
2185 if (class->generic_class && !class->methods) {
2186 MonoClass *gklass = class->generic_class->container_class;
2189 m = mono_class_inflate_generic_method_full (
2190 gklass->methods [index], class, mono_class_get_context (class));
2192 * If setup_methods () is called later for this class, no duplicates are created,
2193 * since inflate_generic_method guarantees that only one instance of a method
2194 * is created for each context.
2197 mono_class_setup_methods (class);
2198 g_assert (m == class->methods [index]);
2202 mono_class_setup_methods (class);
2203 if (class->exception_type) /*FIXME do proper error handling*/
2205 g_assert (index >= 0 && index < class->method.count);
2206 return class->methods [index];
2211 * mono_class_get_inflated_method:
2213 * Given an inflated class CLASS and a method METHOD which should be a method of
2214 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2217 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2219 MonoClass *gklass = class->generic_class->container_class;
2222 g_assert (method->klass == gklass);
2224 mono_class_setup_methods (gklass);
2225 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2227 for (i = 0; i < gklass->method.count; ++i) {
2228 if (gklass->methods [i] == method) {
2230 return class->methods [i];
2232 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2240 * mono_class_get_vtable_entry:
2242 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2243 * LOCKING: Acquires the loader lock.
2246 mono_class_get_vtable_entry (MonoClass *class, int offset)
2250 if (class->rank == 1) {
2252 * szarrays do not overwrite any methods of Array, so we can avoid
2253 * initializing their vtables in some cases.
2255 mono_class_setup_vtable (class->parent);
2256 if (offset < class->parent->vtable_size)
2257 return class->parent->vtable [offset];
2260 if (class->generic_class) {
2261 MonoClass *gklass = class->generic_class->container_class;
2262 mono_class_setup_vtable (gklass);
2263 m = gklass->vtable [offset];
2265 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2267 mono_class_setup_vtable (class);
2268 if (class->exception_type)
2270 m = class->vtable [offset];
2277 * mono_class_get_vtable_size:
2279 * Return the vtable size for KLASS.
2282 mono_class_get_vtable_size (MonoClass *klass)
2284 mono_class_setup_vtable (klass);
2286 return klass->vtable_size;
2289 /*This method can fail the class.*/
2291 mono_class_setup_properties (MonoClass *class)
2293 guint startm, endm, i, j;
2294 guint32 cols [MONO_PROPERTY_SIZE];
2295 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2296 MonoProperty *properties;
2299 if (class->ext && class->ext->properties)
2302 mono_loader_lock ();
2304 if (class->ext && class->ext->properties) {
2305 mono_loader_unlock ();
2309 mono_class_alloc_ext (class);
2311 if (class->generic_class) {
2312 MonoClass *gklass = class->generic_class->container_class;
2314 mono_class_init (gklass);
2315 mono_class_setup_properties (gklass);
2316 if (gklass->exception_type) {
2317 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2318 mono_loader_unlock ();
2322 class->ext->property = gklass->ext->property;
2324 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2326 for (i = 0; i < class->ext->property.count; i++) {
2327 MonoProperty *prop = &properties [i];
2329 *prop = gklass->ext->properties [i];
2332 prop->get = mono_class_inflate_generic_method_full (
2333 prop->get, class, mono_class_get_context (class));
2335 prop->set = mono_class_inflate_generic_method_full (
2336 prop->set, class, mono_class_get_context (class));
2338 prop->parent = class;
2341 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2342 int count = last - first;
2345 mono_class_setup_methods (class);
2346 if (class->exception_type) {
2347 mono_loader_unlock ();
2352 class->ext->property.first = first;
2353 class->ext->property.count = count;
2354 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2355 for (i = first; i < last; ++i) {
2356 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2357 properties [i - first].parent = class;
2358 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2359 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2361 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2362 for (j = startm; j < endm; ++j) {
2365 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2367 if (class->image->uncompressed_metadata)
2368 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2369 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2371 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2373 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2374 case METHOD_SEMANTIC_SETTER:
2375 properties [i - first].set = method;
2377 case METHOD_SEMANTIC_GETTER:
2378 properties [i - first].get = method;
2386 /*Flush any pending writes as we do double checked locking on class->properties */
2387 mono_memory_barrier ();
2389 /* Leave this assignment as the last op in the function */
2390 class->ext->properties = properties;
2392 mono_loader_unlock ();
2396 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2398 MonoMethod **om, **retval;
2401 for (om = methods, count = 0; *om; ++om, ++count)
2404 retval = g_new0 (MonoMethod*, count + 1);
2406 for (om = methods, count = 0; *om; ++om, ++count)
2407 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2412 /*This method can fail the class.*/
2414 mono_class_setup_events (MonoClass *class)
2417 guint startm, endm, i, j;
2418 guint32 cols [MONO_EVENT_SIZE];
2419 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2423 if (class->ext && class->ext->events)
2426 mono_loader_lock ();
2428 if (class->ext && class->ext->events) {
2429 mono_loader_unlock ();
2433 mono_class_alloc_ext (class);
2435 if (class->generic_class) {
2436 MonoClass *gklass = class->generic_class->container_class;
2437 MonoGenericContext *context;
2439 mono_class_setup_events (gklass);
2440 if (gklass->exception_type) {
2441 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2442 mono_loader_unlock ();
2446 class->ext->event = gklass->ext->event;
2447 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2449 if (class->ext->event.count)
2450 context = mono_class_get_context (class);
2452 for (i = 0; i < class->ext->event.count; i++) {
2453 MonoEvent *event = &class->ext->events [i];
2454 MonoEvent *gevent = &gklass->ext->events [i];
2456 event->parent = class;
2457 event->name = gevent->name;
2458 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2459 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2460 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2461 #ifndef MONO_SMALL_CONFIG
2462 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2464 event->attrs = gevent->attrs;
2467 mono_loader_unlock ();
2471 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2472 count = last - first;
2475 mono_class_setup_methods (class);
2476 if (class->exception_type) {
2477 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2478 mono_loader_unlock ();
2482 class->ext->event.first = first;
2483 class->ext->event.count = count;
2484 events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2485 for (i = first; i < last; ++i) {
2486 MonoEvent *event = &events [i - first];
2488 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2489 event->parent = class;
2490 event->attrs = cols [MONO_EVENT_FLAGS];
2491 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2493 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2494 for (j = startm; j < endm; ++j) {
2497 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2499 if (class->image->uncompressed_metadata)
2500 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2501 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2503 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2505 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2506 case METHOD_SEMANTIC_ADD_ON:
2507 event->add = method;
2509 case METHOD_SEMANTIC_REMOVE_ON:
2510 event->remove = method;
2512 case METHOD_SEMANTIC_FIRE:
2513 event->raise = method;
2515 case METHOD_SEMANTIC_OTHER: {
2516 #ifndef MONO_SMALL_CONFIG
2519 if (event->other == NULL) {
2520 event->other = g_new0 (MonoMethod*, 2);
2522 while (event->other [n])
2524 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2526 event->other [n] = method;
2527 /* NULL terminated */
2528 event->other [n + 1] = NULL;
2537 /*Flush any pending writes as we do double checked locking on class->properties */
2538 mono_memory_barrier ();
2540 /* Leave this assignment as the last op in the function */
2541 class->ext->events = events;
2543 mono_loader_unlock ();
2547 * Global pool of interface IDs, represented as a bitset.
2548 * LOCKING: this is supposed to be accessed with the loader lock held.
2550 static MonoBitSet *global_interface_bitset = NULL;
2553 * mono_unload_interface_ids:
2554 * @bitset: bit set of interface IDs
2556 * When an image is unloaded, the interface IDs associated with
2557 * the image are put back in the global pool of IDs so the numbers
2561 mono_unload_interface_ids (MonoBitSet *bitset)
2563 mono_loader_lock ();
2564 mono_bitset_sub (global_interface_bitset, bitset);
2565 mono_loader_unlock ();
2569 mono_unload_interface_id (MonoClass *class)
2571 if (global_interface_bitset && class->interface_id) {
2572 mono_loader_lock ();
2573 mono_bitset_clear (global_interface_bitset, class->interface_id);
2574 mono_loader_unlock ();
2579 * mono_get_unique_iid:
2582 * Assign a unique integer ID to the interface represented by @class.
2583 * The ID will positive and as small as possible.
2584 * LOCKING: this is supposed to be called with the loader lock held.
2585 * Returns: the new ID.
2588 mono_get_unique_iid (MonoClass *class)
2592 g_assert (MONO_CLASS_IS_INTERFACE (class));
2594 if (!global_interface_bitset) {
2595 global_interface_bitset = mono_bitset_new (128, 0);
2598 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2600 int old_size = mono_bitset_size (global_interface_bitset);
2601 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2602 mono_bitset_free (global_interface_bitset);
2603 global_interface_bitset = new_set;
2606 mono_bitset_set (global_interface_bitset, iid);
2607 /* set the bit also in the per-image set */
2608 if (!class->generic_class) {
2609 if (class->image->interface_bitset) {
2610 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2611 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2612 mono_bitset_free (class->image->interface_bitset);
2613 class->image->interface_bitset = new_set;
2616 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2618 mono_bitset_set (class->image->interface_bitset, iid);
2621 #ifndef MONO_SMALL_CONFIG
2622 if (mono_print_vtable) {
2624 char *type_name = mono_type_full_name (&class->byval_arg);
2625 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2626 generic_id = class->generic_class->context.class_inst->id;
2627 g_assert (generic_id != 0);
2631 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2636 g_assert (iid <= 65535);
2641 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2646 mono_class_setup_interfaces (klass, error);
2647 if (!mono_error_ok (error))
2650 for (i = 0; i < klass->interface_count; i++) {
2651 ic = klass->interfaces [i];
2654 *res = g_ptr_array_new ();
2655 g_ptr_array_add (*res, ic);
2656 mono_class_init (ic);
2657 if (ic->exception_type) {
2658 mono_error_set_type_load_class (error, ic, "Error Loading class");
2662 collect_implemented_interfaces_aux (ic, res, error);
2663 if (!mono_error_ok (error))
2669 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2671 GPtrArray *res = NULL;
2673 collect_implemented_interfaces_aux (klass, &res, error);
2674 if (!mono_error_ok (error)) {
2676 g_ptr_array_free (res, TRUE);
2683 compare_interface_ids (const void *p_key, const void *p_element) {
2684 const MonoClass *key = p_key;
2685 const MonoClass *element = *(MonoClass**) p_element;
2687 return (key->interface_id - element->interface_id);
2690 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2692 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2693 MonoClass **result = mono_binary_search (
2695 klass->interfaces_packed,
2696 klass->interface_offsets_count,
2697 sizeof (MonoClass *),
2698 compare_interface_ids);
2700 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2707 * mono_class_interface_offset_with_variance:
2709 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2710 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2712 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2714 * FIXME figure out MS disambiguation rules and fix this function.
2717 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2718 int i = mono_class_interface_offset (klass, itf);
2719 *non_exact_match = FALSE;
2723 if (!mono_class_has_variant_generic_params (itf))
2726 for (i = 0; i < klass->interface_offsets_count; i++) {
2727 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2728 *non_exact_match = TRUE;
2729 return klass->interface_offsets_packed [i];
2737 print_implemented_interfaces (MonoClass *klass) {
2740 GPtrArray *ifaces = NULL;
2742 int ancestor_level = 0;
2744 name = mono_type_get_full_name (klass);
2745 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2748 for (i = 0; i < klass->interface_offsets_count; i++)
2749 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2750 klass->interfaces_packed [i]->interface_id,
2751 klass->interface_offsets_packed [i],
2752 klass->interfaces_packed [i]->method.count,
2753 klass->interfaces_packed [i]->name_space,
2754 klass->interfaces_packed [i]->name );
2755 printf ("Interface flags: ");
2756 for (i = 0; i <= klass->max_interface_id; i++)
2757 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2758 printf ("(%d,T)", i);
2760 printf ("(%d,F)", i);
2762 printf ("Dump interface flags:");
2763 #ifdef COMPRESSED_INTERFACE_BITMAP
2765 const uint8_t* p = klass->interface_bitmap;
2766 i = klass->max_interface_id;
2768 printf (" %d x 00 %02X", p [0], p [1]);
2774 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2775 printf (" %02X", klass->interface_bitmap [i]);
2778 while (klass != NULL) {
2779 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2780 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2781 if (!mono_error_ok (&error)) {
2782 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2783 mono_error_cleanup (&error);
2784 } else if (ifaces) {
2785 for (i = 0; i < ifaces->len; i++) {
2786 MonoClass *ic = g_ptr_array_index (ifaces, i);
2787 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2788 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2790 mono_class_interface_offset (klass, ic),
2795 g_ptr_array_free (ifaces, TRUE);
2798 klass = klass->parent;
2803 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2806 args [0] = &arg0->byval_arg;
2808 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2812 array_class_get_if_rank (MonoClass *class, guint rank)
2814 return rank ? mono_array_class_get (class, rank) : class;
2818 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2820 valuetype_types [0] = eclass;
2821 if (eclass == mono_defaults.int16_class)
2822 valuetype_types [1] = mono_defaults.uint16_class;
2823 else if (eclass == mono_defaults.uint16_class)
2824 valuetype_types [1] = mono_defaults.int16_class;
2825 else if (eclass == mono_defaults.int32_class)
2826 valuetype_types [1] = mono_defaults.uint32_class;
2827 else if (eclass == mono_defaults.uint32_class)
2828 valuetype_types [1] = mono_defaults.int32_class;
2829 else if (eclass == mono_defaults.int64_class)
2830 valuetype_types [1] = mono_defaults.uint64_class;
2831 else if (eclass == mono_defaults.uint64_class)
2832 valuetype_types [1] = mono_defaults.int64_class;
2833 else if (eclass == mono_defaults.byte_class)
2834 valuetype_types [1] = mono_defaults.sbyte_class;
2835 else if (eclass == mono_defaults.sbyte_class)
2836 valuetype_types [1] = mono_defaults.byte_class;
2837 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2838 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2841 /* this won't be needed once bug #325495 is completely fixed
2842 * though we'll need something similar to know which interfaces to allow
2843 * in arrays when they'll be lazyly created
2845 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2846 * MS returns diferrent types based on which instance is called. For example:
2847 * object obj = new byte[10][];
2848 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2849 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2852 * Fixing this should kill quite some code, save some bits and improve compatibility.
2855 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2857 MonoClass *eclass = class->element_class;
2858 static MonoClass* generic_icollection_class = NULL;
2859 static MonoClass* generic_ienumerable_class = NULL;
2860 static MonoClass* generic_ienumerator_class = NULL;
2861 static MonoClass* generic_ireadonlylist_class = NULL;
2862 static MonoClass* generic_ireadonlycollection_class = NULL;
2863 MonoClass *valuetype_types[2] = { NULL, NULL };
2864 MonoClass **interfaces = NULL;
2865 int i, nifaces, interface_count, real_count, original_rank;
2867 gboolean internal_enumerator;
2868 gboolean eclass_is_valuetype;
2870 if (!mono_defaults.generic_ilist_class) {
2874 internal_enumerator = FALSE;
2875 eclass_is_valuetype = FALSE;
2876 original_rank = eclass->rank;
2877 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2878 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2880 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2882 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2883 original_rank = eclass->rank;
2885 eclass = eclass->element_class;
2886 internal_enumerator = TRUE;
2887 *is_enumerator = TRUE;
2895 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2896 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2898 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2900 if (!generic_icollection_class) {
2901 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2902 "System.Collections.Generic", "ICollection`1");
2903 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2904 "System.Collections.Generic", "IEnumerable`1");
2905 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2906 "System.Collections.Generic", "IEnumerator`1");
2907 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2908 "System.Collections.Generic", "IReadOnlyList`1");
2909 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2910 "System.Collections.Generic", "IReadOnlyCollection`1");
2913 mono_class_init (eclass);
2916 * Arrays in 2.0 need to implement a number of generic interfaces
2917 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2918 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2919 * We collect the types needed to build the
2920 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2921 * the generic interfaces needed to implement.
2923 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2924 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2926 if (eclass->valuetype) {
2927 nifaces = generic_ireadonlylist_class ? 5 : 3;
2928 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2930 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2931 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2932 if (internal_enumerator) {
2934 if (valuetype_types [1])
2938 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2939 interfaces [0] = valuetype_types [0];
2940 if (valuetype_types [1])
2941 interfaces [nifaces] = valuetype_types [1];
2943 eclass_is_valuetype = TRUE;
2946 int idepth = eclass->idepth;
2947 if (!internal_enumerator)
2949 nifaces = generic_ireadonlylist_class ? 2 : 3;
2951 // FIXME: This doesn't seem to work/required for generic params
2952 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
2953 mono_class_setup_interface_offsets (eclass);
2955 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2956 /* we add object for interfaces and the supertypes for the other
2957 * types. The last of the supertypes is the element class itself which we
2958 * already created the explicit interfaces for (so we include it for IEnumerator
2959 * and exclude it for arrays).
2961 if (MONO_CLASS_IS_INTERFACE (eclass))
2964 interface_count += idepth;
2965 if (eclass->rank && eclass->element_class->valuetype) {
2966 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2967 if (valuetype_types [1])
2970 /* IList, ICollection, IEnumerable, IReadOnlyList */
2971 interface_count *= nifaces;
2972 real_count = interface_count;
2973 if (internal_enumerator) {
2974 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2975 if (valuetype_types [1])
2978 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2979 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2980 interfaces [0] = mono_defaults.object_class;
2984 for (i = 0; i < idepth; i++) {
2985 mono_class_init (eclass->supertypes [i]);
2986 interfaces [j] = eclass->supertypes [i];
2990 if (all_interfaces) {
2991 for (i = 0; i < eclass->interface_offsets_count; i++) {
2992 interfaces [j] = eclass->interfaces_packed [i];
2996 for (i = 0; i < eclass->interface_count; i++) {
2997 interfaces [j] = eclass->interfaces [i];
3001 if (valuetype_types [1]) {
3002 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3007 /* instantiate the generic interfaces */
3008 for (i = 0; i < interface_count; i += nifaces) {
3009 MonoClass *iface = interfaces [i];
3011 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3012 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3014 if (eclass->valuetype) {
3015 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3016 if (generic_ireadonlylist_class) {
3017 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3018 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3021 if (!generic_ireadonlylist_class)
3022 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3025 if (internal_enumerator) {
3027 /* instantiate IEnumerator<iface> */
3028 for (i = 0; i < interface_count; i++) {
3029 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3031 j = interface_count;
3032 if (!eclass_is_valuetype) {
3033 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3034 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3037 for (i = 0; i < eclass->idepth; i++) {
3038 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3042 for (i = 0; i < eclass->interface_offsets_count; i++) {
3043 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3047 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3049 if (valuetype_types [1])
3050 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3054 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3055 for (i = 0; i < real_count; ++i) {
3056 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3057 g_print ("%s implements %s\n", type_name, name);
3068 find_array_interface (MonoClass *klass, const char *name)
3071 for (i = 0; i < klass->interface_count; ++i) {
3072 if (strcmp (klass->interfaces [i]->name, name) == 0)
3079 * Return the number of virtual methods.
3080 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3081 * Return -1 on failure.
3082 * FIXME It would be nice if this information could be cached somewhere.
3085 count_virtual_methods (MonoClass *class)
3089 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3091 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3092 mono_class_setup_methods (class);
3093 if (class->exception_type)
3096 for (i = 0; i < class->method.count; ++i) {
3097 flags = class->methods [i]->flags;
3098 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3102 for (i = 0; i < class->method.count; ++i) {
3103 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3105 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3113 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3121 m = (l + num_ifaces) / 2;
3122 if (interfaces_full [m] == ic)
3124 if (l == num_ifaces)
3126 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3135 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3137 int i = find_interface (num_ifaces, interfaces_full, ic);
3139 return interface_offsets_full [i];
3144 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3146 int i = find_interface (num_ifaces, interfaces_full, ic);
3150 interface_offsets_full [i] = offset;
3153 for (i = 0; i < num_ifaces; ++i) {
3154 if (interfaces_full [i]) {
3156 if (interfaces_full [i]->interface_id < ic->interface_id)
3159 while (end < num_ifaces && interfaces_full [end]) end++;
3160 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3161 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3163 interfaces_full [i] = ic;
3164 interface_offsets_full [i] = offset;
3170 #ifdef COMPRESSED_INTERFACE_BITMAP
3173 * Compressed interface bitmap design.
3175 * Interface bitmaps take a large amount of memory, because their size is
3176 * linear with the maximum interface id assigned in the process (each interface
3177 * is assigned a unique id as it is loaded). The number of interface classes
3178 * is high because of the many implicit interfaces implemented by arrays (we'll
3179 * need to lazy-load them in the future).
3180 * Most classes implement a very small number of interfaces, so the bitmap is
3181 * sparse. This bitmap needs to be checked by interface casts, so access to the
3182 * needed bit must be fast and doable with few jit instructions.
3184 * The current compression format is as follows:
3185 * *) it is a sequence of one or more two-byte elements
3186 * *) the first byte in the element is the count of empty bitmap bytes
3187 * at the current bitmap position
3188 * *) the second byte in the element is an actual bitmap byte at the current
3191 * As an example, the following compressed bitmap bytes:
3192 * 0x07 0x01 0x00 0x7
3193 * correspond to the following bitmap:
3194 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3196 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3197 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3198 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3202 * mono_compress_bitmap:
3203 * @dest: destination buffer
3204 * @bitmap: bitmap buffer
3205 * @size: size of @bitmap in bytes
3207 * This is a mono internal function.
3208 * The @bitmap data is compressed into a format that is small but
3209 * still searchable in few instructions by the JIT and runtime.
3210 * The compressed data is stored in the buffer pointed to by the
3211 * @dest array. Passing a #NULL value for @dest allows to just compute
3212 * the size of the buffer.
3213 * This compression algorithm assumes the bits set in the bitmap are
3214 * few and far between, like in interface bitmaps.
3215 * Returns: the size of the compressed bitmap in bytes.
3218 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3222 const uint8_t *end = bitmap + size;
3223 while (bitmap < end) {
3224 if (*bitmap || numz == 255) {
3248 * mono_class_interface_match:
3249 * @bitmap: a compressed bitmap buffer
3250 * @id: the index to check in the bitmap
3252 * This is a mono internal function.
3253 * Checks if a bit is set in a compressed interface bitmap. @id must
3254 * be already checked for being smaller than the maximum id encoded in the
3257 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3261 mono_class_interface_match (const uint8_t *bitmap, int id)
3264 id -= bitmap [0] * 8;
3268 return bitmap [1] & (1 << id);
3277 * LOCKING: this is supposed to be called with the loader lock held.
3278 * Return -1 on failure and set exception_type
3281 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3285 int i, j, max_iid, num_ifaces;
3286 MonoClass **interfaces_full = NULL;
3287 int *interface_offsets_full = NULL;
3289 GPtrArray **ifaces_array = NULL;
3290 int interface_offsets_count;
3291 MonoClass **array_interfaces = NULL;
3292 int num_array_interfaces;
3293 int is_enumerator = FALSE;
3295 mono_class_setup_supertypes (class);
3297 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3298 * implicit interfaces have the property that they are assigned the same slot in the
3299 * vtables for compatible interfaces
3301 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3303 /* compute maximum number of slots and maximum interface id */
3305 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3306 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3307 for (j = 0; j < class->idepth; j++) {
3308 k = class->supertypes [j];
3309 num_ifaces += k->interface_count;
3310 for (i = 0; i < k->interface_count; i++) {
3311 ic = k->interfaces [i];
3314 mono_class_init (ic);
3316 if (max_iid < ic->interface_id)
3317 max_iid = ic->interface_id;
3319 ifaces = mono_class_get_implemented_interfaces (k, &error);
3320 if (!mono_error_ok (&error)) {
3321 char *name = mono_type_get_full_name (k);
3322 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)));
3324 mono_error_cleanup (&error);
3329 num_ifaces += ifaces->len;
3330 for (i = 0; i < ifaces->len; ++i) {
3331 ic = g_ptr_array_index (ifaces, i);
3332 if (max_iid < ic->interface_id)
3333 max_iid = ic->interface_id;
3335 ifaces_array [j] = ifaces;
3339 for (i = 0; i < num_array_interfaces; ++i) {
3340 ic = array_interfaces [i];
3341 mono_class_init (ic);
3342 if (max_iid < ic->interface_id)
3343 max_iid = ic->interface_id;
3346 if (MONO_CLASS_IS_INTERFACE (class)) {
3348 if (max_iid < class->interface_id)
3349 max_iid = class->interface_id;
3351 class->max_interface_id = max_iid;
3352 /* compute vtable offset for interfaces */
3353 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3354 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3356 for (i = 0; i < num_ifaces; i++) {
3357 interface_offsets_full [i] = -1;
3360 /* skip the current class */
3361 for (j = 0; j < class->idepth - 1; j++) {
3362 k = class->supertypes [j];
3363 ifaces = ifaces_array [j];
3366 for (i = 0; i < ifaces->len; ++i) {
3368 ic = g_ptr_array_index (ifaces, i);
3370 /*Force the sharing of interface offsets between parent and subtypes.*/
3371 io = mono_class_interface_offset (k, ic);
3373 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3378 g_assert (class == class->supertypes [class->idepth - 1]);
3379 ifaces = ifaces_array [class->idepth - 1];
3381 for (i = 0; i < ifaces->len; ++i) {
3383 ic = g_ptr_array_index (ifaces, i);
3384 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3386 count = count_virtual_methods (ic);
3388 char *name = mono_type_get_full_name (ic);
3389 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3398 if (MONO_CLASS_IS_INTERFACE (class))
3399 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3401 if (num_array_interfaces) {
3402 if (is_enumerator) {
3403 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3404 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3405 g_assert (ienumerator_offset >= 0);
3406 for (i = 0; i < num_array_interfaces; ++i) {
3407 ic = array_interfaces [i];
3408 if (strcmp (ic->name, "IEnumerator`1") == 0)
3409 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3411 g_assert_not_reached ();
3412 /*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);*/
3415 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3416 int ilist_iface_idx = find_array_interface (class, "IList`1");
3417 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3418 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3419 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3420 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3421 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3422 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3423 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3424 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3425 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3426 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3427 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3428 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3429 for (i = 0; i < num_array_interfaces; ++i) {
3431 ic = array_interfaces [i];
3432 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3433 offset = ilist_offset;
3434 else if (strcmp (ic->name, "ICollection`1") == 0)
3435 offset = icollection_offset;
3436 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3437 offset = ienumerable_offset;
3438 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3439 offset = ireadonlylist_offset;
3440 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3441 offset = ireadonlycollection_offset;
3443 g_assert_not_reached ();
3444 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3445 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3450 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3451 if (interface_offsets_full [i] != -1) {
3452 interface_offsets_count ++;
3457 * We might get called multiple times:
3458 * - mono_class_init ()
3459 * - mono_class_setup_vtable ().
3460 * - mono_class_setup_interface_offsets ().
3461 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3462 * means we have to overwrite those when called from other places (#4440).
3464 if (class->interfaces_packed && !overwrite) {
3465 g_assert (class->interface_offsets_count == interface_offsets_count);
3469 class->interface_offsets_count = interface_offsets_count;
3470 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3471 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3472 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3473 #ifdef COMPRESSED_INTERFACE_BITMAP
3474 bitmap = g_malloc0 (bsize);
3476 bitmap = mono_class_alloc0 (class, bsize);
3478 for (i = 0; i < interface_offsets_count; i++) {
3479 int id = interfaces_full [i]->interface_id;
3480 bitmap [id >> 3] |= (1 << (id & 7));
3481 class->interfaces_packed [i] = interfaces_full [i];
3482 class->interface_offsets_packed [i] = interface_offsets_full [i];
3483 /*if (num_array_interfaces)
3484 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]);*/
3486 #ifdef COMPRESSED_INTERFACE_BITMAP
3487 i = mono_compress_bitmap (NULL, bitmap, bsize);
3488 class->interface_bitmap = mono_class_alloc0 (class, i);
3489 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3492 class->interface_bitmap = bitmap;
3497 g_free (interfaces_full);
3498 g_free (interface_offsets_full);
3499 g_free (array_interfaces);
3500 for (i = 0; i < class->idepth; i++) {
3501 ifaces = ifaces_array [i];
3503 g_ptr_array_free (ifaces, TRUE);
3505 g_free (ifaces_array);
3507 //printf ("JUST DONE: ");
3508 //print_implemented_interfaces (class);
3514 * Setup interface offsets for interfaces.
3516 * - class->max_interface_id
3517 * - class->interface_offsets_count
3518 * - class->interfaces_packed
3519 * - class->interface_offsets_packed
3520 * - class->interface_bitmap
3522 * This function can fail @class.
3525 mono_class_setup_interface_offsets (MonoClass *class)
3527 mono_loader_lock ();
3529 setup_interface_offsets (class, 0, FALSE);
3531 mono_loader_unlock ();
3534 /*Checks if @klass has @parent as one of it's parents type gtd
3538 * Bar<T> : Foo<Bar<Bar<T>>>
3542 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3544 klass = mono_class_get_generic_type_definition (klass);
3545 parent = mono_class_get_generic_type_definition (parent);
3546 mono_class_setup_supertypes (klass);
3547 mono_class_setup_supertypes (parent);
3549 return klass->idepth >= parent->idepth &&
3550 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3554 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3556 MonoGenericInst *ginst;
3558 if (!class->generic_class) {
3559 mono_class_setup_vtable_full (class, in_setup);
3560 return class->exception_type == 0;
3563 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3564 if (class->generic_class->container_class->exception_type) {
3565 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3569 ginst = class->generic_class->context.class_inst;
3570 for (i = 0; i < ginst->type_argc; ++i) {
3572 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3574 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3575 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3576 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3578 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3579 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3587 * mono_class_setup_vtable:
3589 * Creates the generic vtable of CLASS.
3590 * Initializes the following fields in MonoClass:
3593 * Plus all the fields initialized by setup_interface_offsets ().
3594 * If there is an error during vtable construction, class->exception_type is set.
3596 * LOCKING: Acquires the loader lock.
3599 mono_class_setup_vtable (MonoClass *class)
3601 mono_class_setup_vtable_full (class, NULL);
3605 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3607 MonoMethod **overrides;
3608 MonoGenericContext *context;
3616 if (MONO_CLASS_IS_INTERFACE (class)) {
3617 /* This sets method->slot for all methods if this is an interface */
3618 mono_class_setup_methods (class);
3622 if (class->exception_type)
3625 if (g_list_find (in_setup, class))
3628 mono_loader_lock ();
3630 if (class->vtable) {
3631 mono_loader_unlock ();
3635 mono_stats.generic_vtable_count ++;
3636 in_setup = g_list_prepend (in_setup, class);
3638 if (class->generic_class) {
3639 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3640 mono_loader_unlock ();
3641 g_list_remove (in_setup, class);
3645 context = mono_class_get_context (class);
3646 type_token = class->generic_class->container_class->type_token;
3648 context = (MonoGenericContext *) class->generic_container;
3649 type_token = class->type_token;
3652 if (class->image->dynamic) {
3653 /* Generic instances can have zero method overrides without causing any harm.
3654 * This is true since we don't do layout all over again for them, we simply inflate
3655 * the layout of the parent.
3657 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3659 /* The following call fails if there are missing methods in the type */
3660 /* FIXME it's probably a good idea to avoid this for generic instances. */
3661 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3665 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3667 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3671 mono_loader_unlock ();
3672 g_list_remove (in_setup, class);
3677 #define DEBUG_INTERFACE_VTABLE_CODE 0
3678 #define TRACE_INTERFACE_VTABLE_CODE 0
3679 #define VERIFY_INTERFACE_VTABLE_CODE 0
3680 #define VTABLE_SELECTOR (1)
3682 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3683 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3684 if (!(VTABLE_SELECTOR)) break; \
3688 #define DEBUG_INTERFACE_VTABLE(stmt)
3691 #if TRACE_INTERFACE_VTABLE_CODE
3692 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3693 if (!(VTABLE_SELECTOR)) break; \
3697 #define TRACE_INTERFACE_VTABLE(stmt)
3700 #if VERIFY_INTERFACE_VTABLE_CODE
3701 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3702 if (!(VTABLE_SELECTOR)) break; \
3706 #define VERIFY_INTERFACE_VTABLE(stmt)
3710 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3712 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3716 GString *res = g_string_new ("");
3718 g_string_append_c (res, '(');
3719 for (i = 0; i < sig->param_count; ++i) {
3721 g_string_append_c (res, ',');
3722 mono_type_get_desc (res, sig->params [i], include_namespace);
3724 g_string_append (res, ")=>");
3725 if (sig->ret != NULL) {
3726 mono_type_get_desc (res, sig->ret, include_namespace);
3728 g_string_append (res, "NULL");
3731 g_string_free (res, FALSE);
3735 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3736 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3737 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3738 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3746 is_wcf_hack_disabled (void)
3748 static gboolean disabled;
3749 static gboolean inited = FALSE;
3751 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3758 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) {
3759 MonoMethodSignature *cmsig, *imsig;
3760 if (strcmp (im->name, cm->name) == 0) {
3761 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3762 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3765 if (! slot_is_empty) {
3766 if (require_newslot) {
3767 if (! interface_is_explicitly_implemented_by_class) {
3768 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3771 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3772 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3776 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3779 cmsig = mono_method_signature (cm);
3780 imsig = mono_method_signature (im);
3781 if (!cmsig || !imsig) {
3782 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3786 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3787 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3788 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3789 TRACE_INTERFACE_VTABLE (printf ("]"));
3792 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3793 /* CAS - SecurityAction.InheritanceDemand on interface */
3794 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3795 mono_secman_inheritancedemand_method (cm, im);
3798 if (mono_security_core_clr_enabled ())
3799 mono_security_core_clr_check_override (class, cm, im);
3801 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3802 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3803 char *body_name = mono_method_full_name (cm, TRUE);
3804 char *decl_name = mono_method_full_name (im, TRUE);
3805 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));
3813 MonoClass *ic = im->klass;
3814 const char *ic_name_space = ic->name_space;
3815 const char *ic_name = ic->name;
3818 if (! require_newslot) {
3819 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3822 if (cm->klass->rank == 0) {
3823 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3826 cmsig = mono_method_signature (cm);
3827 imsig = mono_method_signature (im);
3828 if (!cmsig || !imsig) {
3829 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3833 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3834 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3835 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3836 TRACE_INTERFACE_VTABLE (printf ("]"));
3839 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3840 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3843 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3844 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3847 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))) {
3848 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3852 subname = strstr (cm->name, ic_name_space);
3853 if (subname != cm->name) {
3854 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3857 subname += strlen (ic_name_space);
3858 if (subname [0] != '.') {
3859 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3863 if (strstr (subname, ic_name) != subname) {
3864 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3867 subname += strlen (ic_name);
3868 if (subname [0] != '.') {
3869 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3873 if (strcmp (subname, im->name) != 0) {
3874 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3878 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3879 /* CAS - SecurityAction.InheritanceDemand on interface */
3880 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3881 mono_secman_inheritancedemand_method (cm, im);
3884 if (mono_security_core_clr_enabled ())
3885 mono_security_core_clr_check_override (class, cm, im);
3887 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3888 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3889 char *body_name = mono_method_full_name (cm, TRUE);
3890 char *decl_name = mono_method_full_name (im, TRUE);
3891 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
3901 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3903 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3904 MonoMethod *method = key;
3905 MonoMethod *override = value;
3906 MonoClass *method_class = mono_method_get_class (method);
3907 MonoClass *override_class = mono_method_get_class (override);
3909 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3910 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3911 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3914 print_overrides (GHashTable *override_map, const char *message) {
3916 printf ("Override map \"%s\" START:\n", message);
3917 g_hash_table_foreach (override_map, foreach_override, NULL);
3918 printf ("Override map \"%s\" END.\n", message);
3920 printf ("Override map \"%s\" EMPTY.\n", message);
3924 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3925 char *full_name = mono_type_full_name (&class->byval_arg);
3929 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3931 if (print_interfaces) {
3932 print_implemented_interfaces (class);
3933 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3936 if (class->parent) {
3937 parent_size = class->parent->vtable_size;
3941 for (i = 0; i < size; ++i) {
3942 MonoMethod *cm = vtable [i];
3943 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3944 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3946 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3954 #if VERIFY_INTERFACE_VTABLE_CODE
3956 mono_method_try_get_vtable_index (MonoMethod *method)
3958 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3959 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3960 if (imethod->declaring->is_generic)
3961 return imethod->declaring->slot;
3963 return method->slot;
3967 mono_class_verify_vtable (MonoClass *class)
3970 char *full_name = mono_type_full_name (&class->byval_arg);
3972 printf ("*** Verifying VTable of class '%s' \n", full_name);
3976 if (!class->methods)
3979 for (i = 0; i < class->method.count; ++i) {
3980 MonoMethod *cm = class->methods [i];
3983 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3987 full_name = mono_method_full_name (cm, TRUE);
3989 slot = mono_method_try_get_vtable_index (cm);
3991 if (slot >= class->vtable_size) {
3992 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
3996 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
3997 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
3998 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3999 g_free (other_name);
4002 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4009 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4011 char *method_signature;
4014 for (index = 0; index < onum; ++index) {
4015 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4016 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4018 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4019 type_name = mono_type_full_name (&class->byval_arg);
4020 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4021 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4022 g_free (method_signature);
4024 mono_class_setup_methods (class);
4025 if (class->exception_type) {
4026 char *name = mono_type_get_full_name (class);
4027 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4031 for (index = 0; index < class->method.count; ++index) {
4032 MonoMethod *cm = class->methods [index];
4033 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4035 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4036 g_free (method_signature);
4041 mono_method_get_method_definition (MonoMethod *method)
4043 while (method->is_inflated)
4044 method = ((MonoMethodInflated*)method)->declaring;
4049 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4053 for (i = 0; i < onum; ++i) {
4054 MonoMethod *decl = overrides [i * 2];
4055 MonoMethod *body = overrides [i * 2 + 1];
4057 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4058 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4062 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4063 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4064 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4066 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4070 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4071 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4072 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4074 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4078 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4079 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4083 body = mono_method_get_method_definition (body);
4084 decl = mono_method_get_method_definition (decl);
4086 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4087 char *body_name = mono_method_full_name (body, TRUE);
4088 char *decl_name = mono_method_full_name (decl, TRUE);
4089 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));
4099 mono_class_need_stelemref_method (MonoClass *class)
4101 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4105 * LOCKING: this is supposed to be called with the loader lock held.
4108 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4112 MonoMethod **vtable;
4113 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4114 GPtrArray *ifaces = NULL;
4115 GHashTable *override_map = NULL;
4116 gboolean security_enabled = mono_security_enabled ();
4118 gpointer class_iter;
4119 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4120 int first_non_interface_slot;
4122 GSList *virt_methods = NULL, *l;
4123 int stelemref_slot = 0;
4128 if (overrides && !verify_class_overrides (class, overrides, onum))
4131 ifaces = mono_class_get_implemented_interfaces (class, &error);
4132 if (!mono_error_ok (&error)) {
4133 char *name = mono_type_get_full_name (class);
4134 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)));
4136 mono_error_cleanup (&error);
4138 } else if (ifaces) {
4139 for (i = 0; i < ifaces->len; i++) {
4140 MonoClass *ic = g_ptr_array_index (ifaces, i);
4141 max_vtsize += ic->method.count;
4143 g_ptr_array_free (ifaces, TRUE);
4147 if (class->parent) {
4148 mono_class_init (class->parent);
4149 mono_class_setup_vtable_full (class->parent, in_setup);
4151 if (class->parent->exception_type) {
4152 char *name = mono_type_get_full_name (class->parent);
4153 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4158 max_vtsize += class->parent->vtable_size;
4159 cur_slot = class->parent->vtable_size;
4162 max_vtsize += class->method.count;
4164 /*Array have a slot for stelemref*/
4165 if (mono_class_need_stelemref_method (class)) {
4166 stelemref_slot = cur_slot;
4171 vtable = alloca (sizeof (gpointer) * max_vtsize);
4172 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4174 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4176 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4177 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4180 max_iid = class->max_interface_id;
4181 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4183 /* Optimized version for generic instances */
4184 if (class->generic_class) {
4186 MonoClass *gklass = class->generic_class->container_class;
4189 mono_class_setup_vtable_full (gklass, in_setup);
4190 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4191 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4195 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4196 class->vtable_size = gklass->vtable_size;
4197 for (i = 0; i < gklass->vtable_size; ++i)
4198 if (gklass->vtable [i]) {
4199 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4200 if (!mono_error_ok (&error)) {
4201 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4202 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4204 mono_error_cleanup (&error);
4208 tmp [i]->slot = gklass->vtable [i]->slot;
4210 mono_memory_barrier ();
4211 class->vtable = tmp;
4213 /* Have to set method->slot for abstract virtual methods */
4214 if (class->methods && gklass->methods) {
4215 for (i = 0; i < class->method.count; ++i)
4216 if (class->methods [i]->slot == -1)
4217 class->methods [i]->slot = gklass->methods [i]->slot;
4223 if (class->parent && class->parent->vtable_size) {
4224 MonoClass *parent = class->parent;
4227 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4229 // Also inherit parent interface vtables, just as a starting point.
4230 // This is needed otherwise bug-77127.exe fails when the property methods
4231 // have different names in the iterface and the class, because for child
4232 // classes the ".override" information is not used anymore.
4233 for (i = 0; i < parent->interface_offsets_count; i++) {
4234 MonoClass *parent_interface = parent->interfaces_packed [i];
4235 int interface_offset = mono_class_interface_offset (class, parent_interface);
4236 /*FIXME this is now dead code as this condition will never hold true.
4237 Since interface offsets are inherited then the offset of an interface implemented
4238 by a parent will never be the out of it's vtable boundary.
4240 if (interface_offset >= parent->vtable_size) {
4241 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4244 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4245 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4246 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4247 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4248 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4249 parent_interface_offset + j, parent_interface_offset, j,
4250 interface_offset + j, interface_offset, j));
4257 /*Array have a slot for stelemref*/
4258 if (mono_class_need_stelemref_method (class)) {
4259 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4261 method->slot = stelemref_slot;
4263 g_assert (method->slot == stelemref_slot);
4265 vtable [stelemref_slot] = method;
4268 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4269 /* override interface methods */
4270 for (i = 0; i < onum; i++) {
4271 MonoMethod *decl = overrides [i*2];
4272 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4274 dslot = mono_method_get_vtable_slot (decl);
4276 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4280 dslot += mono_class_interface_offset (class, decl->klass);
4281 vtable [dslot] = overrides [i*2 + 1];
4282 vtable [dslot]->slot = dslot;
4284 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4286 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4288 if (mono_security_core_clr_enabled ())
4289 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4292 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4293 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4296 * Create a list of virtual methods to avoid calling
4297 * mono_class_get_virtual_methods () which is slow because of the metadata
4301 gpointer iter = NULL;
4304 virt_methods = NULL;
4305 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4306 virt_methods = g_slist_prepend (virt_methods, cm);
4308 if (class->exception_type)
4312 // Loop on all implemented interfaces...
4313 for (i = 0; i < class->interface_offsets_count; i++) {
4314 MonoClass *parent = class->parent;
4316 gboolean interface_is_explicitly_implemented_by_class;
4319 ic = class->interfaces_packed [i];
4320 ic_offset = mono_class_interface_offset (class, ic);
4322 mono_class_setup_methods (ic);
4323 if (ic->exception_type)
4326 // Check if this interface is explicitly implemented (instead of just inherited)
4327 if (parent != NULL) {
4328 int implemented_interfaces_index;
4329 interface_is_explicitly_implemented_by_class = FALSE;
4330 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4331 if (ic == class->interfaces [implemented_interfaces_index]) {
4332 interface_is_explicitly_implemented_by_class = TRUE;
4337 interface_is_explicitly_implemented_by_class = TRUE;
4340 // Loop on all interface methods...
4341 for (im_index = 0; im_index < ic->method.count; im_index++) {
4342 MonoMethod *im = ic->methods [im_index];
4343 int im_slot = ic_offset + im->slot;
4344 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4346 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4349 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4351 // If there is an explicit implementation, just use it right away,
4352 // otherwise look for a matching method
4353 if (override_im == NULL) {
4358 // First look for a suitable method among the class methods
4360 for (l = virt_methods; l; l = l->next) {
4362 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)));
4363 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4364 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4365 vtable [im_slot] = cm;
4366 /* Why do we need this? */
4371 TRACE_INTERFACE_VTABLE (printf ("\n"));
4372 if (class->exception_type) /*Might be set by check_interface_method_override*/
4376 // If the slot is still empty, look in all the inherited virtual methods...
4377 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4378 MonoClass *parent = class->parent;
4379 // Reverse order, so that last added methods are preferred
4380 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4381 MonoMethod *cm = parent->vtable [cm_index];
4383 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));
4384 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4385 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4386 vtable [im_slot] = cm;
4387 /* Why do we need this? */
4393 if (class->exception_type) /*Might be set by check_interface_method_override*/
4395 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4399 g_assert (vtable [im_slot] == override_im);
4404 // If the class is not abstract, check that all its interface slots are full.
4405 // The check is done here and not directly at the end of the loop above because
4406 // it can happen (for injected generic array interfaces) that the same slot is
4407 // processed multiple times (those interfaces have overlapping slots), and it
4408 // will not always be the first pass the one that fills the slot.
4409 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4410 for (i = 0; i < class->interface_offsets_count; i++) {
4414 ic = class->interfaces_packed [i];
4415 ic_offset = mono_class_interface_offset (class, ic);
4417 for (im_index = 0; im_index < ic->method.count; im_index++) {
4418 MonoMethod *im = ic->methods [im_index];
4419 int im_slot = ic_offset + im->slot;
4421 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4424 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4425 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4426 if (vtable [im_slot] == NULL) {
4427 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4434 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4436 for (l = virt_methods; l; l = l->next) {
4439 * If the method is REUSE_SLOT, we must check in the
4440 * base class for a method to override.
4442 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4444 for (k = class->parent; k ; k = k->parent) {
4449 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4450 MonoMethodSignature *cmsig, *m1sig;
4452 cmsig = mono_method_signature (cm);
4453 m1sig = mono_method_signature (m1);
4455 if (!cmsig || !m1sig) {
4456 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4460 if (!strcmp(cm->name, m1->name) &&
4461 mono_metadata_signature_equal (cmsig, m1sig)) {
4463 /* CAS - SecurityAction.InheritanceDemand */
4464 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4465 mono_secman_inheritancedemand_method (cm, m1);
4468 if (mono_security_core_clr_enabled ())
4469 mono_security_core_clr_check_override (class, cm, m1);
4471 slot = mono_method_get_vtable_slot (m1);
4475 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4476 char *body_name = mono_method_full_name (cm, TRUE);
4477 char *decl_name = mono_method_full_name (m1, TRUE);
4478 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));
4484 g_assert (cm->slot < max_vtsize);
4486 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4487 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4488 mono_method_full_name (m1, 1), m1,
4489 mono_method_full_name (cm, 1), cm));
4490 g_hash_table_insert (override_map, m1, cm);
4494 if (k->exception_type)
4504 /*Non final newslot methods must be given a non-interface vtable slot*/
4505 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4509 cm->slot = cur_slot++;
4511 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4512 vtable [cm->slot] = cm;
4515 /* override non interface methods */
4516 for (i = 0; i < onum; i++) {
4517 MonoMethod *decl = overrides [i*2];
4518 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4519 g_assert (decl->slot != -1);
4520 vtable [decl->slot] = overrides [i*2 + 1];
4521 overrides [i * 2 + 1]->slot = decl->slot;
4523 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4524 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4525 mono_method_full_name (decl, 1), decl,
4526 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4527 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4529 if (mono_security_core_clr_enabled ())
4530 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4535 * If a method occupies more than one place in the vtable, and it is
4536 * overriden, then change the other occurances too.
4541 for (i = 0; i < max_vtsize; ++i)
4543 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4545 cm = g_hash_table_lookup (override_map, vtable [i]);
4550 g_hash_table_destroy (override_map);
4551 override_map = NULL;
4554 g_slist_free (virt_methods);
4555 virt_methods = NULL;
4557 /* Ensure that all vtable slots are filled with concrete instance methods */
4558 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4559 for (i = 0; i < cur_slot; ++i) {
4560 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4561 char *type_name = mono_type_get_full_name (class);
4562 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4563 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));
4565 g_free (method_name);
4571 if (class->generic_class) {
4572 MonoClass *gklass = class->generic_class->container_class;
4574 mono_class_init (gklass);
4576 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4578 /* Check that the vtable_size value computed in mono_class_init () is correct */
4579 if (class->vtable_size)
4580 g_assert (cur_slot == class->vtable_size);
4581 class->vtable_size = cur_slot;
4584 /* Try to share the vtable with our parent. */
4585 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4586 mono_memory_barrier ();
4587 class->vtable = class->parent->vtable;
4589 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4590 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4591 mono_memory_barrier ();
4592 class->vtable = tmp;
4595 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4596 if (mono_print_vtable) {
4599 print_implemented_interfaces (class);
4601 for (i = 0; i <= max_iid; i++)
4602 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4605 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4606 class->vtable_size, icount);
4608 for (i = 0; i < cur_slot; ++i) {
4613 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4614 mono_method_full_name (cm, TRUE));
4620 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4621 class->name, max_iid);
4623 for (i = 0; i < class->interface_count; i++) {
4624 ic = class->interfaces [i];
4625 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4626 mono_class_interface_offset (class, ic),
4627 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4630 for (k = class->parent; k ; k = k->parent) {
4631 for (i = 0; i < k->interface_count; i++) {
4632 ic = k->interfaces [i];
4633 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4634 mono_class_interface_offset (class, ic),
4635 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4641 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4646 char *name = mono_type_get_full_name (class);
4647 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4650 g_hash_table_destroy (override_map);
4652 g_slist_free (virt_methods);
4657 * mono_method_get_vtable_slot:
4659 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4660 * LOCKING: Acquires the loader lock.
4662 * FIXME Use proper MonoError machinery here.
4665 mono_method_get_vtable_slot (MonoMethod *method)
4667 if (method->slot == -1) {
4668 mono_class_setup_vtable (method->klass);
4669 if (method->klass->exception_type)
4671 if (method->slot == -1) {
4675 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4676 g_assert (method->klass->generic_class);
4677 gklass = method->klass->generic_class->container_class;
4678 mono_class_setup_methods (method->klass);
4679 g_assert (method->klass->methods);
4680 for (i = 0; i < method->klass->method.count; ++i) {
4681 if (method->klass->methods [i] == method)
4684 g_assert (i < method->klass->method.count);
4685 g_assert (gklass->methods);
4686 method->slot = gklass->methods [i]->slot;
4688 g_assert (method->slot != -1);
4690 return method->slot;
4694 * mono_method_get_vtable_index:
4697 * Returns the index into the runtime vtable to access the method or,
4698 * in the case of a virtual generic method, the virtual generic method
4699 * thunk. Returns -1 on failure.
4701 * FIXME Use proper MonoError machinery here.
4704 mono_method_get_vtable_index (MonoMethod *method)
4706 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4707 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4708 if (imethod->declaring->is_generic)
4709 return mono_method_get_vtable_slot (imethod->declaring);
4711 return mono_method_get_vtable_slot (method);
4714 static MonoMethod *default_ghc = NULL;
4715 static MonoMethod *default_finalize = NULL;
4716 static int finalize_slot = -1;
4717 static int ghc_slot = -1;
4720 initialize_object_slots (MonoClass *class)
4725 if (class == mono_defaults.object_class) {
4726 mono_class_setup_vtable (class);
4727 for (i = 0; i < class->vtable_size; ++i) {
4728 MonoMethod *cm = class->vtable [i];
4730 if (!strcmp (cm->name, "GetHashCode"))
4732 else if (!strcmp (cm->name, "Finalize"))
4736 g_assert (ghc_slot > 0);
4737 default_ghc = class->vtable [ghc_slot];
4739 g_assert (finalize_slot > 0);
4740 default_finalize = class->vtable [finalize_slot];
4745 MonoMethod *array_method;
4747 } GenericArrayMethodInfo;
4749 static int generic_array_method_num = 0;
4750 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4753 generic_array_methods (MonoClass *class)
4755 int i, count_generic = 0;
4756 GList *list = NULL, *tmp;
4757 if (generic_array_method_num)
4758 return generic_array_method_num;
4759 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4760 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4761 for (i = 0; i < class->parent->method.count; i++) {
4762 MonoMethod *m = class->parent->methods [i];
4763 if (!strncmp (m->name, "InternalArray__", 15)) {
4765 list = g_list_prepend (list, m);
4768 list = g_list_reverse (list);
4769 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4771 for (tmp = list; tmp; tmp = tmp->next) {
4772 const char *mname, *iname;
4774 MonoMethod *m = tmp->data;
4775 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4776 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4778 generic_array_method_info [i].array_method = m;
4779 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4780 iname = "System.Collections.Generic.ICollection`1.";
4781 mname = m->name + 27;
4782 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4783 iname = "System.Collections.Generic.IEnumerable`1.";
4784 mname = m->name + 27;
4785 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4786 iname = "System.Collections.Generic.IReadOnlyList`1.";
4787 mname = m->name + strlen (ireadonlylist_prefix);
4788 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4789 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4790 mname = m->name + strlen (ireadonlycollection_prefix);
4791 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4792 iname = "System.Collections.Generic.IList`1.";
4793 mname = m->name + 15;
4795 g_assert_not_reached ();
4798 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4799 strcpy (name, iname);
4800 strcpy (name + strlen (iname), mname);
4801 generic_array_method_info [i].name = name;
4804 /*g_print ("array generic methods: %d\n", count_generic);*/
4806 generic_array_method_num = count_generic;
4808 return generic_array_method_num;
4812 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4814 MonoGenericContext tmp_context;
4817 tmp_context.class_inst = NULL;
4818 tmp_context.method_inst = iface->generic_class->context.class_inst;
4819 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4821 for (i = 0; i < generic_array_method_num; i++) {
4822 MonoMethod *m = generic_array_method_info [i].array_method;
4823 MonoMethod *inflated;
4825 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4826 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4831 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4833 int null_length = strlen ("(null)");
4834 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4835 char *s = mono_image_alloc (image, len);
4838 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4839 g_assert (result == len - 1);
4845 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4847 gpointer exception_data = NULL;
4849 switch (error->exception_type) {
4850 case MONO_EXCEPTION_TYPE_LOAD:
4851 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4854 case MONO_EXCEPTION_MISSING_METHOD:
4855 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4858 case MONO_EXCEPTION_MISSING_FIELD: {
4859 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4860 const char *class_name;
4863 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4865 class_name = error->klass->name;
4867 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4870 g_free ((void*)class_name);
4874 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4877 if (error->ref_only)
4878 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.";
4880 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4882 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4886 case MONO_EXCEPTION_BAD_IMAGE:
4887 exception_data = error->msg;
4891 g_assert_not_reached ();
4894 mono_class_set_failure (class, error->exception_type, exception_data);
4899 * @class: the class to initialize
4901 * Compute the instance_size, class_size and other infos that cannot be
4902 * computed at mono_class_get() time. Also compute vtable_size if possible.
4903 * Returns TRUE on success or FALSE if there was a problem in loading
4904 * the type (incorrect assemblies, missing assemblies, methods, etc).
4906 * LOCKING: Acquires the loader lock.
4909 mono_class_init (MonoClass *class)
4912 MonoCachedClassInfo cached_info;
4913 gboolean has_cached_info;
4917 /* Double-checking locking pattern */
4918 if (class->inited || class->exception_type)
4919 return class->exception_type == MONO_EXCEPTION_NONE;
4921 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4923 /* We do everything inside the lock to prevent races */
4924 mono_loader_lock ();
4926 if (class->inited || class->exception_type) {
4927 mono_loader_unlock ();
4928 /* Somebody might have gotten in before us */
4929 return class->exception_type == MONO_EXCEPTION_NONE;
4932 if (class->init_pending) {
4933 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4937 class->init_pending = 1;
4939 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4940 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4945 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4946 MonoClass *element_class = class->element_class;
4947 if (!element_class->inited)
4948 mono_class_init (element_class);
4949 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4950 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4955 /* CAS - SecurityAction.InheritanceDemand */
4956 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4957 mono_secman_inheritancedemand_class (class, class->parent);
4960 mono_stats.initialized_class_count++;
4962 if (class->generic_class && !class->generic_class->is_dynamic) {
4963 MonoClass *gklass = class->generic_class->container_class;
4965 mono_stats.generic_class_count++;
4967 class->method = gklass->method;
4968 class->field = gklass->field;
4970 mono_class_init (gklass);
4971 // FIXME: Why is this needed ?
4972 if (!gklass->exception_type)
4973 mono_class_setup_methods (gklass);
4974 if (gklass->exception_type) {
4975 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4979 if (MONO_CLASS_IS_INTERFACE (class))
4980 class->interface_id = mono_get_unique_iid (class);
4983 if (class->parent && !class->parent->inited)
4984 mono_class_init (class->parent);
4986 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
4988 if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
4989 class->nested_classes_inited = TRUE;
4992 * Computes the size used by the fields, and their locations
4994 if (has_cached_info) {
4995 class->instance_size = cached_info.instance_size;
4996 class->sizes.class_size = cached_info.class_size;
4997 class->packing_size = cached_info.packing_size;
4998 class->min_align = cached_info.min_align;
4999 class->blittable = cached_info.blittable;
5000 class->has_references = cached_info.has_references;
5001 class->has_static_refs = cached_info.has_static_refs;
5002 class->no_special_static_fields = cached_info.no_special_static_fields;
5005 if (!class->size_inited){
5006 mono_class_setup_fields (class);
5007 if (class->exception_type || mono_loader_get_last_error ())
5011 /* Initialize arrays */
5013 class->method.count = 3 + (class->rank > 1? 2: 1);
5015 if (class->interface_count) {
5016 int count_generic = generic_array_methods (class);
5017 class->method.count += class->interface_count * count_generic;
5021 mono_class_setup_supertypes (class);
5024 initialize_object_slots (class);
5027 * Initialize the rest of the data without creating a generic vtable if possible.
5028 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5029 * also avoid computing a generic vtable.
5031 if (has_cached_info) {
5033 class->vtable_size = cached_info.vtable_size;
5034 class->has_finalize = cached_info.has_finalize;
5035 class->has_finalize_inited = TRUE;
5036 class->ghcimpl = cached_info.ghcimpl;
5037 class->has_cctor = cached_info.has_cctor;
5038 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5039 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5040 * The first slot if for array with.
5042 static int szarray_vtable_size[2] = { 0 };
5044 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5047 if (!szarray_vtable_size [slot]) {
5048 mono_class_setup_vtable (class);
5049 szarray_vtable_size [slot] = class->vtable_size;
5051 class->vtable_size = szarray_vtable_size[slot];
5053 class->has_finalize_inited = TRUE;
5054 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5055 MonoClass *gklass = class->generic_class->container_class;
5057 /* Generic instance case */
5058 class->ghcimpl = gklass->ghcimpl;
5059 class->has_finalize = mono_class_has_finalizer (gklass);
5060 class->has_finalize_inited = TRUE;
5061 class->has_cctor = gklass->has_cctor;
5063 mono_class_setup_vtable (gklass);
5064 if (gklass->exception_type) {
5065 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5069 class->vtable_size = gklass->vtable_size;
5073 /* ghcimpl is not currently used
5075 if (class->parent) {
5076 MonoMethod *cmethod = class->vtable [ghc_slot];
5077 if (cmethod->is_inflated)
5078 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5079 if (cmethod == default_ghc) {
5085 /* C# doesn't allow interfaces to have cctors */
5086 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5087 MonoMethod *cmethod = NULL;
5089 if (class->type_token) {
5090 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5091 /* The find_method function ignores the 'flags' argument */
5092 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5093 class->has_cctor = 1;
5095 mono_class_setup_methods (class);
5096 if (class->exception_type)
5099 for (i = 0; i < class->method.count; ++i) {
5100 MonoMethod *method = class->methods [i];
5101 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5102 (strcmp (".cctor", method->name) == 0)) {
5103 class->has_cctor = 1;
5111 if (class->parent) {
5112 int first_iface_slot;
5113 /* This will compute class->parent->vtable_size for some classes */
5114 mono_class_init (class->parent);
5115 if (class->parent->exception_type) {
5116 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5119 if (mono_loader_get_last_error ())
5121 if (!class->parent->vtable_size) {
5122 /* FIXME: Get rid of this somehow */
5123 mono_class_setup_vtable (class->parent);
5124 if (class->parent->exception_type) {
5125 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5128 if (mono_loader_get_last_error ())
5131 first_iface_slot = class->parent->vtable_size;
5132 if (mono_class_need_stelemref_method (class))
5134 setup_interface_offsets (class, first_iface_slot, TRUE);
5136 setup_interface_offsets (class, 0, TRUE);
5139 if (mono_security_core_clr_enabled ())
5140 mono_security_core_clr_check_inheritance (class);
5142 if (mono_loader_get_last_error ()) {
5143 if (class->exception_type == MONO_EXCEPTION_NONE) {
5144 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5146 mono_loader_clear_error ();
5149 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5150 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5155 /* Because of the double-checking locking pattern */
5156 mono_memory_barrier ();
5158 class->init_pending = 0;
5160 mono_loader_unlock ();
5162 if (mono_debugger_class_init_func)
5163 mono_debugger_class_init_func (class);
5165 return class->exception_type == MONO_EXCEPTION_NONE;
5169 * mono_class_has_finalizer:
5171 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5175 mono_class_has_finalizer (MonoClass *klass)
5177 if (!klass->has_finalize_inited) {
5178 MonoClass *class = klass;
5180 mono_loader_lock ();
5182 /* Interfaces and valuetypes are not supposed to have finalizers */
5183 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5184 MonoMethod *cmethod = NULL;
5186 if (class->parent && class->parent->has_finalize) {
5187 class->has_finalize = 1;
5189 if (class->parent) {
5191 * Can't search in metadata for a method named Finalize, because that
5192 * ignores overrides.
5194 mono_class_setup_vtable (class);
5195 if (class->exception_type || mono_loader_get_last_error ())
5197 cmethod = class->vtable [finalize_slot];
5201 g_assert (class->vtable_size > finalize_slot);
5203 class->has_finalize = 0;
5204 if (class->parent) {
5205 if (cmethod->is_inflated)
5206 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5207 if (cmethod != default_finalize) {
5208 class->has_finalize = 1;
5215 mono_memory_barrier ();
5216 klass->has_finalize_inited = TRUE;
5218 mono_loader_unlock ();
5221 return klass->has_finalize;
5224 mono_loader_unlock ();
5229 mono_is_corlib_image (MonoImage *image)
5231 /* FIXME: allow the dynamic case for our compilers and with full trust */
5233 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5235 return image == mono_defaults.corlib;
5239 * LOCKING: this assumes the loader lock is held
5242 mono_class_setup_mono_type (MonoClass *class)
5244 const char *name = class->name;
5245 const char *nspace = class->name_space;
5246 gboolean is_corlib = mono_is_corlib_image (class->image);
5248 class->this_arg.byref = 1;
5249 class->this_arg.data.klass = class;
5250 class->this_arg.type = MONO_TYPE_CLASS;
5251 class->byval_arg.data.klass = class;
5252 class->byval_arg.type = MONO_TYPE_CLASS;
5254 if (is_corlib && !strcmp (nspace, "System")) {
5255 if (!strcmp (name, "ValueType")) {
5257 * do not set the valuetype bit for System.ValueType.
5258 * class->valuetype = 1;
5260 class->blittable = TRUE;
5261 } else if (!strcmp (name, "Enum")) {
5263 * do not set the valuetype bit for System.Enum.
5264 * class->valuetype = 1;
5266 class->valuetype = 0;
5267 class->enumtype = 0;
5268 } else if (!strcmp (name, "Object")) {
5269 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5270 } else if (!strcmp (name, "String")) {
5271 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5272 } else if (!strcmp (name, "TypedReference")) {
5273 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5277 if (class->valuetype) {
5278 int t = MONO_TYPE_VALUETYPE;
5280 if (is_corlib && !strcmp (nspace, "System")) {
5283 if (!strcmp (name, "Boolean")) {
5284 t = MONO_TYPE_BOOLEAN;
5285 } else if (!strcmp(name, "Byte")) {
5287 class->blittable = TRUE;
5291 if (!strcmp (name, "Char")) {
5296 if (!strcmp (name, "Double")) {
5298 class->blittable = TRUE;
5302 if (!strcmp (name, "Int32")) {
5304 class->blittable = TRUE;
5305 } else if (!strcmp(name, "Int16")) {
5307 class->blittable = TRUE;
5308 } else if (!strcmp(name, "Int64")) {
5310 class->blittable = TRUE;
5311 } else if (!strcmp(name, "IntPtr")) {
5313 class->blittable = TRUE;
5317 if (!strcmp (name, "Single")) {
5319 class->blittable = TRUE;
5320 } else if (!strcmp(name, "SByte")) {
5322 class->blittable = TRUE;
5326 if (!strcmp (name, "UInt32")) {
5328 class->blittable = TRUE;
5329 } else if (!strcmp(name, "UInt16")) {
5331 class->blittable = TRUE;
5332 } else if (!strcmp(name, "UInt64")) {
5334 class->blittable = TRUE;
5335 } else if (!strcmp(name, "UIntPtr")) {
5337 class->blittable = TRUE;
5341 if (!strcmp (name, "TypedReference")) {
5342 t = MONO_TYPE_TYPEDBYREF;
5343 class->blittable = TRUE;
5347 if (!strcmp (name, "Void")) {
5355 class->this_arg.type = class->byval_arg.type = t;
5358 if (MONO_CLASS_IS_INTERFACE (class))
5359 class->interface_id = mono_get_unique_iid (class);
5365 * COM initialization is delayed until needed.
5366 * However when a [ComImport] attribute is present on a type it will trigger
5367 * the initialization. This is not a problem unless the BCL being executed
5368 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5371 init_com_from_comimport (MonoClass *class)
5373 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5374 if (mono_security_core_clr_enabled ()) {
5375 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5376 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5377 /* but it can not be made available for application (i.e. user code) since all COM calls
5378 * are considered native calls. In this case we fail with a TypeLoadException (just like
5379 * Silverlight 2 does */
5380 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5385 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5387 #endif /*DISABLE_COM*/
5390 * LOCKING: this assumes the loader lock is held
5393 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5395 gboolean system_namespace;
5396 gboolean is_corlib = mono_is_corlib_image (class->image);
5398 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5400 /* if root of the hierarchy */
5401 if (system_namespace && !strcmp (class->name, "Object")) {
5402 class->parent = NULL;
5403 class->instance_size = sizeof (MonoObject);
5406 if (!strcmp (class->name, "<Module>")) {
5407 class->parent = NULL;
5408 class->instance_size = 0;
5412 if (!MONO_CLASS_IS_INTERFACE (class)) {
5413 /* Imported COM Objects always derive from __ComObject. */
5415 if (MONO_CLASS_IS_IMPORT (class)) {
5416 init_com_from_comimport (class);
5417 if (parent == mono_defaults.object_class)
5418 parent = mono_class_get_com_object_class ();
5422 /* set the parent to something useful and safe, but mark the type as broken */
5423 parent = mono_defaults.object_class;
5424 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5427 class->parent = parent;
5429 if (parent->generic_class && !parent->name) {
5431 * If the parent is a generic instance, we may get
5432 * called before it is fully initialized, especially
5433 * before it has its name.
5438 #ifndef DISABLE_REMOTING
5439 class->marshalbyref = parent->marshalbyref;
5440 class->contextbound = parent->contextbound;
5443 class->delegate = parent->delegate;
5445 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5446 mono_class_set_is_com_object (class);
5448 if (system_namespace) {
5449 #ifndef DISABLE_REMOTING
5450 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5451 class->marshalbyref = 1;
5453 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5454 class->contextbound = 1;
5456 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5457 class->delegate = 1;
5460 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5461 (strcmp (class->parent->name_space, "System") == 0)))
5462 class->valuetype = 1;
5463 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5464 class->valuetype = class->enumtype = 1;
5466 /*class->enumtype = class->parent->enumtype; */
5468 /* initialize com types if COM interfaces are present */
5470 if (MONO_CLASS_IS_IMPORT (class))
5471 init_com_from_comimport (class);
5473 class->parent = NULL;
5479 * mono_class_setup_supertypes:
5482 * Build the data structure needed to make fast type checks work.
5483 * This currently sets two fields in @class:
5484 * - idepth: distance between @class and System.Object in the type
5486 * - supertypes: array of classes: each element has a class in the hierarchy
5487 * starting from @class up to System.Object
5489 * LOCKING: This function is atomic, in case of contention we waste memory.
5492 mono_class_setup_supertypes (MonoClass *class)
5495 MonoClass **supertypes;
5497 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5501 if (class->parent && !class->parent->supertypes)
5502 mono_class_setup_supertypes (class->parent);
5504 class->idepth = class->parent->idepth + 1;
5508 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5509 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5511 if (class->parent) {
5512 supertypes [class->idepth - 1] = class;
5513 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5515 supertypes [0] = class;
5518 mono_atomic_store_release (&class->supertypes, supertypes);
5522 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5524 MonoClass *gtd = (MonoClass*)user_data;
5525 /* Only try to fix generic instances of @gtd */
5526 if (gclass->generic_class->container_class != gtd)
5529 /* Check if the generic instance has no parent. */
5530 if (gtd->parent && !gclass->parent)
5531 mono_generic_class_setup_parent (gclass, gtd);
5537 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5539 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5540 mono_error_set_type_load_class (error, class, msg);
5544 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5546 MonoLoaderError *lerror = mono_loader_get_last_error ();
5549 set_failure_from_loader_error (class, lerror);
5550 mono_error_set_from_loader_error (error);
5554 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5555 mono_error_set_type_load_class (error, class, msg);
5560 * mono_class_create_from_typedef:
5561 * @image: image where the token is valid
5562 * @type_token: typedef token
5563 * @error: used to return any error found while creating the type
5565 * Create the MonoClass* representing the specified type token.
5566 * @type_token must be a TypeDef token.
5568 * FIXME: don't return NULL on failure, just the the caller figure it out.
5571 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5573 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5574 MonoClass *class, *parent = NULL;
5575 guint32 cols [MONO_TYPEDEF_SIZE];
5576 guint32 cols_next [MONO_TYPEDEF_SIZE];
5577 guint tidx = mono_metadata_token_index (type_token);
5578 MonoGenericContext *context = NULL;
5579 const char *name, *nspace;
5581 MonoClass **interfaces;
5582 guint32 field_last, method_last;
5583 guint32 nesting_tokeen;
5585 mono_error_init (error);
5587 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5588 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5589 g_assert (!mono_loader_get_last_error ());
5593 mono_loader_lock ();
5595 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5596 mono_loader_unlock ();
5597 g_assert (!mono_loader_get_last_error ());
5601 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5603 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5604 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5606 class = mono_image_alloc0 (image, sizeof (MonoClass));
5609 class->name_space = nspace;
5611 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5613 class->image = image;
5614 class->type_token = type_token;
5615 class->flags = cols [MONO_TYPEDEF_FLAGS];
5617 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5619 classes_size += sizeof (MonoClass);
5622 * Check whether we're a generic type definition.
5624 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5625 if (class->generic_container) {
5626 class->is_generic = 1;
5627 class->generic_container->owner.klass = class;
5628 context = &class->generic_container->context;
5631 if (class->generic_container)
5632 enable_gclass_recording ();
5634 if (cols [MONO_TYPEDEF_EXTENDS]) {
5636 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5638 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5639 /*WARNING: this must satisfy mono_metadata_type_hash*/
5640 class->this_arg.byref = 1;
5641 class->this_arg.data.klass = class;
5642 class->this_arg.type = MONO_TYPE_CLASS;
5643 class->byval_arg.data.klass = class;
5644 class->byval_arg.type = MONO_TYPE_CLASS;
5646 parent = mono_class_get_full (image, parent_token, context);
5648 if (parent == NULL) {
5649 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5650 goto parent_failure;
5653 for (tmp = parent; tmp; tmp = tmp->parent) {
5655 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5656 goto parent_failure;
5658 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5659 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5660 goto parent_failure;
5665 mono_class_setup_parent (class, parent);
5667 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5668 mono_class_setup_mono_type (class);
5670 if (class->generic_container)
5671 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5674 * This might access class->byval_arg for recursion generated by generic constraints,
5675 * so it has to come after setup_mono_type ().
5677 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5678 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5679 if (!mono_error_ok (error)) {
5680 /*FIXME implement a mono_class_set_failure_from_mono_error */
5681 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5682 mono_loader_unlock ();
5683 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5684 g_assert (!mono_loader_get_last_error ());
5689 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5693 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5697 class->cast_class = class->element_class = class;
5699 if (!class->enumtype) {
5700 if (!mono_metadata_interfaces_from_typedef_full (
5701 image, type_token, &interfaces, &icount, FALSE, context)){
5702 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5703 mono_loader_unlock ();
5704 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5708 class->interfaces = interfaces;
5709 class->interface_count = icount;
5710 class->interfaces_inited = 1;
5713 /*g_print ("Load class %s\n", name);*/
5716 * Compute the field and method lists
5718 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5719 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5721 if (tt->rows > tidx){
5722 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5723 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5724 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5726 field_last = image->tables [MONO_TABLE_FIELD].rows;
5727 method_last = image->tables [MONO_TABLE_METHOD].rows;
5730 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5731 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5732 class->field.count = field_last - class->field.first;
5734 class->field.count = 0;
5736 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5737 class->method.count = method_last - class->method.first;
5739 class->method.count = 0;
5741 /* reserve space to store vector pointer in arrays */
5742 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5743 class->instance_size += 2 * sizeof (gpointer);
5744 g_assert (class->field.count == 0);
5747 if (class->enumtype) {
5748 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5749 if (!enum_basetype) {
5750 /*set it to a default value as the whole runtime can't handle this to be null*/
5751 class->cast_class = class->element_class = mono_defaults.int32_class;
5752 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5753 mono_loader_unlock ();
5754 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5755 g_assert (!mono_loader_get_last_error ());
5758 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5762 * If we're a generic type definition, load the constraints.
5763 * We must do this after the class has been constructed to make certain recursive scenarios
5766 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5767 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5768 mono_loader_unlock ();
5769 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5770 g_assert (!mono_loader_get_last_error ());
5774 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5775 if (!strncmp (name, "Vector", 6))
5776 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");
5779 mono_loader_unlock ();
5781 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5782 g_assert (!mono_loader_get_last_error ());
5787 mono_class_setup_mono_type (class);
5788 mono_loader_unlock ();
5789 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5790 g_assert (!mono_loader_get_last_error ());
5794 /** is klass Nullable<T>? */
5796 mono_class_is_nullable (MonoClass *klass)
5798 return klass->generic_class != NULL &&
5799 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5803 /** if klass is T? return T */
5805 mono_class_get_nullable_param (MonoClass *klass)
5807 g_assert (mono_class_is_nullable (klass));
5808 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5812 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5816 MonoGenericClass *gclass = klass->generic_class;
5818 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5819 if (!mono_error_ok (&error)) {
5820 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5821 klass->parent = mono_defaults.object_class;
5822 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5823 mono_error_cleanup (&error);
5827 mono_class_setup_parent (klass, klass->parent);
5829 if (klass->enumtype) {
5830 klass->cast_class = gtd->cast_class;
5831 klass->element_class = gtd->element_class;
5837 * Create the `MonoClass' for an instantiation of a generic type.
5838 * We only do this if we actually need it.
5841 mono_generic_class_get_class (MonoGenericClass *gclass)
5843 MonoClass *klass, *gklass;
5845 if (gclass->cached_class)
5846 return gclass->cached_class;
5848 mono_loader_lock ();
5849 if (gclass->cached_class) {
5850 mono_loader_unlock ();
5851 return gclass->cached_class;
5854 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5856 gklass = gclass->container_class;
5858 if (record_gclass_instantiation > 0)
5859 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5861 if (gklass->nested_in) {
5862 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5863 klass->nested_in = gklass->nested_in;
5866 klass->name = gklass->name;
5867 klass->name_space = gklass->name_space;
5869 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5871 klass->image = gklass->image;
5872 klass->flags = gklass->flags;
5873 klass->type_token = gklass->type_token;
5874 klass->field.count = gklass->field.count;
5876 klass->is_inflated = 1;
5877 klass->generic_class = gclass;
5879 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5880 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5881 klass->this_arg.byref = TRUE;
5882 klass->enumtype = gklass->enumtype;
5883 klass->valuetype = gklass->valuetype;
5885 klass->cast_class = klass->element_class = klass;
5887 if (mono_class_is_nullable (klass))
5888 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5891 * We're not interested in the nested classes of a generic instance.
5892 * We use the generic type definition to look for nested classes.
5895 mono_generic_class_setup_parent (klass, gklass);
5897 if (gclass->is_dynamic) {
5900 mono_class_setup_supertypes (klass);
5902 if (klass->enumtype) {
5904 * For enums, gklass->fields might not been set, but instance_size etc. is
5905 * already set in mono_reflection_create_internal_class (). For non-enums,
5906 * these will be computed normally in mono_class_layout_fields ().
5908 klass->instance_size = gklass->instance_size;
5909 klass->sizes.class_size = gklass->sizes.class_size;
5910 mono_memory_barrier ();
5911 klass->size_inited = 1;
5915 mono_memory_barrier ();
5916 gclass->cached_class = klass;
5918 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5920 inflated_classes ++;
5921 inflated_classes_size += sizeof (MonoClass);
5923 mono_loader_unlock ();
5929 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5931 MonoClass *klass, **ptr;
5933 MonoGenericContainer *container = mono_generic_param_owner (param);
5937 image = mono_defaults.corlib;
5939 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5940 classes_size += sizeof (MonoClass);
5943 klass->name = pinfo->name;
5945 int n = mono_generic_param_num (param);
5946 klass->name = mono_image_alloc0 (image, 16);
5947 sprintf ((char*)klass->name, "%d", n);
5952 MonoMethod *omethod = container->owner.method;
5953 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5955 MonoClass *oklass = container->owner.klass;
5956 klass->name_space = oklass ? oklass->name_space : "";
5959 klass->name_space = "";
5962 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5966 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5970 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5971 klass->parent = pinfo->constraints [0];
5973 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5974 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5976 klass->parent = mono_defaults.object_class;
5979 if (count - pos > 0) {
5980 klass->interface_count = count - pos;
5981 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5982 klass->interfaces_inited = TRUE;
5983 for (i = pos; i < count; i++)
5984 klass->interfaces [i - pos] = pinfo->constraints [i];
5987 klass->image = image;
5989 klass->inited = TRUE;
5990 klass->cast_class = klass->element_class = klass;
5991 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5993 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5994 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5995 klass->this_arg.byref = TRUE;
5997 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5998 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6000 /*Init these fields to sane values*/
6001 klass->min_align = 1;
6002 klass->instance_size = sizeof (gpointer);
6003 mono_memory_barrier ();
6004 klass->size_inited = 1;
6006 mono_class_setup_supertypes (klass);
6008 if (count - pos > 0) {
6009 mono_class_setup_vtable (klass->parent);
6010 if (klass->parent->exception_type)
6011 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6013 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6019 #define FAST_CACHE_SIZE 16
6022 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6024 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6025 MonoImage *image = param->image;
6030 if (n < FAST_CACHE_SIZE) {
6032 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6034 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6036 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6037 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6042 * LOCKING: Acquires the loader lock.
6045 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6047 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6048 MonoImage *image = param->image;
6053 if (n < FAST_CACHE_SIZE) {
6055 /* No locking needed */
6056 if (!image->mvar_cache_fast)
6057 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6058 image->mvar_cache_fast [n] = klass;
6060 if (!image->var_cache_fast)
6061 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6062 image->var_cache_fast [n] = klass;
6066 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6068 mono_loader_lock ();
6069 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6071 ht = g_hash_table_new (NULL, NULL);
6072 mono_memory_barrier ();
6074 image->mvar_cache_slow = ht;
6076 image->var_cache_slow = ht;
6078 mono_loader_unlock ();
6081 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6085 * LOCKING: Acquires the loader lock.
6088 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6090 MonoGenericContainer *container = mono_generic_param_owner (param);
6091 MonoGenericParamInfo *pinfo;
6094 mono_loader_lock ();
6097 pinfo = mono_generic_param_info (param);
6098 if (pinfo->pklass) {
6099 mono_loader_unlock ();
6100 return pinfo->pklass;
6106 klass = get_anon_gparam_class (param, is_mvar);
6108 mono_loader_unlock ();
6113 if (!image && container) {
6115 MonoMethod *method = container->owner.method;
6116 image = (method && method->klass) ? method->klass->image : NULL;
6118 MonoClass *klass = container->owner.klass;
6119 // FIXME: 'klass' should not be null
6120 // But, monodis creates GenericContainers without associating a owner to it
6121 image = klass ? klass->image : NULL;
6125 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6127 mono_memory_barrier ();
6130 pinfo->pklass = klass;
6132 set_anon_gparam_class (param, is_mvar, klass);
6134 mono_loader_unlock ();
6136 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6137 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6143 mono_ptr_class_get (MonoType *type)
6146 MonoClass *el_class;
6150 el_class = mono_class_from_mono_type (type);
6151 image = el_class->image;
6153 mono_loader_lock ();
6155 if (!image->ptr_cache)
6156 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6158 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6159 mono_loader_unlock ();
6162 result = mono_image_alloc0 (image, sizeof (MonoClass));
6164 classes_size += sizeof (MonoClass);
6166 result->parent = NULL; /* no parent for PTR types */
6167 result->name_space = el_class->name_space;
6168 name = g_strdup_printf ("%s*", el_class->name);
6169 result->name = mono_image_strdup (image, name);
6172 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6174 result->image = el_class->image;
6175 result->inited = TRUE;
6176 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6177 /* Can pointers get boxed? */
6178 result->instance_size = sizeof (gpointer);
6179 result->cast_class = result->element_class = el_class;
6180 result->blittable = TRUE;
6182 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6183 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6184 result->this_arg.byref = TRUE;
6186 mono_class_setup_supertypes (result);
6188 g_hash_table_insert (image->ptr_cache, el_class, result);
6190 mono_loader_unlock ();
6192 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6198 mono_fnptr_class_get (MonoMethodSignature *sig)
6201 static GHashTable *ptr_hash = NULL;
6203 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6205 mono_loader_lock ();
6208 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6210 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6211 mono_loader_unlock ();
6214 result = g_new0 (MonoClass, 1);
6216 result->parent = NULL; /* no parent for PTR types */
6217 result->name_space = "System";
6218 result->name = "MonoFNPtrFakeClass";
6220 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6222 result->image = mono_defaults.corlib; /* need to fix... */
6223 result->inited = TRUE;
6224 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6225 /* Can pointers get boxed? */
6226 result->instance_size = sizeof (gpointer);
6227 result->cast_class = result->element_class = result;
6228 result->blittable = TRUE;
6230 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6231 result->this_arg.data.method = result->byval_arg.data.method = sig;
6232 result->this_arg.byref = TRUE;
6233 result->blittable = TRUE;
6235 mono_class_setup_supertypes (result);
6237 g_hash_table_insert (ptr_hash, sig, result);
6239 mono_loader_unlock ();
6241 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6247 mono_class_from_mono_type (MonoType *type)
6249 switch (type->type) {
6250 case MONO_TYPE_OBJECT:
6251 return type->data.klass? type->data.klass: mono_defaults.object_class;
6252 case MONO_TYPE_VOID:
6253 return type->data.klass? type->data.klass: mono_defaults.void_class;
6254 case MONO_TYPE_BOOLEAN:
6255 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6256 case MONO_TYPE_CHAR:
6257 return type->data.klass? type->data.klass: mono_defaults.char_class;
6259 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6261 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6263 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6265 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6267 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6269 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6271 return type->data.klass? type->data.klass: mono_defaults.int_class;
6273 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6275 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6277 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6279 return type->data.klass? type->data.klass: mono_defaults.single_class;
6281 return type->data.klass? type->data.klass: mono_defaults.double_class;
6282 case MONO_TYPE_STRING:
6283 return type->data.klass? type->data.klass: mono_defaults.string_class;
6284 case MONO_TYPE_TYPEDBYREF:
6285 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6286 case MONO_TYPE_ARRAY:
6287 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6289 return mono_ptr_class_get (type->data.type);
6290 case MONO_TYPE_FNPTR:
6291 return mono_fnptr_class_get (type->data.method);
6292 case MONO_TYPE_SZARRAY:
6293 return mono_array_class_get (type->data.klass, 1);
6294 case MONO_TYPE_CLASS:
6295 case MONO_TYPE_VALUETYPE:
6296 return type->data.klass;
6297 case MONO_TYPE_GENERICINST:
6298 return mono_generic_class_get_class (type->data.generic_class);
6300 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6301 case MONO_TYPE_MVAR:
6302 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6304 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6305 g_assert_not_reached ();
6312 * mono_type_retrieve_from_typespec
6313 * @image: context where the image is created
6314 * @type_spec: typespec token
6315 * @context: the generic context used to evaluate generic instantiations in
6318 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6320 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6322 mono_error_init (error);
6323 *did_inflate = FALSE;
6326 char *name = mono_class_name_from_token (image, type_spec);
6327 char *assembly = mono_assembly_name_from_token (image, type_spec);
6328 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6332 if (context && (context->class_inst || context->method_inst)) {
6333 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6335 if (!mono_error_ok (error))
6340 *did_inflate = TRUE;
6347 * mono_class_create_from_typespec
6348 * @image: context where the image is created
6349 * @type_spec: typespec token
6350 * @context: the generic context used to evaluate generic instantiations in
6353 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6356 gboolean inflated = FALSE;
6357 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6358 if (!mono_error_ok (error))
6360 ret = mono_class_from_mono_type (t);
6362 mono_metadata_free_type (t);
6367 * mono_bounded_array_class_get:
6368 * @element_class: element class
6369 * @rank: the dimension of the array class
6370 * @bounded: whenever the array has non-zero bounds
6372 * Returns: a class object describing the array with element type @element_type and
6376 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6380 MonoClass *parent = NULL;
6381 GSList *list, *rootlist = NULL;
6384 gboolean corlib_type = FALSE;
6386 g_assert (rank <= 255);
6389 /* bounded only matters for one-dimensional arrays */
6392 image = eclass->image;
6394 if (rank == 1 && !bounded) {
6396 * This case is very frequent not just during compilation because of calls
6397 * from mono_class_from_mono_type (), mono_array_new (),
6398 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6400 EnterCriticalSection (&image->szarray_cache_lock);
6401 if (!image->szarray_cache)
6402 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6403 class = g_hash_table_lookup (image->szarray_cache, eclass);
6404 LeaveCriticalSection (&image->szarray_cache_lock);
6408 mono_loader_lock ();
6410 mono_loader_lock ();
6412 if (!image->array_cache)
6413 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6415 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6416 for (; list; list = list->next) {
6418 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6419 mono_loader_unlock ();
6426 /* for the building corlib use System.Array from it */
6427 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6428 parent = mono_class_from_name (image, "System", "Array");
6431 parent = mono_defaults.array_class;
6432 if (!parent->inited)
6433 mono_class_init (parent);
6436 class = mono_image_alloc0 (image, sizeof (MonoClass));
6438 class->image = image;
6439 class->name_space = eclass->name_space;
6440 nsize = strlen (eclass->name);
6441 name = g_malloc (nsize + 2 + rank + 1);
6442 memcpy (name, eclass->name, nsize);
6445 memset (name + nsize + 1, ',', rank - 1);
6447 name [nsize + rank] = '*';
6448 name [nsize + rank + bounded] = ']';
6449 name [nsize + rank + bounded + 1] = 0;
6450 class->name = mono_image_strdup (image, name);
6453 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6455 classes_size += sizeof (MonoClass);
6457 class->type_token = 0;
6458 /* all arrays are marked serializable and sealed, bug #42779 */
6459 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6460 class->parent = parent;
6461 class->instance_size = mono_class_instance_size (class->parent);
6463 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6464 /*Arrays of those two types are invalid.*/
6465 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6466 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6467 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6468 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6469 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6471 /* element_size -1 is ok as this is not an instantitable type*/
6472 class->sizes.element_size = -1;
6474 class->sizes.element_size = mono_class_array_element_size (eclass);
6476 mono_class_setup_supertypes (class);
6478 if (eclass->generic_class)
6479 mono_class_init (eclass);
6480 if (!eclass->size_inited)
6481 mono_class_setup_fields (eclass);
6482 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6483 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6485 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6489 if (eclass->enumtype)
6490 class->cast_class = eclass->element_class;
6492 class->cast_class = eclass;
6494 switch (class->cast_class->byval_arg.type) {
6496 class->cast_class = mono_defaults.byte_class;
6499 class->cast_class = mono_defaults.int16_class;
6502 #if SIZEOF_VOID_P == 4
6506 class->cast_class = mono_defaults.int32_class;
6509 #if SIZEOF_VOID_P == 8
6513 class->cast_class = mono_defaults.int64_class;
6517 class->element_class = eclass;
6519 if ((rank > 1) || bounded) {
6520 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6521 class->byval_arg.type = MONO_TYPE_ARRAY;
6522 class->byval_arg.data.array = at;
6523 at->eklass = eclass;
6525 /* FIXME: complete.... */
6527 class->byval_arg.type = MONO_TYPE_SZARRAY;
6528 class->byval_arg.data.klass = eclass;
6530 class->this_arg = class->byval_arg;
6531 class->this_arg.byref = 1;
6536 class->generic_container = eclass->generic_container;
6538 if (rank == 1 && !bounded) {
6539 MonoClass *prev_class;
6541 EnterCriticalSection (&image->szarray_cache_lock);
6542 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6544 /* Someone got in before us */
6547 g_hash_table_insert (image->szarray_cache, eclass, class);
6548 LeaveCriticalSection (&image->szarray_cache_lock);
6550 list = g_slist_append (rootlist, class);
6551 g_hash_table_insert (image->array_cache, eclass, list);
6554 mono_loader_unlock ();
6556 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6562 * mono_array_class_get:
6563 * @element_class: element class
6564 * @rank: the dimension of the array class
6566 * Returns: a class object describing the array with element type @element_type and
6570 mono_array_class_get (MonoClass *eclass, guint32 rank)
6572 return mono_bounded_array_class_get (eclass, rank, FALSE);
6576 * mono_class_instance_size:
6579 * Returns: the size of an object instance
6582 mono_class_instance_size (MonoClass *klass)
6584 if (!klass->size_inited)
6585 mono_class_init (klass);
6587 return klass->instance_size;
6591 * mono_class_min_align:
6594 * Returns: minimm alignment requirements
6597 mono_class_min_align (MonoClass *klass)
6599 if (!klass->size_inited)
6600 mono_class_init (klass);
6602 return klass->min_align;
6606 * mono_class_value_size:
6609 * This function is used for value types, and return the
6610 * space and the alignment to store that kind of value object.
6612 * Returns: the size of a value of kind @klass
6615 mono_class_value_size (MonoClass *klass, guint32 *align)
6619 /* fixme: check disable, because we still have external revereces to
6620 * mscorlib and Dummy Objects
6622 /*g_assert (klass->valuetype);*/
6624 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6627 *align = klass->min_align;
6633 * mono_class_data_size:
6636 * Returns: the size of the static class data
6639 mono_class_data_size (MonoClass *klass)
6642 mono_class_init (klass);
6643 /* This can happen with dynamically created types */
6644 if (!klass->fields_inited)
6645 mono_class_setup_fields_locking (klass);
6647 /* in arrays, sizes.class_size is unioned with element_size
6648 * and arrays have no static fields
6652 return klass->sizes.class_size;
6656 * Auxiliary routine to mono_class_get_field
6658 * Takes a field index instead of a field token.
6660 static MonoClassField *
6661 mono_class_get_field_idx (MonoClass *class, int idx)
6663 mono_class_setup_fields_locking (class);
6664 if (class->exception_type)
6668 if (class->image->uncompressed_metadata) {
6670 * class->field.first points to the FieldPtr table, while idx points into the
6671 * Field table, so we have to do a search.
6673 /*FIXME this is broken for types with multiple fields with the same name.*/
6674 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6677 for (i = 0; i < class->field.count; ++i)
6678 if (mono_field_get_name (&class->fields [i]) == name)
6679 return &class->fields [i];
6680 g_assert_not_reached ();
6682 if (class->field.count) {
6683 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6684 return &class->fields [idx - class->field.first];
6688 class = class->parent;
6694 * mono_class_get_field:
6695 * @class: the class to lookup the field.
6696 * @field_token: the field token
6698 * Returns: A MonoClassField representing the type and offset of
6699 * the field, or a NULL value if the field does not belong to this
6703 mono_class_get_field (MonoClass *class, guint32 field_token)
6705 int idx = mono_metadata_token_index (field_token);
6707 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6709 return mono_class_get_field_idx (class, idx - 1);
6713 * mono_class_get_field_from_name:
6714 * @klass: the class to lookup the field.
6715 * @name: the field name
6717 * Search the class @klass and it's parents for a field with the name @name.
6719 * Returns: the MonoClassField pointer of the named field or NULL
6722 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6724 return mono_class_get_field_from_name_full (klass, name, NULL);
6728 * mono_class_get_field_from_name_full:
6729 * @klass: the class to lookup the field.
6730 * @name: the field name
6731 * @type: the type of the fields. This optional.
6733 * Search the class @klass and it's parents for a field with the name @name and type @type.
6735 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6736 * of its generic type definition.
6738 * Returns: the MonoClassField pointer of the named field or NULL
6741 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6745 mono_class_setup_fields_locking (klass);
6746 if (klass->exception_type)
6750 for (i = 0; i < klass->field.count; ++i) {
6751 MonoClassField *field = &klass->fields [i];
6753 if (strcmp (name, mono_field_get_name (field)) != 0)
6757 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6758 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6763 klass = klass->parent;
6769 * mono_class_get_field_token:
6770 * @field: the field we need the token of
6772 * Get the token of a field. Note that the tokesn is only valid for the image
6773 * the field was loaded from. Don't use this function for fields in dynamic types.
6775 * Returns: the token representing the field in the image it was loaded from.
6778 mono_class_get_field_token (MonoClassField *field)
6780 MonoClass *klass = field->parent;
6783 mono_class_setup_fields_locking (klass);
6788 for (i = 0; i < klass->field.count; ++i) {
6789 if (&klass->fields [i] == field) {
6790 int idx = klass->field.first + i + 1;
6792 if (klass->image->uncompressed_metadata)
6793 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6794 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6797 klass = klass->parent;
6800 g_assert_not_reached ();
6805 mono_field_get_index (MonoClassField *field)
6807 int index = field - field->parent->fields;
6809 g_assert (index >= 0 && index < field->parent->field.count);
6815 * mono_class_get_field_default_value:
6817 * Return the default value of the field as a pointer into the metadata blob.
6820 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6823 guint32 constant_cols [MONO_CONSTANT_SIZE];
6825 MonoClass *klass = field->parent;
6827 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6829 if (!klass->ext || !klass->ext->field_def_values) {
6830 mono_loader_lock ();
6831 mono_class_alloc_ext (klass);
6832 if (!klass->ext->field_def_values)
6833 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6834 mono_loader_unlock ();
6837 field_index = mono_field_get_index (field);
6839 if (!klass->ext->field_def_values [field_index].data) {
6840 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6844 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6846 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6847 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6848 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6851 *def_type = klass->ext->field_def_values [field_index].def_type;
6852 return klass->ext->field_def_values [field_index].data;
6856 mono_property_get_index (MonoProperty *prop)
6858 int index = prop - prop->parent->ext->properties;
6860 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6866 * mono_class_get_property_default_value:
6868 * Return the default value of the field as a pointer into the metadata blob.
6871 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6874 guint32 constant_cols [MONO_CONSTANT_SIZE];
6875 MonoClass *klass = property->parent;
6877 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6879 * We don't cache here because it is not used by C# so it's quite rare, but
6880 * we still do the lookup in klass->ext because that is where the data
6881 * is stored for dynamic assemblies.
6884 if (klass->image->dynamic) {
6885 int prop_index = mono_property_get_index (property);
6886 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6887 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6888 return klass->ext->prop_def_values [prop_index].data;
6892 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6896 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6897 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6898 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6902 mono_class_get_event_token (MonoEvent *event)
6904 MonoClass *klass = event->parent;
6909 for (i = 0; i < klass->ext->event.count; ++i) {
6910 if (&klass->ext->events [i] == event)
6911 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6914 klass = klass->parent;
6917 g_assert_not_reached ();
6922 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6926 gpointer iter = NULL;
6927 while ((p = mono_class_get_properties (klass, &iter))) {
6928 if (! strcmp (name, p->name))
6931 klass = klass->parent;
6937 mono_class_get_property_token (MonoProperty *prop)
6939 MonoClass *klass = prop->parent;
6943 gpointer iter = NULL;
6944 while ((p = mono_class_get_properties (klass, &iter))) {
6945 if (&klass->ext->properties [i] == prop)
6946 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6950 klass = klass->parent;
6953 g_assert_not_reached ();
6958 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6960 const char *name, *nspace;
6962 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6964 switch (type_token & 0xff000000){
6965 case MONO_TOKEN_TYPE_DEF: {
6966 guint32 cols [MONO_TYPEDEF_SIZE];
6967 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6968 guint tidx = mono_metadata_token_index (type_token);
6970 if (tidx > tt->rows)
6971 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6973 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6974 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6975 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6976 if (strlen (nspace) == 0)
6977 return g_strdup_printf ("%s", name);
6979 return g_strdup_printf ("%s.%s", nspace, name);
6982 case MONO_TOKEN_TYPE_REF: {
6984 guint32 cols [MONO_TYPEREF_SIZE];
6985 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6986 guint tidx = mono_metadata_token_index (type_token);
6989 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6991 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6992 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6993 mono_error_cleanup (&error);
6997 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
6998 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
6999 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7000 if (strlen (nspace) == 0)
7001 return g_strdup_printf ("%s", name);
7003 return g_strdup_printf ("%s.%s", nspace, name);
7006 case MONO_TOKEN_TYPE_SPEC:
7007 return g_strdup_printf ("Typespec 0x%08x", type_token);
7009 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7014 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7017 return g_strdup_printf ("DynamicAssembly %s", image->name);
7019 switch (type_token & 0xff000000){
7020 case MONO_TOKEN_TYPE_DEF:
7021 if (image->assembly)
7022 return mono_stringify_assembly_name (&image->assembly->aname);
7023 else if (image->assembly_name)
7024 return g_strdup (image->assembly_name);
7025 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7026 case MONO_TOKEN_TYPE_REF: {
7028 MonoAssemblyName aname;
7029 guint32 cols [MONO_TYPEREF_SIZE];
7030 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7031 guint32 idx = mono_metadata_token_index (type_token);
7034 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7036 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7037 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7038 mono_error_cleanup (&error);
7041 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7043 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7044 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7045 case MONO_RESOLTION_SCOPE_MODULE:
7047 return g_strdup ("");
7048 case MONO_RESOLTION_SCOPE_MODULEREF:
7050 return g_strdup ("");
7051 case MONO_RESOLTION_SCOPE_TYPEREF:
7053 return g_strdup ("");
7054 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7055 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7056 return mono_stringify_assembly_name (&aname);
7058 g_assert_not_reached ();
7062 case MONO_TOKEN_TYPE_SPEC:
7064 return g_strdup ("");
7066 g_assert_not_reached ();
7073 * mono_class_get_full:
7074 * @image: the image where the class resides
7075 * @type_token: the token for the class
7076 * @context: the generic context used to evaluate generic instantiations in
7078 * Returns: the MonoClass that represents @type_token in @image
7081 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7084 MonoClass *class = NULL;
7086 if (image->dynamic) {
7087 int table = mono_metadata_token_table (type_token);
7089 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7090 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7093 return mono_lookup_dynamic_token (image, type_token, context);
7096 switch (type_token & 0xff000000){
7097 case MONO_TOKEN_TYPE_DEF:
7098 class = mono_class_create_from_typedef (image, type_token, &error);
7099 if (!mono_error_ok (&error)) {
7100 mono_loader_set_error_from_mono_error (&error);
7101 /*FIXME don't swallow the error message*/
7102 mono_error_cleanup (&error);
7106 case MONO_TOKEN_TYPE_REF:
7107 class = mono_class_from_typeref (image, type_token);
7109 case MONO_TOKEN_TYPE_SPEC:
7110 class = mono_class_create_from_typespec (image, type_token, context, &error);
7111 if (!mono_error_ok (&error)) {
7112 /*FIXME don't swallow the error message*/
7113 mono_error_cleanup (&error);
7117 g_warning ("unknown token type %x", type_token & 0xff000000);
7118 g_assert_not_reached ();
7122 char *name = mono_class_name_from_token (image, type_token);
7123 char *assembly = mono_assembly_name_from_token (image, type_token);
7124 mono_loader_set_error_type_load (name, assembly);
7134 * mono_type_get_full:
7135 * @image: the image where the type resides
7136 * @type_token: the token for the type
7137 * @context: the generic context used to evaluate generic instantiations in
7139 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7141 * Returns: the MonoType that represents @type_token in @image
7144 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7147 MonoType *type = NULL;
7148 gboolean inflated = FALSE;
7150 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7152 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7154 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7155 MonoClass *class = mono_class_get_full (image, type_token, context);
7156 return class ? mono_class_get_type (class) : NULL;
7159 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7161 if (!mono_error_ok (&error)) {
7162 /*FIXME don't swalloc the error message.*/
7163 char *name = mono_class_name_from_token (image, type_token);
7164 char *assembly = mono_assembly_name_from_token (image, type_token);
7166 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7168 mono_error_cleanup (&error);
7169 mono_loader_set_error_type_load (name, assembly);
7174 MonoType *tmp = type;
7175 type = mono_class_get_type (mono_class_from_mono_type (type));
7176 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7177 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7178 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7180 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7182 if (type->type != tmp->type)
7185 mono_metadata_free_type (tmp);
7192 mono_class_get (MonoImage *image, guint32 type_token)
7194 return mono_class_get_full (image, type_token, NULL);
7198 * mono_image_init_name_cache:
7200 * Initializes the class name cache stored in image->name_cache.
7202 * LOCKING: Acquires the corresponding image lock.
7205 mono_image_init_name_cache (MonoImage *image)
7207 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7208 guint32 cols [MONO_TYPEDEF_SIZE];
7211 guint32 i, visib, nspace_index;
7212 GHashTable *name_cache2, *nspace_table;
7214 mono_image_lock (image);
7216 if (image->name_cache) {
7217 mono_image_unlock (image);
7221 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7223 if (image->dynamic) {
7224 mono_image_unlock (image);
7228 /* Temporary hash table to avoid lookups in the nspace_table */
7229 name_cache2 = g_hash_table_new (NULL, NULL);
7231 for (i = 1; i <= t->rows; ++i) {
7232 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7233 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7235 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7236 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7238 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7240 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7241 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7243 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7244 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7245 if (!nspace_table) {
7246 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7247 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7248 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7251 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7254 /* Load type names from EXPORTEDTYPES table */
7256 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7257 guint32 cols [MONO_EXP_TYPE_SIZE];
7260 for (i = 0; i < t->rows; ++i) {
7261 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7262 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7263 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7265 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7266 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7267 if (!nspace_table) {
7268 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7269 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7270 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7273 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7277 g_hash_table_destroy (name_cache2);
7278 mono_image_unlock (image);
7281 /*FIXME Only dynamic assemblies should allow this operation.*/
7283 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7284 const char *name, guint32 index)
7286 GHashTable *nspace_table;
7287 GHashTable *name_cache;
7290 mono_image_lock (image);
7292 if (!image->name_cache)
7293 mono_image_init_name_cache (image);
7295 name_cache = image->name_cache;
7296 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7297 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7298 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7301 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7302 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7304 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7306 mono_image_unlock (image);
7315 find_nocase (gpointer key, gpointer value, gpointer user_data)
7317 char *name = (char*)key;
7318 FindUserData *data = (FindUserData*)user_data;
7320 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7321 data->value = value;
7325 * mono_class_from_name_case:
7326 * @image: The MonoImage where the type is looked up in
7327 * @name_space: the type namespace
7328 * @name: the type short name.
7330 * Obtains a MonoClass with a given namespace and a given name which
7331 * is located in the given MonoImage. The namespace and name
7332 * lookups are case insensitive.
7335 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7337 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7338 guint32 cols [MONO_TYPEDEF_SIZE];
7343 if (image->dynamic) {
7345 FindUserData user_data;
7347 mono_image_lock (image);
7349 if (!image->name_cache)
7350 mono_image_init_name_cache (image);
7352 user_data.key = name_space;
7353 user_data.value = NULL;
7354 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7356 if (user_data.value) {
7357 GHashTable *nspace_table = (GHashTable*)user_data.value;
7359 user_data.key = name;
7360 user_data.value = NULL;
7362 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7364 if (user_data.value)
7365 token = GPOINTER_TO_UINT (user_data.value);
7368 mono_image_unlock (image);
7371 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7377 /* add a cache if needed */
7378 for (i = 1; i <= t->rows; ++i) {
7379 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7380 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7382 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7383 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7385 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7387 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7388 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7389 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7390 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7396 return_nested_in (MonoClass *class, char *nested)
7399 char *s = strchr (nested, '/');
7400 gpointer iter = NULL;
7407 while ((found = mono_class_get_nested_types (class, &iter))) {
7408 if (strcmp (found->name, nested) == 0) {
7410 return return_nested_in (found, s);
7418 search_modules (MonoImage *image, const char *name_space, const char *name)
7420 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7421 MonoImage *file_image;
7426 * The EXPORTEDTYPES table only contains public types, so have to search the
7428 * Note: image->modules contains the contents of the MODULEREF table, while
7429 * the real module list is in the FILE table.
7431 for (i = 0; i < file_table->rows; i++) {
7432 guint32 cols [MONO_FILE_SIZE];
7433 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7434 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7437 file_image = mono_image_load_file_for_image (image, i + 1);
7439 class = mono_class_from_name (file_image, name_space, name);
7449 * mono_class_from_name:
7450 * @image: The MonoImage where the type is looked up in
7451 * @name_space: the type namespace
7452 * @name: the type short name.
7454 * Obtains a MonoClass with a given namespace and a given name which
7455 * is located in the given MonoImage.
7457 * To reference nested classes, use the "/" character as a separator.
7458 * For example use "Foo/Bar" to reference the class Bar that is nested
7459 * inside Foo, like this: "class Foo { class Bar {} }".
7462 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7464 GHashTable *nspace_table;
7465 MonoImage *loaded_image;
7472 if ((nested = strchr (name, '/'))) {
7473 int pos = nested - name;
7474 int len = strlen (name);
7477 memcpy (buf, name, len + 1);
7479 nested = buf + pos + 1;
7483 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7484 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7485 gboolean res = get_class_from_name (image, name_space, name, &class);
7488 class = search_modules (image, name_space, name);
7490 return class ? return_nested_in (class, nested) : NULL;
7496 mono_image_lock (image);
7498 if (!image->name_cache)
7499 mono_image_init_name_cache (image);
7501 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7504 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7506 mono_image_unlock (image);
7508 if (!token && image->dynamic && image->modules) {
7509 /* Search modules as well */
7510 for (i = 0; i < image->module_count; ++i) {
7511 MonoImage *module = image->modules [i];
7513 class = mono_class_from_name (module, name_space, name);
7520 class = search_modules (image, name_space, name);
7528 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7529 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7530 guint32 cols [MONO_EXP_TYPE_SIZE];
7533 idx = mono_metadata_token_index (token);
7535 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7537 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7538 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7539 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7542 class = mono_class_from_name (loaded_image, name_space, name);
7544 return return_nested_in (class, nested);
7546 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7547 guint32 assembly_idx;
7549 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7551 mono_assembly_load_reference (image, assembly_idx - 1);
7552 g_assert (image->references [assembly_idx - 1]);
7553 if (image->references [assembly_idx - 1] == (gpointer)-1)
7556 /* FIXME: Cycle detection */
7557 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7559 g_error ("not yet implemented");
7563 token = MONO_TOKEN_TYPE_DEF | token;
7565 class = mono_class_get (image, token);
7567 return return_nested_in (class, nested);
7572 * mono_class_is_subclass_of:
7573 * @klass: class to probe if it is a subclass of another one
7574 * @klassc: the class we suspect is the base class
7575 * @check_interfaces: whether we should perform interface checks
7577 * This method determines whether @klass is a subclass of @klassc.
7579 * If the @check_interfaces flag is set, then if @klassc is an interface
7580 * this method return true if the @klass implements the interface or
7581 * if @klass is an interface, if one of its base classes is @klass.
7583 * If @check_interfaces is false then, then if @klass is not an interface
7584 * then it returns true if the @klass is a subclass of @klassc.
7586 * if @klass is an interface and @klassc is System.Object, then this function
7591 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7592 gboolean check_interfaces)
7594 /*FIXME test for interfaces with variant generic arguments*/
7596 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7597 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7599 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7602 for (i = 0; i < klass->interface_count; i ++) {
7603 MonoClass *ic = klass->interfaces [i];
7608 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7613 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7616 if (klassc == mono_defaults.object_class)
7623 mono_type_is_generic_argument (MonoType *type)
7625 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7629 mono_class_has_variant_generic_params (MonoClass *klass)
7632 MonoGenericContainer *container;
7634 if (!klass->generic_class)
7637 container = klass->generic_class->container_class->generic_container;
7639 for (i = 0; i < container->type_argc; ++i)
7640 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7647 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7649 if (target == candidate)
7652 if (check_for_reference_conv &&
7653 mono_type_is_generic_argument (&target->byval_arg) &&
7654 mono_type_is_generic_argument (&candidate->byval_arg)) {
7655 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7656 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7658 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7661 if (!mono_class_is_assignable_from (target, candidate))
7667 * @container the generic container from the GTD
7668 * @klass: the class to be assigned to
7669 * @oklass: the source class
7671 * Both klass and oklass must be instances of the same generic interface.
7672 * Return true if @klass can be assigned to a @klass variable
7675 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7678 MonoType **klass_argv, **oklass_argv;
7679 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7680 MonoGenericContainer *container = klass_gtd->generic_container;
7682 if (klass == oklass)
7685 /*Viable candidates are instances of the same generic interface*/
7686 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7689 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7690 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7692 for (j = 0; j < container->type_argc; ++j) {
7693 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7694 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7696 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7700 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7701 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7703 if (param1_class != param2_class) {
7704 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7705 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7707 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7708 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7718 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7720 MonoGenericParam *gparam, *ogparam;
7721 MonoGenericParamInfo *tinfo, *cinfo;
7722 MonoClass **candidate_class;
7723 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7726 if (target == candidate)
7728 if (target->byval_arg.type != candidate->byval_arg.type)
7731 gparam = target->byval_arg.data.generic_param;
7732 ogparam = candidate->byval_arg.data.generic_param;
7733 tinfo = mono_generic_param_info (gparam);
7734 cinfo = mono_generic_param_info (ogparam);
7736 class_constraint_satisfied = FALSE;
7737 valuetype_constraint_satisfied = FALSE;
7739 /*candidate must have a super set of target's special constraints*/
7740 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7741 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7743 if (cinfo->constraints) {
7744 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7745 MonoClass *cc = *candidate_class;
7747 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7748 class_constraint_satisfied = TRUE;
7749 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7750 valuetype_constraint_satisfied = TRUE;
7753 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7754 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7756 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7758 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7760 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7761 valuetype_constraint_satisfied)) {
7766 /*candidate type constraints must be a superset of target's*/
7767 if (tinfo->constraints) {
7768 MonoClass **target_class;
7769 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7770 MonoClass *tc = *target_class;
7773 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7774 * check it's constraints since it satisfy the constraint by itself.
7776 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7779 if (!cinfo->constraints)
7782 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7783 MonoClass *cc = *candidate_class;
7785 if (mono_class_is_assignable_from (tc, cc))
7789 * This happens when we have the following:
7791 * Bar<K> where K : IFace
7792 * Foo<T, U> where T : U where U : IFace
7794 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7797 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7798 if (mono_gparam_is_assignable_from (target, cc))
7802 if (!*candidate_class)
7807 /*candidate itself must have a constraint that satisfy target*/
7808 if (cinfo->constraints) {
7809 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7810 MonoClass *cc = *candidate_class;
7811 if (mono_class_is_assignable_from (target, cc))
7819 * mono_class_is_assignable_from:
7820 * @klass: the class to be assigned to
7821 * @oklass: the source class
7823 * Return: true if an instance of object oklass can be assigned to an
7824 * instance of object @klass
7827 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7829 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7831 mono_class_init (klass);
7833 if (!oklass->inited)
7834 mono_class_init (oklass);
7836 if (klass->exception_type || oklass->exception_type)
7839 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7840 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7842 return mono_gparam_is_assignable_from (klass, oklass);
7845 if (MONO_CLASS_IS_INTERFACE (klass)) {
7846 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7847 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7848 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7852 for (i = 0; constraints [i]; ++i) {
7853 if (mono_class_is_assignable_from (klass, constraints [i]))
7861 /* interface_offsets might not be set for dynamic classes */
7862 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7864 * oklass might be a generic type parameter but they have
7865 * interface_offsets set.
7867 return mono_reflection_call_is_assignable_to (oklass, klass);
7868 if (!oklass->interface_bitmap)
7869 /* Happens with generic instances of not-yet created dynamic types */
7871 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7874 if (mono_class_has_variant_generic_params (klass)) {
7877 mono_class_setup_interfaces (oklass, &error);
7878 if (!mono_error_ok (&error)) {
7879 mono_error_cleanup (&error);
7883 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7884 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7885 MonoClass *iface = oklass->interfaces_packed [i];
7887 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7892 } else if (klass->delegate) {
7893 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7895 }else if (klass->rank) {
7896 MonoClass *eclass, *eoclass;
7898 if (oklass->rank != klass->rank)
7901 /* vectors vs. one dimensional arrays */
7902 if (oklass->byval_arg.type != klass->byval_arg.type)
7905 eclass = klass->cast_class;
7906 eoclass = oklass->cast_class;
7909 * a is b does not imply a[] is b[] when a is a valuetype, and
7910 * b is a reference type.
7913 if (eoclass->valuetype) {
7914 if ((eclass == mono_defaults.enum_class) ||
7915 (eclass == mono_defaults.enum_class->parent) ||
7916 (eclass == mono_defaults.object_class))
7920 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7921 } else if (mono_class_is_nullable (klass)) {
7922 if (mono_class_is_nullable (oklass))
7923 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7925 return mono_class_is_assignable_from (klass->cast_class, oklass);
7926 } else if (klass == mono_defaults.object_class)
7929 return mono_class_has_parent (oklass, klass);
7932 /*Check if @oklass is variant compatible with @klass.*/
7934 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7937 MonoType **klass_argv, **oklass_argv;
7938 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7939 MonoGenericContainer *container = klass_gtd->generic_container;
7941 /*Viable candidates are instances of the same generic interface*/
7942 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7945 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7946 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7948 for (j = 0; j < container->type_argc; ++j) {
7949 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7950 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7952 if (param1_class->valuetype != param2_class->valuetype)
7956 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7957 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7959 if (param1_class != param2_class) {
7960 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7961 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7963 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7964 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7972 /*Check if @candidate implements the interface @target*/
7974 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7978 gboolean is_variant = mono_class_has_variant_generic_params (target);
7980 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7981 if (mono_class_is_variant_compatible_slow (target, candidate))
7986 if (candidate == target)
7989 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7990 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7991 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7993 if (tb && tb->interfaces) {
7994 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7995 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7996 MonoClass *iface_class;
7998 /* we can't realize the type here since it can do pretty much anything. */
8001 iface_class = mono_class_from_mono_type (iface->type);
8002 if (iface_class == target)
8004 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8006 if (mono_class_implement_interface_slow (target, iface_class))
8011 /*setup_interfaces don't mono_class_init anything*/
8012 /*FIXME this doesn't handle primitive type arrays.
8013 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8014 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8016 mono_class_setup_interfaces (candidate, &error);
8017 if (!mono_error_ok (&error)) {
8018 mono_error_cleanup (&error);
8022 for (i = 0; i < candidate->interface_count; ++i) {
8023 if (candidate->interfaces [i] == target)
8026 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8029 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8033 candidate = candidate->parent;
8034 } while (candidate);
8040 * Check if @oklass can be assigned to @klass.
8041 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8044 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8046 if (candidate == target)
8048 if (target == mono_defaults.object_class)
8051 if (mono_class_has_parent (candidate, target))
8054 /*If target is not an interface there is no need to check them.*/
8055 if (MONO_CLASS_IS_INTERFACE (target))
8056 return mono_class_implement_interface_slow (target, candidate);
8058 if (target->delegate && mono_class_has_variant_generic_params (target))
8059 return mono_class_is_variant_compatible (target, candidate, FALSE);
8062 MonoClass *eclass, *eoclass;
8064 if (target->rank != candidate->rank)
8067 /* vectors vs. one dimensional arrays */
8068 if (target->byval_arg.type != candidate->byval_arg.type)
8071 eclass = target->cast_class;
8072 eoclass = candidate->cast_class;
8075 * a is b does not imply a[] is b[] when a is a valuetype, and
8076 * b is a reference type.
8079 if (eoclass->valuetype) {
8080 if ((eclass == mono_defaults.enum_class) ||
8081 (eclass == mono_defaults.enum_class->parent) ||
8082 (eclass == mono_defaults.object_class))
8086 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8088 /*FIXME properly handle nullables */
8089 /*FIXME properly handle (M)VAR */
8094 * mono_class_get_cctor:
8095 * @klass: A MonoClass pointer
8097 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8100 mono_class_get_cctor (MonoClass *klass)
8102 MonoCachedClassInfo cached_info;
8104 if (klass->image->dynamic) {
8106 * has_cctor is not set for these classes because mono_class_init () is
8109 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8112 if (!klass->has_cctor)
8115 if (mono_class_get_cached_class_info (klass, &cached_info))
8116 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8118 if (klass->generic_class && !klass->methods)
8119 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8121 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8125 * mono_class_get_finalizer:
8126 * @klass: The MonoClass pointer
8128 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8131 mono_class_get_finalizer (MonoClass *klass)
8133 MonoCachedClassInfo cached_info;
8136 mono_class_init (klass);
8137 if (!mono_class_has_finalizer (klass))
8140 if (mono_class_get_cached_class_info (klass, &cached_info))
8141 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8143 mono_class_setup_vtable (klass);
8144 return klass->vtable [finalize_slot];
8149 * mono_class_needs_cctor_run:
8150 * @klass: the MonoClass pointer
8151 * @caller: a MonoMethod describing the caller
8153 * Determines whenever the class has a static constructor and whenever it
8154 * needs to be called when executing CALLER.
8157 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8161 method = mono_class_get_cctor (klass);
8163 return (method == caller) ? FALSE : TRUE;
8169 * mono_class_array_element_size:
8172 * Returns: the number of bytes an element of type @klass
8173 * uses when stored into an array.
8176 mono_class_array_element_size (MonoClass *klass)
8178 MonoType *type = &klass->byval_arg;
8181 switch (type->type) {
8184 case MONO_TYPE_BOOLEAN:
8188 case MONO_TYPE_CHAR:
8197 case MONO_TYPE_CLASS:
8198 case MONO_TYPE_STRING:
8199 case MONO_TYPE_OBJECT:
8200 case MONO_TYPE_SZARRAY:
8201 case MONO_TYPE_ARRAY:
8203 case MONO_TYPE_MVAR:
8204 return sizeof (gpointer);
8209 case MONO_TYPE_VALUETYPE:
8210 if (type->data.klass->enumtype) {
8211 type = mono_class_enum_basetype (type->data.klass);
8212 klass = klass->element_class;
8215 return mono_class_instance_size (klass) - sizeof (MonoObject);
8216 case MONO_TYPE_GENERICINST:
8217 type = &type->data.generic_class->container_class->byval_arg;
8220 case MONO_TYPE_VOID:
8224 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8230 * mono_array_element_size:
8231 * @ac: pointer to a #MonoArrayClass
8233 * Returns: the size of single array element.
8236 mono_array_element_size (MonoClass *ac)
8238 g_assert (ac->rank);
8239 return ac->sizes.element_size;
8243 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8244 MonoGenericContext *context)
8246 if (image->dynamic) {
8247 MonoClass *tmp_handle_class;
8248 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8250 g_assert (tmp_handle_class);
8252 *handle_class = tmp_handle_class;
8254 if (tmp_handle_class == mono_defaults.typehandle_class)
8255 return &((MonoClass*)obj)->byval_arg;
8260 switch (token & 0xff000000) {
8261 case MONO_TOKEN_TYPE_DEF:
8262 case MONO_TOKEN_TYPE_REF:
8263 case MONO_TOKEN_TYPE_SPEC: {
8266 *handle_class = mono_defaults.typehandle_class;
8267 type = mono_type_get_full (image, token, context);
8270 mono_class_init (mono_class_from_mono_type (type));
8271 /* We return a MonoType* as handle */
8274 case MONO_TOKEN_FIELD_DEF: {
8276 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8280 *handle_class = mono_defaults.fieldhandle_class;
8281 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8284 mono_class_init (class);
8285 return mono_class_get_field (class, token);
8287 case MONO_TOKEN_METHOD_DEF:
8288 case MONO_TOKEN_METHOD_SPEC: {
8290 meth = mono_get_method_full (image, token, NULL, context);
8292 *handle_class = mono_defaults.methodhandle_class;
8295 case MONO_TOKEN_MEMBER_REF: {
8296 guint32 cols [MONO_MEMBERREF_SIZE];
8298 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8299 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8300 mono_metadata_decode_blob_size (sig, &sig);
8301 if (*sig == 0x6) { /* it's a field */
8303 MonoClassField *field;
8304 field = mono_field_from_token (image, token, &klass, context);
8306 *handle_class = mono_defaults.fieldhandle_class;
8310 meth = mono_get_method_full (image, token, NULL, context);
8312 *handle_class = mono_defaults.methodhandle_class;
8317 g_warning ("Unknown token 0x%08x in ldtoken", token);
8324 * This function might need to call runtime functions so it can't be part
8325 * of the metadata library.
8327 static MonoLookupDynamicToken lookup_dynamic = NULL;
8330 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8332 lookup_dynamic = func;
8336 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8338 MonoClass *handle_class;
8340 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8344 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8346 return lookup_dynamic (image, token, valid_token, handle_class, context);
8349 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8352 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8354 get_cached_class_info = func;
8358 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8360 if (!get_cached_class_info)
8363 return get_cached_class_info (klass, res);
8367 mono_install_get_class_from_name (MonoGetClassFromName func)
8369 get_class_from_name = func;
8373 mono_class_get_image (MonoClass *klass)
8375 return klass->image;
8379 * mono_class_get_element_class:
8380 * @klass: the MonoClass to act on
8382 * Returns: the element class of an array or an enumeration.
8385 mono_class_get_element_class (MonoClass *klass)
8387 return klass->element_class;
8391 * mono_class_is_valuetype:
8392 * @klass: the MonoClass to act on
8394 * Returns: true if the MonoClass represents a ValueType.
8397 mono_class_is_valuetype (MonoClass *klass)
8399 return klass->valuetype;
8403 * mono_class_is_enum:
8404 * @klass: the MonoClass to act on
8406 * Returns: true if the MonoClass represents an enumeration.
8409 mono_class_is_enum (MonoClass *klass)
8411 return klass->enumtype;
8415 * mono_class_enum_basetype:
8416 * @klass: the MonoClass to act on
8418 * Returns: the underlying type representation for an enumeration.
8421 mono_class_enum_basetype (MonoClass *klass)
8423 if (klass->element_class == klass)
8424 /* SRE or broken types */
8427 return &klass->element_class->byval_arg;
8431 * mono_class_get_parent
8432 * @klass: the MonoClass to act on
8434 * Returns: the parent class for this class.
8437 mono_class_get_parent (MonoClass *klass)
8439 return klass->parent;
8443 * mono_class_get_nesting_type;
8444 * @klass: the MonoClass to act on
8446 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8449 mono_class_get_nesting_type (MonoClass *klass)
8451 return klass->nested_in;
8455 * mono_class_get_rank:
8456 * @klass: the MonoClass to act on
8458 * Returns: the rank for the array (the number of dimensions).
8461 mono_class_get_rank (MonoClass *klass)
8467 * mono_class_get_flags:
8468 * @klass: the MonoClass to act on
8470 * The type flags from the TypeDef table from the metadata.
8471 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8474 * Returns: the flags from the TypeDef table.
8477 mono_class_get_flags (MonoClass *klass)
8479 return klass->flags;
8483 * mono_class_get_name
8484 * @klass: the MonoClass to act on
8486 * Returns: the name of the class.
8489 mono_class_get_name (MonoClass *klass)
8495 * mono_class_get_namespace:
8496 * @klass: the MonoClass to act on
8498 * Returns: the namespace of the class.
8501 mono_class_get_namespace (MonoClass *klass)
8503 return klass->name_space;
8507 * mono_class_get_type:
8508 * @klass: the MonoClass to act on
8510 * This method returns the internal Type representation for the class.
8512 * Returns: the MonoType from the class.
8515 mono_class_get_type (MonoClass *klass)
8517 return &klass->byval_arg;
8521 * mono_class_get_type_token
8522 * @klass: the MonoClass to act on
8524 * This method returns type token for the class.
8526 * Returns: the type token for the class.
8529 mono_class_get_type_token (MonoClass *klass)
8531 return klass->type_token;
8535 * mono_class_get_byref_type:
8536 * @klass: the MonoClass to act on
8541 mono_class_get_byref_type (MonoClass *klass)
8543 return &klass->this_arg;
8547 * mono_class_num_fields:
8548 * @klass: the MonoClass to act on
8550 * Returns: the number of static and instance fields in the class.
8553 mono_class_num_fields (MonoClass *klass)
8555 return klass->field.count;
8559 * mono_class_num_methods:
8560 * @klass: the MonoClass to act on
8562 * Returns: the number of methods in the class.
8565 mono_class_num_methods (MonoClass *klass)
8567 return klass->method.count;
8571 * mono_class_num_properties
8572 * @klass: the MonoClass to act on
8574 * Returns: the number of properties in the class.
8577 mono_class_num_properties (MonoClass *klass)
8579 mono_class_setup_properties (klass);
8581 return klass->ext->property.count;
8585 * mono_class_num_events:
8586 * @klass: the MonoClass to act on
8588 * Returns: the number of events in the class.
8591 mono_class_num_events (MonoClass *klass)
8593 mono_class_setup_events (klass);
8595 return klass->ext->event.count;
8599 * mono_class_get_fields:
8600 * @klass: the MonoClass to act on
8602 * This routine is an iterator routine for retrieving the fields in a class.
8604 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8605 * iterate over all of the elements. When no more values are
8606 * available, the return value is NULL.
8608 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8611 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8613 MonoClassField* field;
8617 mono_class_setup_fields_locking (klass);
8618 if (klass->exception_type)
8620 /* start from the first */
8621 if (klass->field.count) {
8622 return *iter = &klass->fields [0];
8630 if (field < &klass->fields [klass->field.count]) {
8631 return *iter = field;
8637 * mono_class_get_methods
8638 * @klass: the MonoClass to act on
8640 * This routine is an iterator routine for retrieving the fields in a class.
8642 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8643 * iterate over all of the elements. When no more values are
8644 * available, the return value is NULL.
8646 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8649 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8651 MonoMethod** method;
8655 mono_class_setup_methods (klass);
8658 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8659 * FIXME we should better report this error to the caller
8661 if (!klass->methods)
8663 /* start from the first */
8664 if (klass->method.count) {
8665 *iter = &klass->methods [0];
8666 return klass->methods [0];
8674 if (method < &klass->methods [klass->method.count]) {
8682 * mono_class_get_virtual_methods:
8684 * Iterate over the virtual methods of KLASS.
8686 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8689 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8691 MonoMethod** method;
8694 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8696 mono_class_setup_methods (klass);
8698 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8699 * FIXME we should better report this error to the caller
8701 if (!klass->methods)
8703 /* start from the first */
8704 method = &klass->methods [0];
8709 while (method < &klass->methods [klass->method.count]) {
8710 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8714 if (method < &klass->methods [klass->method.count]) {
8721 /* Search directly in metadata to avoid calling setup_methods () */
8722 MonoMethod *res = NULL;
8728 start_index = GPOINTER_TO_UINT (*iter);
8731 for (i = start_index; i < klass->method.count; ++i) {
8734 /* class->method.first points into the methodptr table */
8735 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8737 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8741 if (i < klass->method.count) {
8742 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8743 /* Add 1 here so the if (*iter) check fails */
8744 *iter = GUINT_TO_POINTER (i + 1);
8753 * mono_class_get_properties:
8754 * @klass: the MonoClass to act on
8756 * This routine is an iterator routine for retrieving the properties in a class.
8758 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8759 * iterate over all of the elements. When no more values are
8760 * available, the return value is NULL.
8762 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8765 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8767 MonoProperty* property;
8771 mono_class_setup_properties (klass);
8772 /* start from the first */
8773 if (klass->ext->property.count) {
8774 return *iter = &klass->ext->properties [0];
8782 if (property < &klass->ext->properties [klass->ext->property.count]) {
8783 return *iter = property;
8789 * mono_class_get_events:
8790 * @klass: the MonoClass to act on
8792 * This routine is an iterator routine for retrieving the properties in a class.
8794 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8795 * iterate over all of the elements. When no more values are
8796 * available, the return value is NULL.
8798 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8801 mono_class_get_events (MonoClass* klass, gpointer *iter)
8807 mono_class_setup_events (klass);
8808 /* start from the first */
8809 if (klass->ext->event.count) {
8810 return *iter = &klass->ext->events [0];
8818 if (event < &klass->ext->events [klass->ext->event.count]) {
8819 return *iter = event;
8825 * mono_class_get_interfaces
8826 * @klass: the MonoClass to act on
8828 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8830 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8831 * iterate over all of the elements. When no more values are
8832 * available, the return value is NULL.
8834 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8837 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8845 mono_class_init (klass);
8846 if (!klass->interfaces_inited) {
8847 mono_class_setup_interfaces (klass, &error);
8848 if (!mono_error_ok (&error)) {
8849 mono_error_cleanup (&error);
8853 /* start from the first */
8854 if (klass->interface_count) {
8855 *iter = &klass->interfaces [0];
8856 return klass->interfaces [0];
8864 if (iface < &klass->interfaces [klass->interface_count]) {
8872 * mono_class_get_nested_types
8873 * @klass: the MonoClass to act on
8875 * This routine is an iterator routine for retrieving the nested types of a class.
8876 * This works only if @klass is non-generic, or a generic type definition.
8878 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8879 * iterate over all of the elements. When no more values are
8880 * available, the return value is NULL.
8882 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8885 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8893 if (!klass->nested_classes_inited) {
8894 if (!klass->type_token)
8895 klass->nested_classes_inited = TRUE;
8896 mono_loader_lock ();
8897 if (!klass->nested_classes_inited) {
8898 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8901 guint32 cols [MONO_NESTED_CLASS_SIZE];
8902 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8903 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8904 if (!mono_error_ok (&error)) {
8905 /*FIXME don't swallow the error message*/
8906 mono_error_cleanup (&error);
8908 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8911 mono_class_alloc_ext (klass);
8912 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8914 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8917 mono_memory_barrier ();
8918 klass->nested_classes_inited = TRUE;
8919 mono_loader_unlock ();
8923 /* start from the first */
8924 if (klass->ext && klass->ext->nested_classes) {
8925 *iter = klass->ext->nested_classes;
8926 return klass->ext->nested_classes->data;
8928 /* no nested types */
8943 * mono_class_is_delegate
8944 * @klass: the MonoClass to act on
8946 * Returns: true if the MonoClass represents a System.Delegate.
8949 mono_class_is_delegate (MonoClass *klass)
8951 return klass->delegate;
8955 * mono_class_implements_interface
8956 * @klass: The MonoClass to act on
8957 * @interface: The interface to check if @klass implements.
8959 * Returns: true if @klass implements @interface.
8962 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
8964 return mono_class_is_assignable_from (iface, klass);
8968 * mono_field_get_name:
8969 * @field: the MonoClassField to act on
8971 * Returns: the name of the field.
8974 mono_field_get_name (MonoClassField *field)
8980 * mono_field_get_type:
8981 * @field: the MonoClassField to act on
8983 * Returns: MonoType of the field.
8986 mono_field_get_type (MonoClassField *field)
8989 MonoType *type = mono_field_get_type_checked (field, &error);
8990 if (!mono_error_ok (&error)) {
8991 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8992 mono_error_cleanup (&error);
8999 * mono_field_get_type_checked:
9000 * @field: the MonoClassField to act on
9001 * @error: used to return any erro found while retrieving @field type
9003 * Returns: MonoType of the field.
9006 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9008 mono_error_init (error);
9010 mono_field_resolve_type (field, error);
9015 * mono_field_get_parent:
9016 * @field: the MonoClassField to act on
9018 * Returns: MonoClass where the field was defined.
9021 mono_field_get_parent (MonoClassField *field)
9023 return field->parent;
9027 * mono_field_get_flags;
9028 * @field: the MonoClassField to act on
9030 * The metadata flags for a field are encoded using the
9031 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9033 * Returns: the flags for the field.
9036 mono_field_get_flags (MonoClassField *field)
9039 return mono_field_resolve_flags (field);
9040 return field->type->attrs;
9044 * mono_field_get_offset;
9045 * @field: the MonoClassField to act on
9047 * Returns: the field offset.
9050 mono_field_get_offset (MonoClassField *field)
9052 return field->offset;
9056 mono_field_get_rva (MonoClassField *field)
9060 MonoClass *klass = field->parent;
9062 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9064 if (!klass->ext || !klass->ext->field_def_values) {
9065 mono_loader_lock ();
9066 mono_class_alloc_ext (klass);
9067 if (!klass->ext->field_def_values)
9068 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9069 mono_loader_unlock ();
9072 field_index = mono_field_get_index (field);
9074 if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
9075 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9077 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9078 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9081 return klass->ext->field_def_values [field_index].data;
9085 * mono_field_get_data;
9086 * @field: the MonoClassField to act on
9088 * Returns: pointer to the metadata constant value or to the field
9089 * data if it has an RVA flag.
9092 mono_field_get_data (MonoClassField *field)
9094 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9095 MonoTypeEnum def_type;
9097 return mono_class_get_field_default_value (field, &def_type);
9098 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9099 return mono_field_get_rva (field);
9106 * mono_property_get_name:
9107 * @prop: the MonoProperty to act on
9109 * Returns: the name of the property
9112 mono_property_get_name (MonoProperty *prop)
9118 * mono_property_get_set_method
9119 * @prop: the MonoProperty to act on.
9121 * Returns: the setter method of the property (A MonoMethod)
9124 mono_property_get_set_method (MonoProperty *prop)
9130 * mono_property_get_get_method
9131 * @prop: the MonoProperty to act on.
9133 * Returns: the setter method of the property (A MonoMethod)
9136 mono_property_get_get_method (MonoProperty *prop)
9142 * mono_property_get_parent:
9143 * @prop: the MonoProperty to act on.
9145 * Returns: the MonoClass where the property was defined.
9148 mono_property_get_parent (MonoProperty *prop)
9150 return prop->parent;
9154 * mono_property_get_flags:
9155 * @prop: the MonoProperty to act on.
9157 * The metadata flags for a property are encoded using the
9158 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9160 * Returns: the flags for the property.
9163 mono_property_get_flags (MonoProperty *prop)
9169 * mono_event_get_name:
9170 * @event: the MonoEvent to act on
9172 * Returns: the name of the event.
9175 mono_event_get_name (MonoEvent *event)
9181 * mono_event_get_add_method:
9182 * @event: The MonoEvent to act on.
9184 * Returns: the @add' method for the event (a MonoMethod).
9187 mono_event_get_add_method (MonoEvent *event)
9193 * mono_event_get_remove_method:
9194 * @event: The MonoEvent to act on.
9196 * Returns: the @remove method for the event (a MonoMethod).
9199 mono_event_get_remove_method (MonoEvent *event)
9201 return event->remove;
9205 * mono_event_get_raise_method:
9206 * @event: The MonoEvent to act on.
9208 * Returns: the @raise method for the event (a MonoMethod).
9211 mono_event_get_raise_method (MonoEvent *event)
9213 return event->raise;
9217 * mono_event_get_parent:
9218 * @event: the MonoEvent to act on.
9220 * Returns: the MonoClass where the event is defined.
9223 mono_event_get_parent (MonoEvent *event)
9225 return event->parent;
9229 * mono_event_get_flags
9230 * @event: the MonoEvent to act on.
9232 * The metadata flags for an event are encoded using the
9233 * EVENT_* constants. See the tabledefs.h file for details.
9235 * Returns: the flags for the event.
9238 mono_event_get_flags (MonoEvent *event)
9240 return event->attrs;
9244 * mono_class_get_method_from_name:
9245 * @klass: where to look for the method
9246 * @name_space: name of the method
9247 * @param_count: number of parameters. -1 for any number.
9249 * Obtains a MonoMethod with a given name and number of parameters.
9250 * It only works if there are no multiple signatures for any given method name.
9253 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9255 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9259 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9261 MonoMethod *res = NULL;
9264 /* Search directly in the metadata to avoid calling setup_methods () */
9265 for (i = 0; i < klass->method.count; ++i) {
9266 guint32 cols [MONO_METHOD_SIZE];
9268 MonoMethodSignature *sig;
9270 /* class->method.first points into the methodptr table */
9271 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9273 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9274 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9275 if (param_count == -1) {
9279 sig = mono_method_signature (method);
9280 if (sig && sig->param_count == param_count) {
9291 * mono_class_get_method_from_name_flags:
9292 * @klass: where to look for the method
9293 * @name_space: name of the method
9294 * @param_count: number of parameters. -1 for any number.
9295 * @flags: flags which must be set in the method
9297 * Obtains a MonoMethod with a given name and number of parameters.
9298 * It only works if there are no multiple signatures for any given method name.
9301 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9303 MonoMethod *res = NULL;
9306 mono_class_init (klass);
9308 if (klass->generic_class && !klass->methods) {
9309 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9311 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9315 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9316 mono_class_setup_methods (klass);
9318 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9319 See mono/tests/array_load_exception.il
9320 FIXME we should better report this error to the caller
9322 if (!klass->methods)
9324 for (i = 0; i < klass->method.count; ++i) {
9325 MonoMethod *method = klass->methods [i];
9327 if (method->name[0] == name [0] &&
9328 !strcmp (name, method->name) &&
9329 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9330 ((method->flags & flags) == flags)) {
9337 res = find_method_in_metadata (klass, name, param_count, flags);
9344 * mono_class_set_failure:
9345 * @klass: class in which the failure was detected
9346 * @ex_type: the kind of exception/error to be thrown (later)
9347 * @ex_data: exception data (specific to each type of exception/error)
9349 * Keep a detected failure informations in the class for later processing.
9350 * Note that only the first failure is kept.
9352 * LOCKING: Acquires the loader lock.
9355 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9357 if (klass->exception_type)
9360 mono_loader_lock ();
9361 klass->exception_type = ex_type;
9363 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9364 mono_loader_unlock ();
9370 * mono_class_get_exception_data:
9372 * Return the exception_data property of KLASS.
9374 * LOCKING: Acquires the loader lock.
9377 mono_class_get_exception_data (MonoClass *klass)
9379 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9383 * mono_classes_init:
9385 * Initialize the resources used by this module.
9388 mono_classes_init (void)
9390 mono_counters_register ("Inflated methods size",
9391 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9392 mono_counters_register ("Inflated classes",
9393 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9394 mono_counters_register ("Inflated classes size",
9395 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9396 mono_counters_register ("MonoClass size",
9397 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9398 mono_counters_register ("MonoClassExt size",
9399 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9403 * mono_classes_cleanup:
9405 * Free the resources used by this module.
9408 mono_classes_cleanup (void)
9410 if (global_interface_bitset)
9411 mono_bitset_free (global_interface_bitset);
9412 global_interface_bitset = NULL;
9416 * mono_class_get_exception_for_failure:
9417 * @klass: class in which the failure was detected
9419 * Return a constructed MonoException than the caller can then throw
9420 * using mono_raise_exception - or NULL if no failure is present (or
9421 * doesn't result in an exception).
9424 mono_class_get_exception_for_failure (MonoClass *klass)
9426 gpointer exception_data = mono_class_get_exception_data (klass);
9428 switch (klass->exception_type) {
9429 #ifndef DISABLE_SECURITY
9430 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9431 MonoDomain *domain = mono_domain_get ();
9432 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9433 MonoMethod *method = exception_data;
9434 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9435 MonoObject *exc = NULL;
9439 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9440 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9441 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9443 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9444 return (MonoException*) exc;
9447 case MONO_EXCEPTION_TYPE_LOAD: {
9450 char *str = mono_type_get_full_name (klass);
9451 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9452 name = mono_string_new (mono_domain_get (), str);
9454 ex = mono_get_exception_type_load (name, astr);
9458 case MONO_EXCEPTION_MISSING_METHOD: {
9459 char *class_name = exception_data;
9460 char *assembly_name = class_name + strlen (class_name) + 1;
9462 return mono_get_exception_missing_method (class_name, assembly_name);
9464 case MONO_EXCEPTION_MISSING_FIELD: {
9465 char *class_name = exception_data;
9466 char *member_name = class_name + strlen (class_name) + 1;
9468 return mono_get_exception_missing_field (class_name, member_name);
9470 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9471 char *msg_format = exception_data;
9472 char *assembly_name = msg_format + strlen (msg_format) + 1;
9473 char *msg = g_strdup_printf (msg_format, assembly_name);
9476 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9482 case MONO_EXCEPTION_BAD_IMAGE: {
9483 return mono_get_exception_bad_image_format (exception_data);
9486 MonoLoaderError *error;
9489 error = mono_loader_get_last_error ();
9491 ex = mono_loader_error_prepare_exception (error);
9495 /* TODO - handle other class related failures */
9502 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9504 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9505 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9507 if (outer_klass == inner_klass)
9509 inner_klass = inner_klass->nested_in;
9510 } while (inner_klass);
9515 mono_class_get_generic_type_definition (MonoClass *klass)
9517 return klass->generic_class ? klass->generic_class->container_class : klass;
9521 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9523 * Generic instantiations are ignored for all super types of @klass.
9525 * Visibility checks ignoring generic instantiations.
9528 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9531 klass = mono_class_get_generic_type_definition (klass);
9532 parent = mono_class_get_generic_type_definition (parent);
9533 mono_class_setup_supertypes (klass);
9535 for (i = 0; i < klass->idepth; ++i) {
9536 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9542 * Subtype can only access parent members with family protection if the site object
9543 * is subclass of Subtype. For example:
9544 * class A { protected int x; }
9546 * void valid_access () {
9550 * void invalid_access () {
9557 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9559 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9562 if (context_klass == NULL)
9564 /*if access_klass is not member_klass context_klass must be type compat*/
9565 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9571 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9574 if (accessing == accessed)
9576 if (!accessed || !accessing)
9579 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9580 * anywhere so untrusted friends are not safe to access platform's code internals */
9581 if (mono_security_core_clr_enabled ()) {
9582 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9586 mono_assembly_load_friends (accessed);
9587 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9588 MonoAssemblyName *friend = tmp->data;
9589 /* Be conservative with checks */
9592 if (strcmp (accessing->aname.name, friend->name))
9594 if (friend->public_key_token [0]) {
9595 if (!accessing->aname.public_key_token [0])
9597 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9606 * If klass is a generic type or if it is derived from a generic type, return the
9607 * MonoClass of the generic definition
9608 * Returns NULL if not found
9611 get_generic_definition_class (MonoClass *klass)
9614 if (klass->generic_class && klass->generic_class->container_class)
9615 return klass->generic_class->container_class;
9616 klass = klass->parent;
9622 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9625 for (i = 0; i < ginst->type_argc; ++i) {
9626 MonoType *type = ginst->type_argv[i];
9627 switch (type->type) {
9628 case MONO_TYPE_SZARRAY:
9629 if (!can_access_type (access_klass, type->data.klass))
9632 case MONO_TYPE_ARRAY:
9633 if (!can_access_type (access_klass, type->data.array->eklass))
9637 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9640 case MONO_TYPE_CLASS:
9641 case MONO_TYPE_VALUETYPE:
9642 case MONO_TYPE_GENERICINST:
9643 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9651 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9655 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9658 if (access_klass->element_class && !access_klass->enumtype)
9659 access_klass = access_klass->element_class;
9661 if (member_klass->element_class && !member_klass->enumtype)
9662 member_klass = member_klass->element_class;
9664 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9666 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9669 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9672 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9675 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9678 /*Non nested type with nested visibility. We just fail it.*/
9679 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9682 switch (access_level) {
9683 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9684 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9686 case TYPE_ATTRIBUTE_PUBLIC:
9689 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9692 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9693 return is_nesting_type (member_klass, access_klass);
9695 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9696 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9698 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9699 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9701 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9702 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9703 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9705 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9706 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9707 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9712 /* FIXME: check visibility of type, too */
9714 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9716 MonoClass *member_generic_def;
9717 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9720 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9721 access_klass->generic_container) &&
9722 (member_generic_def = get_generic_definition_class (member_klass))) {
9723 MonoClass *access_container;
9725 if (access_klass->generic_container)
9726 access_container = access_klass;
9728 access_container = access_klass->generic_class->container_class;
9730 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9734 /* Partition I 8.5.3.2 */
9735 /* the access level values are the same for fields and methods */
9736 switch (access_level) {
9737 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9738 /* same compilation unit */
9739 return access_klass->image == member_klass->image;
9740 case FIELD_ATTRIBUTE_PRIVATE:
9741 return access_klass == member_klass;
9742 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9743 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9744 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9747 case FIELD_ATTRIBUTE_ASSEMBLY:
9748 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9749 case FIELD_ATTRIBUTE_FAMILY:
9750 if (is_valid_family_access (access_klass, member_klass, context_klass))
9753 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9754 if (is_valid_family_access (access_klass, member_klass, context_klass))
9756 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9757 case FIELD_ATTRIBUTE_PUBLIC:
9764 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9766 /* FIXME: check all overlapping fields */
9767 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9769 MonoClass *nested = method->klass->nested_in;
9771 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9774 nested = nested->nested_in;
9781 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9783 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9785 MonoClass *nested = method->klass->nested_in;
9787 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9790 nested = nested->nested_in;
9795 * with generics calls to explicit interface implementations can be expressed
9796 * directly: the method is private, but we must allow it. This may be opening
9797 * a hole or the generics code should handle this differently.
9798 * Maybe just ensure the interface type is public.
9800 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9806 * mono_method_can_access_method_full:
9807 * @method: The caller method
9808 * @called: The called method
9809 * @context_klass: The static type on stack of the owner @called object used
9811 * This function must be used with instance calls, as they have more strict family accessibility.
9812 * It can be used with static methods, but context_klass should be NULL.
9814 * Returns: TRUE if caller have proper visibility and acessibility to @called
9817 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9819 MonoClass *access_class = method->klass;
9820 MonoClass *member_class = called->klass;
9821 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9823 MonoClass *nested = access_class->nested_in;
9825 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9828 nested = nested->nested_in;
9835 can = can_access_type (access_class, member_class);
9837 MonoClass *nested = access_class->nested_in;
9839 can = can_access_type (nested, member_class);
9842 nested = nested->nested_in;
9849 if (called->is_inflated) {
9850 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9851 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9860 * mono_method_can_access_field_full:
9861 * @method: The caller method
9862 * @field: The accessed field
9863 * @context_klass: The static type on stack of the owner @field object used
9865 * This function must be used with instance fields, as they have more strict family accessibility.
9866 * It can be used with static fields, but context_klass should be NULL.
9868 * Returns: TRUE if caller have proper visibility and acessibility to @field
9871 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9873 MonoClass *access_class = method->klass;
9874 MonoClass *member_class = field->parent;
9875 /* FIXME: check all overlapping fields */
9876 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9878 MonoClass *nested = access_class->nested_in;
9880 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9883 nested = nested->nested_in;
9890 can = can_access_type (access_class, member_class);
9892 MonoClass *nested = access_class->nested_in;
9894 can = can_access_type (nested, member_class);
9897 nested = nested->nested_in;
9907 * mono_class_can_access_class:
9908 * @source_class: The source class
9909 * @target_class: The accessed class
9911 * This function returns is @target_class is visible to @source_class
9913 * Returns: TRUE if source have proper visibility and acessibility to target
9916 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9918 return can_access_type (source_class, target_class);
9922 * mono_type_is_valid_enum_basetype:
9923 * @type: The MonoType to check
9925 * Returns: TRUE if the type can be used as the basetype of an enum
9927 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9928 switch (type->type) {
9931 case MONO_TYPE_BOOLEAN:
9934 case MONO_TYPE_CHAR:
9947 * mono_class_is_valid_enum:
9948 * @klass: An enum class to be validated
9950 * This method verify the required properties an enum should have.
9952 * Returns: TRUE if the informed enum class is valid
9954 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9955 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9956 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9958 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9959 MonoClassField * field;
9960 gpointer iter = NULL;
9961 gboolean found_base_field = FALSE;
9963 g_assert (klass->enumtype);
9964 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9965 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9969 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9972 while ((field = mono_class_get_fields (klass, &iter))) {
9973 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9974 if (found_base_field)
9976 found_base_field = TRUE;
9977 if (!mono_type_is_valid_enum_basetype (field->type))
9982 if (!found_base_field)
9985 if (klass->method.count > 0)
9992 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9994 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
9998 * mono_class_setup_interface_id:
10000 * Initializes MonoClass::interface_id if required.
10002 * LOCKING: Acquires the loader lock.
10005 mono_class_setup_interface_id (MonoClass *class)
10007 mono_loader_lock ();
10008 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10009 class->interface_id = mono_get_unique_iid (class);
10010 mono_loader_unlock ();
10014 * mono_class_alloc_ext:
10016 * Allocate klass->ext if not already done.
10017 * LOCKING: Assumes the loader lock is held.
10020 mono_class_alloc_ext (MonoClass *klass)
10023 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10024 class_ext_size += sizeof (MonoClassExt);
10029 * mono_class_setup_interfaces:
10031 * Initialize class->interfaces/interfaces_count.
10032 * LOCKING: Acquires the loader lock.
10033 * This function can fail the type.
10036 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10040 mono_error_init (error);
10042 if (klass->interfaces_inited)
10045 mono_loader_lock ();
10047 if (klass->interfaces_inited) {
10048 mono_loader_unlock ();
10052 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10053 MonoType *args [1];
10055 /* generic IList, ICollection, IEnumerable */
10056 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10057 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
10059 args [0] = &klass->element_class->byval_arg;
10060 klass->interfaces [0] = mono_class_bind_generic_parameters (
10061 mono_defaults.generic_ilist_class, 1, args, FALSE);
10062 if (klass->interface_count > 1)
10063 klass->interfaces [1] = mono_class_bind_generic_parameters (
10064 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10065 } else if (klass->generic_class) {
10066 MonoClass *gklass = klass->generic_class->container_class;
10068 klass->interface_count = gklass->interface_count;
10069 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
10070 for (i = 0; i < klass->interface_count; i++) {
10071 klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10072 if (!mono_error_ok (error)) {
10073 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10074 klass->interfaces = NULL;
10080 mono_memory_barrier ();
10082 klass->interfaces_inited = TRUE;
10084 mono_loader_unlock ();
10088 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10090 MonoClass *class = field->parent;
10091 MonoImage *image = class->image;
10092 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10093 int field_idx = field - class->fields;
10095 mono_error_init (error);
10098 MonoClassField *gfield = >d->fields [field_idx];
10099 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10100 if (!mono_error_ok (error)) {
10101 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10102 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10106 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10107 if (!mono_error_ok (error)) {
10108 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10109 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10114 guint32 cols [MONO_FIELD_SIZE];
10115 MonoGenericContainer *container = NULL;
10116 int idx = class->field.first + field_idx;
10118 /*FIXME, in theory we do not lazy load SRE fields*/
10119 g_assert (!image->dynamic);
10121 if (class->generic_container) {
10122 container = class->generic_container;
10124 container = gtd->generic_container;
10125 g_assert (container);
10128 /* class->field.first and idx points into the fieldptr table */
10129 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10131 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10132 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10133 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10137 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10139 mono_metadata_decode_value (sig, &sig);
10140 /* FIELD signature == 0x06 */
10141 g_assert (*sig == 0x06);
10142 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10144 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10149 mono_field_resolve_flags (MonoClassField *field)
10151 MonoClass *class = field->parent;
10152 MonoImage *image = class->image;
10153 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10154 int field_idx = field - class->fields;
10158 MonoClassField *gfield = >d->fields [field_idx];
10159 return mono_field_get_flags (gfield);
10161 int idx = class->field.first + field_idx;
10163 /*FIXME, in theory we do not lazy load SRE fields*/
10164 g_assert (!image->dynamic);
10166 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10171 * mono_class_setup_basic_field_info:
10172 * @class: The class to initialize
10174 * Initializes the class->fields array of fields.
10175 * Aquires the loader lock.
10178 mono_class_setup_basic_field_info_locking (MonoClass *class)
10180 mono_loader_lock ();
10181 mono_class_setup_basic_field_info (class);
10182 mono_loader_unlock ();
10186 * mono_class_get_fields_lazy:
10187 * @klass: the MonoClass to act on
10189 * This routine is an iterator routine for retrieving the fields in a class.
10190 * Only minimal information about fields are loaded. Accessors must be used
10191 * for all MonoClassField returned.
10193 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10194 * iterate over all of the elements. When no more values are
10195 * available, the return value is NULL.
10197 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10200 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10202 MonoClassField* field;
10206 mono_class_setup_basic_field_info_locking (klass);
10207 if (!klass->fields)
10209 /* start from the first */
10210 if (klass->field.count) {
10211 return *iter = &klass->fields [0];
10219 if (field < &klass->fields [klass->field.count]) {
10220 return *iter = field;
10226 mono_class_full_name (MonoClass *klass)
10228 return mono_type_full_name (&klass->byval_arg);