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 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
176 This is not the observed behavior of existing implementations.
177 The defacto behavior is that it's just a typedef in disguise.
179 /* a typedef in disguise */
180 return mono_class_from_name (image, nspace, name);
181 case MONO_RESOLTION_SCOPE_MODULEREF:
182 module = mono_image_load_module (image, idx);
184 return mono_class_from_name (module, nspace, name);
186 char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
189 human_name = mono_stringify_assembly_name (&image->assembly->aname);
190 mono_loader_set_error_type_load (msg, human_name);
196 case MONO_RESOLTION_SCOPE_TYPEREF: {
197 MonoClass *enclosing;
200 if (idx == mono_metadata_token_index (type_token)) {
201 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token));
205 enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
209 if (enclosing->nested_classes_inited && enclosing->ext) {
210 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
211 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
213 if (strcmp (res->name, name) == 0)
217 /* Don't call mono_class_init as we might've been called by it recursively */
218 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
220 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
221 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
222 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
224 if (strcmp (nname, name) == 0) {
225 MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
226 if (!mono_error_ok (&error)) {
227 mono_loader_set_error_from_mono_error (&error);
228 mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
234 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
237 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
240 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
244 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
245 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
249 if (!image->references || !image->references [idx - 1])
250 mono_assembly_load_reference (image, idx - 1);
251 g_assert (image->references [idx - 1]);
253 /* If the assembly did not load, register this as a type load exception */
254 if (image->references [idx - 1] == REFERENCE_MISSING){
255 MonoAssemblyName aname;
258 mono_assembly_get_assemblyref (image, idx - 1, &aname);
259 human_name = mono_stringify_assembly_name (&aname);
260 mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
266 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
271 mono_image_memdup (MonoImage *image, void *data, guint size)
273 void *res = mono_image_alloc (image, size);
274 memcpy (res, data, size);
278 /* Copy everything mono_metadata_free_array free. */
280 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
283 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
285 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
287 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
289 a = g_memdup (a, sizeof (MonoArrayType));
291 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
293 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
298 /* Copy everything mono_metadata_free_method_signature free. */
300 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
304 sig = mono_metadata_signature_dup_full (image, sig);
306 sig->ret = mono_metadata_type_dup (image, sig->ret);
307 for (i = 0; i < sig->param_count; ++i)
308 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
314 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
316 MonoAssembly *ta = klass->image->assembly;
319 name = mono_stringify_assembly_name (&ta->aname);
320 g_string_append_printf (str, ", %s", name);
325 mono_type_name_check_byref (MonoType *type, GString *str)
328 g_string_append_c (str, '&');
332 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
333 MonoTypeNameFormat format)
337 switch (type->type) {
338 case MONO_TYPE_ARRAY: {
339 int i, rank = type->data.array->rank;
340 MonoTypeNameFormat nested_format;
342 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
343 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
345 mono_type_get_name_recurse (
346 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
347 g_string_append_c (str, '[');
349 g_string_append_c (str, '*');
350 for (i = 1; i < rank; i++)
351 g_string_append_c (str, ',');
352 g_string_append_c (str, ']');
354 mono_type_name_check_byref (type, str);
356 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
357 _mono_type_get_assembly_name (type->data.array->eklass, str);
360 case MONO_TYPE_SZARRAY: {
361 MonoTypeNameFormat nested_format;
363 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
364 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
366 mono_type_get_name_recurse (
367 &type->data.klass->byval_arg, str, FALSE, nested_format);
368 g_string_append (str, "[]");
370 mono_type_name_check_byref (type, str);
372 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
373 _mono_type_get_assembly_name (type->data.klass, str);
376 case MONO_TYPE_PTR: {
377 MonoTypeNameFormat nested_format;
379 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
380 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
382 mono_type_get_name_recurse (
383 type->data.type, str, FALSE, nested_format);
384 g_string_append_c (str, '*');
386 mono_type_name_check_byref (type, str);
388 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
389 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
394 if (!mono_generic_param_info (type->data.generic_param))
395 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
397 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
399 mono_type_name_check_byref (type, str);
403 klass = mono_class_from_mono_type (type);
404 if (klass->nested_in) {
405 mono_type_get_name_recurse (
406 &klass->nested_in->byval_arg, str, TRUE, format);
407 if (format == MONO_TYPE_NAME_FORMAT_IL)
408 g_string_append_c (str, '.');
410 g_string_append_c (str, '+');
411 } else if (*klass->name_space) {
412 g_string_append (str, klass->name_space);
413 g_string_append_c (str, '.');
415 if (format == MONO_TYPE_NAME_FORMAT_IL) {
416 char *s = strchr (klass->name, '`');
417 int len = s ? s - klass->name : strlen (klass->name);
419 g_string_append_len (str, klass->name, len);
421 g_string_append (str, klass->name);
424 if (klass->generic_class) {
425 MonoGenericClass *gclass = klass->generic_class;
426 MonoGenericInst *inst = gclass->context.class_inst;
427 MonoTypeNameFormat nested_format;
430 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
431 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
433 if (format == MONO_TYPE_NAME_FORMAT_IL)
434 g_string_append_c (str, '<');
436 g_string_append_c (str, '[');
437 for (i = 0; i < inst->type_argc; i++) {
438 MonoType *t = inst->type_argv [i];
441 g_string_append_c (str, ',');
442 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
443 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
444 g_string_append_c (str, '[');
445 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
446 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
447 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
448 g_string_append_c (str, ']');
450 if (format == MONO_TYPE_NAME_FORMAT_IL)
451 g_string_append_c (str, '>');
453 g_string_append_c (str, ']');
454 } else if (klass->generic_container &&
455 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
456 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
459 if (format == MONO_TYPE_NAME_FORMAT_IL)
460 g_string_append_c (str, '<');
462 g_string_append_c (str, '[');
463 for (i = 0; i < klass->generic_container->type_argc; i++) {
465 g_string_append_c (str, ',');
466 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
468 if (format == MONO_TYPE_NAME_FORMAT_IL)
469 g_string_append_c (str, '>');
471 g_string_append_c (str, ']');
474 mono_type_name_check_byref (type, str);
476 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
477 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
478 _mono_type_get_assembly_name (klass, str);
484 * mono_type_get_name_full:
486 * @format: the format for the return string.
489 * Returns: the string representation in a number of formats:
491 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
492 * returned in the formatrequired by System.Reflection, this is the
493 * inverse of mono_reflection_parse_type ().
495 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
496 * be used by the IL assembler.
498 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
500 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
503 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
507 result = g_string_new ("");
509 mono_type_get_name_recurse (type, result, FALSE, format);
511 return g_string_free (result, FALSE);
515 * mono_type_get_full_name:
518 * Returns: the string representation for type as required by System.Reflection.
519 * The inverse of mono_reflection_parse_type ().
522 mono_type_get_full_name (MonoClass *class)
524 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
528 * mono_type_get_name:
531 * Returns: the string representation for type as it would be represented in IL code.
534 mono_type_get_name (MonoType *type)
536 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
540 * mono_type_get_underlying_type:
543 * Returns: the MonoType for the underlying integer type if @type
544 * is an enum and byref is false, otherwise the type itself.
547 mono_type_get_underlying_type (MonoType *type)
549 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
550 return mono_class_enum_basetype (type->data.klass);
551 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
552 return mono_class_enum_basetype (type->data.generic_class->container_class);
557 * mono_class_is_open_constructed_type:
560 * Returns TRUE if type represents a generics open constructed type.
561 * IOW, not all type parameters required for the instantiation have
562 * been provided or it's a generic type definition.
564 * An open constructed type means it's a non realizable type. Not to
565 * be mixed up with an abstract type - we can't cast or dispatch to
566 * an open type, for example.
569 mono_class_is_open_constructed_type (MonoType *t)
575 case MONO_TYPE_SZARRAY:
576 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
577 case MONO_TYPE_ARRAY:
578 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
580 return mono_class_is_open_constructed_type (t->data.type);
581 case MONO_TYPE_GENERICINST:
582 return t->data.generic_class->context.class_inst->is_open;
583 case MONO_TYPE_CLASS:
584 case MONO_TYPE_VALUETYPE:
585 return t->data.klass->generic_container != NULL;
592 This is a simple function to catch the most common bad instances of generic types.
593 Specially those that might lead to further failures in the runtime.
596 is_valid_generic_argument (MonoType *type)
598 switch (type->type) {
600 //case MONO_TYPE_TYPEDBYREF:
607 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
609 mono_error_init (error);
611 switch (type->type) {
612 case MONO_TYPE_MVAR: {
614 int num = mono_type_get_generic_param_num (type);
615 MonoGenericInst *inst = context->method_inst;
616 if (!inst || !inst->type_argv)
618 if (num >= inst->type_argc) {
619 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
620 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
621 num, info ? info->name : "", inst->type_argc);
625 if (!is_valid_generic_argument (inst->type_argv [num])) {
626 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
627 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
628 num, info ? info->name : "", inst->type_argv [num]->type);
632 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
633 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
634 * ->byref and ->attrs from @type are propagated to the returned type.
636 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
637 nt->byref = type->byref;
638 nt->attrs = type->attrs;
641 case MONO_TYPE_VAR: {
643 int num = mono_type_get_generic_param_num (type);
644 MonoGenericInst *inst = context->class_inst;
647 if (num >= inst->type_argc) {
648 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
649 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
650 num, info ? info->name : "", inst->type_argc);
653 if (!is_valid_generic_argument (inst->type_argv [num])) {
654 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
655 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
656 num, info ? info->name : "", inst->type_argv [num]->type);
659 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
660 nt->byref = type->byref;
661 nt->attrs = type->attrs;
664 case MONO_TYPE_SZARRAY: {
665 MonoClass *eclass = type->data.klass;
666 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
667 if (!inflated || !mono_error_ok (error))
669 nt = mono_metadata_type_dup (image, type);
670 nt->data.klass = mono_class_from_mono_type (inflated);
671 mono_metadata_free_type (inflated);
674 case MONO_TYPE_ARRAY: {
675 MonoClass *eclass = type->data.array->eklass;
676 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
677 if (!inflated || !mono_error_ok (error))
679 nt = mono_metadata_type_dup (image, type);
680 nt->data.array->eklass = mono_class_from_mono_type (inflated);
681 mono_metadata_free_type (inflated);
684 case MONO_TYPE_GENERICINST: {
685 MonoGenericClass *gclass = type->data.generic_class;
686 MonoGenericInst *inst;
688 if (!gclass->context.class_inst->is_open)
691 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
692 if (!mono_error_ok (error))
694 if (inst != gclass->context.class_inst)
695 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
697 if (gclass == type->data.generic_class)
700 nt = mono_metadata_type_dup (image, type);
701 nt->data.generic_class = gclass;
704 case MONO_TYPE_CLASS:
705 case MONO_TYPE_VALUETYPE: {
706 MonoClass *klass = type->data.klass;
707 MonoGenericContainer *container = klass->generic_container;
708 MonoGenericInst *inst;
709 MonoGenericClass *gclass = NULL;
715 /* We can't use context->class_inst directly, since it can have more elements */
716 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
717 if (!mono_error_ok (error))
719 if (inst == container->context.class_inst)
722 gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
724 nt = mono_metadata_type_dup (image, type);
725 nt->type = MONO_TYPE_GENERICINST;
726 nt->data.generic_class = gclass;
736 mono_generic_class_get_context (MonoGenericClass *gclass)
738 return &gclass->context;
742 mono_class_get_context (MonoClass *class)
744 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
748 * mono_class_get_generic_container:
750 * Return the generic container of KLASS which should be a generic type definition.
752 MonoGenericContainer*
753 mono_class_get_generic_container (MonoClass *klass)
755 g_assert (klass->is_generic);
757 return klass->generic_container;
761 * mono_class_get_generic_class:
763 * Return the MonoGenericClass of KLASS, which should be a generic instance.
766 mono_class_get_generic_class (MonoClass *klass)
768 g_assert (klass->is_inflated);
770 return klass->generic_class;
774 * mono_class_inflate_generic_type_with_mempool:
775 * @mempool: a mempool
777 * @context: a generics context
778 * @error: error context
780 * The same as mono_class_inflate_generic_type, but allocates the MonoType
781 * from mempool if it is non-NULL. If it is NULL, the MonoType is
782 * allocated on the heap and is owned by the caller.
783 * The returned type can potentially be the same as TYPE, so it should not be
784 * modified by the caller, and it should be freed using mono_metadata_free_type ().
787 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
789 MonoType *inflated = NULL;
790 mono_error_init (error);
793 inflated = inflate_generic_type (image, type, context, error);
794 if (!mono_error_ok (error))
798 MonoType *shared = mono_metadata_get_shared_type (type);
803 return mono_metadata_type_dup (image, type);
807 mono_stats.inflated_type_count++;
812 * mono_class_inflate_generic_type:
814 * @context: a generics context
816 * If @type is a generic type and @context is not NULL, instantiate it using the
817 * generics context @context.
819 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
820 * on the heap and is owned by the caller. Returns NULL on error.
822 * @deprecated Please use mono_class_inflate_generic_type_checked instead
825 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
829 result = mono_class_inflate_generic_type_checked (type, context, &error);
831 if (!mono_error_ok (&error)) {
832 mono_error_cleanup (&error);
839 * mono_class_inflate_generic_type:
841 * @context: a generics context
842 * @error: error context to use
844 * If @type is a generic type and @context is not NULL, instantiate it using the
845 * generics context @context.
847 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
848 * on the heap and is owned by the caller.
851 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
853 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
857 * mono_class_inflate_generic_type_no_copy:
859 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
863 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
865 MonoType *inflated = NULL;
867 mono_error_init (error);
869 inflated = inflate_generic_type (image, type, context, error);
870 if (!mono_error_ok (error))
877 mono_stats.inflated_type_count++;
882 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
887 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
888 if (!mono_error_ok (error))
891 res = mono_class_from_mono_type (inflated);
892 mono_metadata_free_type (inflated);
897 * mono_class_inflate_generic_class:
899 * Inflate the class GKLASS with CONTEXT.
902 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
907 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
908 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
915 static MonoGenericContext
916 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
918 MonoGenericInst *class_inst = NULL;
919 MonoGenericInst *method_inst = NULL;
920 MonoGenericContext res = { NULL, NULL };
922 mono_error_init (error);
924 if (context->class_inst) {
925 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
926 if (!mono_error_ok (error))
930 if (context->method_inst) {
931 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
932 if (!mono_error_ok (error))
936 res.class_inst = class_inst;
937 res.method_inst = method_inst;
943 * mono_class_inflate_generic_method:
944 * @method: a generic method
945 * @context: a generics context
947 * Instantiate the generic method @method using the generics context @context.
949 * Returns: the new instantiated method
952 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
954 return mono_class_inflate_generic_method_full (method, NULL, context);
958 * mono_class_inflate_generic_method_full:
960 * Instantiate method @method with the generic context @context.
961 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
962 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
965 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
968 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
969 if (!mono_error_ok (&error))
970 /*FIXME do proper error handling - on this case, kill this function. */
971 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
977 * mono_class_inflate_generic_method_full_checked:
978 * Same as mono_class_inflate_generic_method_full but return failure using @error.
981 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
984 MonoMethodInflated *iresult, *cached;
985 MonoMethodSignature *sig;
986 MonoGenericContext tmp_context;
987 gboolean is_mb_open = FALSE;
989 mono_error_init (error);
991 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
992 while (method->is_inflated) {
993 MonoGenericContext *method_context = mono_method_get_context (method);
994 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
996 tmp_context = inflate_generic_context (method_context, context, error);
997 if (!mono_error_ok (error))
999 context = &tmp_context;
1001 if (mono_metadata_generic_context_equal (method_context, context))
1004 method = imethod->declaring;
1008 * A method only needs to be inflated if the context has argument for which it is
1011 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1012 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1015 if (!((method->is_generic && context->method_inst) ||
1016 (method->klass->generic_container && context->class_inst)))
1020 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1021 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1022 * This is opposite to the way non-SRE MethodInfos behave.
1024 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1026 * void Example<T> () {
1030 * In Example, the method token must be encoded as: "void Example<!!0>()"
1032 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1033 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1035 * On the other hand, inflating a non-SRE generic method with its own arguments should
1036 * return itself. For example:
1038 * MethodInfo m = ... //m is a generic method definition
1039 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1042 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1043 * what happens with regular methods.
1045 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1046 * everything should behave like a regular type or method.
1049 is_mb_open = method->is_generic &&
1050 method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1051 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1053 iresult = g_new0 (MonoMethodInflated, 1);
1054 iresult->context = *context;
1055 iresult->declaring = method;
1056 iresult->method.method.is_mb_open = is_mb_open;
1058 if (!context->method_inst && method->is_generic)
1059 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1061 if (!context->class_inst) {
1062 g_assert (!iresult->declaring->klass->generic_class);
1063 if (iresult->declaring->klass->generic_container)
1064 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1065 else if (iresult->declaring->klass->generic_class)
1066 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1069 mono_loader_lock ();
1070 cached = mono_method_inflated_lookup (iresult, FALSE);
1072 mono_loader_unlock ();
1074 return (MonoMethod*)cached;
1077 mono_stats.inflated_method_count++;
1079 inflated_methods_size += sizeof (MonoMethodInflated);
1081 sig = mono_method_signature (method);
1083 char *name = mono_type_get_full_name (method->klass);
1084 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1090 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1092 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1095 result = (MonoMethod *) iresult;
1096 result->is_inflated = TRUE;
1097 result->is_generic = FALSE;
1098 result->sre_method = FALSE;
1099 result->signature = NULL;
1100 result->is_mb_open = is_mb_open;
1102 if (!context->method_inst) {
1103 /* Set the generic_container of the result to the generic_container of method */
1104 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1106 if (generic_container) {
1107 result->is_generic = 1;
1108 mono_method_set_generic_container (result, generic_container);
1112 if (!klass_hint || !klass_hint->generic_class ||
1113 klass_hint->generic_class->container_class != method->klass ||
1114 klass_hint->generic_class->context.class_inst != context->class_inst)
1117 if (method->klass->generic_container)
1118 result->klass = klass_hint;
1120 if (!result->klass) {
1121 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1122 if (!mono_error_ok (error))
1125 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1127 mono_metadata_free_type (inflated);
1131 * FIXME: This should hold, but it doesn't:
1133 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1134 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1135 * g_assert (result->is_generic);
1138 * Fixing this here causes other things to break, hence a very
1139 * ugly hack in mini-trampolines.c - see
1140 * is_generic_method_definition().
1143 mono_method_inflated_lookup (iresult, TRUE);
1144 mono_loader_unlock ();
1148 mono_loader_unlock ();
1154 * mono_get_inflated_method:
1156 * Obsolete. We keep it around since it's mentioned in the public API.
1159 mono_get_inflated_method (MonoMethod *method)
1165 * mono_method_get_context_general:
1167 * @uninflated: handle uninflated methods?
1169 * Returns the generic context of a method or NULL if it doesn't have
1170 * one. For an inflated method that's the context stored in the
1171 * method. Otherwise it's in the method's generic container or in the
1172 * generic container of the method's class.
1175 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1177 if (method->is_inflated) {
1178 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1179 return &imethod->context;
1183 if (method->is_generic)
1184 return &(mono_method_get_generic_container (method)->context);
1185 if (method->klass->generic_container)
1186 return &method->klass->generic_container->context;
1191 * mono_method_get_context:
1194 * Returns the generic context for method if it's inflated, otherwise
1198 mono_method_get_context (MonoMethod *method)
1200 return mono_method_get_context_general (method, FALSE);
1204 * mono_method_get_generic_container:
1206 * Returns the generic container of METHOD, which should be a generic method definition.
1207 * Returns NULL if METHOD is not a generic method definition.
1208 * LOCKING: Acquires the loader lock.
1210 MonoGenericContainer*
1211 mono_method_get_generic_container (MonoMethod *method)
1213 MonoGenericContainer *container;
1215 if (!method->is_generic)
1218 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1219 g_assert (container);
1225 * mono_method_set_generic_container:
1227 * Sets the generic container of METHOD to CONTAINER.
1228 * LOCKING: Acquires the loader lock.
1231 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1233 g_assert (method->is_generic);
1235 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1239 * mono_class_find_enum_basetype:
1240 * @class: The enum class
1242 * Determine the basetype of an enum by iterating through its fields. We do this
1243 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1246 mono_class_find_enum_basetype (MonoClass *class)
1248 MonoGenericContainer *container = NULL;
1249 MonoImage *m = class->image;
1250 const int top = class->field.count;
1253 g_assert (class->enumtype);
1255 if (class->generic_container)
1256 container = class->generic_container;
1257 else if (class->generic_class) {
1258 MonoClass *gklass = class->generic_class->container_class;
1260 container = gklass->generic_container;
1261 g_assert (container);
1265 * Fetch all the field information.
1267 for (i = 0; i < top; i++){
1269 guint32 cols [MONO_FIELD_SIZE];
1270 int idx = class->field.first + i;
1273 /* class->field.first and idx points into the fieldptr table */
1274 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1276 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1279 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1282 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1283 mono_metadata_decode_value (sig, &sig);
1284 /* FIELD signature == 0x06 */
1288 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1291 if (class->generic_class) {
1292 //FIXME do we leak here?
1293 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1294 ftype->attrs = cols [MONO_FIELD_FLAGS];
1304 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1307 mono_type_has_exceptions (MonoType *type)
1309 switch (type->type) {
1310 case MONO_TYPE_CLASS:
1311 case MONO_TYPE_VALUETYPE:
1312 case MONO_TYPE_SZARRAY:
1313 return type->data.klass->exception_type;
1314 case MONO_TYPE_ARRAY:
1315 return type->data.array->eklass->exception_type;
1316 case MONO_TYPE_GENERICINST:
1317 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1325 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1329 mono_class_alloc (MonoClass *class, int size)
1331 if (class->generic_class)
1332 return mono_image_set_alloc (class->generic_class->owner, size);
1334 return mono_image_alloc (class->image, size);
1338 mono_class_alloc0 (MonoClass *class, int size)
1342 res = mono_class_alloc (class, size);
1343 memset (res, 0, size);
1347 #define mono_class_new0(class,struct_type, n_structs) \
1348 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1351 * mono_class_setup_basic_field_info:
1352 * @class: The class to initialize
1354 * Initializes the class->fields.
1355 * LOCKING: Assumes the loader lock is held.
1358 mono_class_setup_basic_field_info (MonoClass *class)
1360 MonoClassField *field;
1368 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1369 image = class->image;
1370 top = class->field.count;
1372 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1374 * This happens when a generic instance of an unfinished generic typebuilder
1375 * is used as an element type for creating an array type. We can't initialize
1376 * the fields of this class using the fields of gklass, since gklass is not
1377 * finished yet, fields could be added to it later.
1383 mono_class_setup_basic_field_info (gtd);
1385 top = gtd->field.count;
1386 class->field.first = gtd->field.first;
1387 class->field.count = gtd->field.count;
1390 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1393 * Fetch all the field information.
1395 for (i = 0; i < top; i++){
1396 field = &class->fields [i];
1397 field->parent = class;
1400 field->name = mono_field_get_name (>d->fields [i]);
1402 int idx = class->field.first + i;
1403 /* class->field.first and idx points into the fieldptr table */
1404 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1405 /* The name is needed for fieldrefs */
1406 field->name = mono_metadata_string_heap (image, name_idx);
1412 * mono_class_setup_fields:
1413 * @class: The class to initialize
1415 * Initializes the class->fields.
1416 * LOCKING: Assumes the loader lock is held.
1419 mono_class_setup_fields (MonoClass *class)
1422 MonoImage *m = class->image;
1424 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1425 int i, blittable = TRUE;
1426 guint32 real_size = 0;
1427 guint32 packing_size = 0;
1428 gboolean explicit_size;
1429 MonoClassField *field;
1430 MonoGenericContainer *container = NULL;
1431 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1434 * FIXME: We have a race condition here. It's possible that this function returns
1435 * to its caller with `instance_size` set to `0` instead of the actual size. This
1436 * is not a problem when the function is called recursively on the same class,
1437 * because the size will be initialized by the outer invocation. What follows is a
1438 * description of how it can occur in other cases, too. There it is a problem,
1439 * because it can lead to the GC being asked to allocate an object of size `0`,
1440 * which SGen chokes on. The race condition is triggered infrequently by
1441 * `tests/sgen-suspend.cs`.
1443 * This function is called for a class whenever one of its subclasses is inited.
1444 * For example, it's called for every subclass of Object. What it does is this:
1446 * if (class->setup_fields_called)
1449 * class->instance_size = 0;
1451 * class->setup_fields_called = 1;
1452 * ... critical point
1453 * class->instance_size = actual_instance_size;
1455 * The last two steps are sometimes reversed, but that only changes the way in which
1456 * the race condition works.
1458 * Assume thread A goes through this function and makes it to the critical point.
1459 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1460 * immediately, but `instance_size` is incorrect.
1462 * The other case looks like this:
1464 * if (class->setup_fields_called)
1466 * ... critical point X
1467 * class->instance_size = 0;
1468 * ... critical point Y
1469 * class->instance_size = actual_instance_size;
1471 * class->setup_fields_called = 1;
1473 * Assume thread A goes through the function and makes it to critical point X. Now
1474 * thread B runs through the whole of the function, returning, assuming
1475 * `instance_size` is set. At that point thread A gets to run and makes it to
1476 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1479 if (class->setup_fields_called)
1482 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1484 * This happens when a generic instance of an unfinished generic typebuilder
1485 * is used as an element type for creating an array type. We can't initialize
1486 * the fields of this class using the fields of gklass, since gklass is not
1487 * finished yet, fields could be added to it later.
1492 mono_class_setup_basic_field_info (class);
1493 top = class->field.count;
1496 mono_class_setup_fields (gtd);
1497 if (gtd->exception_type) {
1498 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1503 class->instance_size = 0;
1505 class->sizes.class_size = 0;
1507 if (class->parent) {
1508 /* For generic instances, class->parent might not have been initialized */
1509 mono_class_init (class->parent);
1510 if (!class->parent->size_inited) {
1511 mono_class_setup_fields (class->parent);
1512 if (class->parent->exception_type) {
1513 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1517 class->instance_size += class->parent->instance_size;
1518 class->min_align = class->parent->min_align;
1519 /* we use |= since it may have been set already */
1520 class->has_references |= class->parent->has_references;
1521 blittable = class->parent->blittable;
1523 class->instance_size = sizeof (MonoObject);
1524 class->min_align = 1;
1527 /* We can't really enable 16 bytes alignment until the GC supports it.
1528 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1529 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1530 Bug #506144 is an example of this issue.
1532 if (class->simd_type)
1533 class->min_align = 16;
1535 /* Get the real size */
1536 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1538 if (explicit_size) {
1539 if ((packing_size & 0xfffffff0) != 0) {
1540 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1541 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1544 class->packing_size = packing_size;
1545 real_size += class->instance_size;
1549 if (explicit_size && real_size) {
1550 class->instance_size = MAX (real_size, class->instance_size);
1552 class->blittable = blittable;
1553 mono_memory_barrier ();
1554 class->size_inited = 1;
1555 class->fields_inited = 1;
1556 class->setup_fields_called = 1;
1560 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1563 /* Prevent infinite loops if the class references itself */
1564 class->setup_fields_called = 1;
1566 if (class->generic_container) {
1567 container = class->generic_container;
1569 container = gtd->generic_container;
1570 g_assert (container);
1574 * Fetch all the field information.
1576 for (i = 0; i < top; i++){
1577 int idx = class->field.first + i;
1578 field = &class->fields [i];
1580 field->parent = class;
1583 mono_field_resolve_type (field, &error);
1584 if (!mono_error_ok (&error)) {
1585 /*mono_field_resolve_type already failed class*/
1586 mono_error_cleanup (&error);
1590 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1591 g_assert (field->type);
1594 if (mono_field_is_deleted (field))
1597 MonoClassField *gfield = >d->fields [i];
1598 field->offset = gfield->offset;
1600 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1602 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1603 field->offset = offset;
1605 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1606 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1609 if (field->offset < -1) { /*-1 is used to encode special static fields */
1610 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1616 /* Only do these checks if we still think this type is blittable */
1617 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1618 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1621 MonoClass *field_class = mono_class_from_mono_type (field->type);
1623 mono_class_setup_fields (field_class);
1624 if (field_class->exception_type) {
1625 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1629 if (!field_class || !field_class->blittable)
1634 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1635 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1636 blittable = class->element_class->blittable;
1639 if (mono_type_has_exceptions (field->type)) {
1640 char *class_name = mono_type_get_full_name (class);
1641 char *type_name = mono_type_full_name (field->type);
1643 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1644 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1645 g_free (class_name);
1649 /* The def_value of fields is compute lazily during vtable creation */
1652 if (class == mono_defaults.string_class)
1655 class->blittable = blittable;
1657 if (class->enumtype && !mono_class_enum_basetype (class)) {
1658 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1661 if (explicit_size && real_size) {
1662 class->instance_size = MAX (real_size, class->instance_size);
1665 if (class->exception_type)
1667 mono_class_layout_fields (class);
1669 /*valuetypes can't be neither bigger than 1Mb or empty. */
1670 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1671 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1673 mono_memory_barrier ();
1674 class->fields_inited = 1;
1678 * mono_class_setup_fields_locking:
1679 * @class: The class to initialize
1681 * Initializes the class->fields array of fields.
1682 * Aquires the loader lock.
1685 mono_class_setup_fields_locking (MonoClass *class)
1687 /* This can be checked without locks */
1688 if (class->fields_inited)
1690 mono_loader_lock ();
1691 mono_class_setup_fields (class);
1692 mono_loader_unlock ();
1696 * mono_class_has_references:
1698 * Returns whenever @klass->has_references is set, initializing it if needed.
1699 * Aquires the loader lock.
1702 mono_class_has_references (MonoClass *klass)
1704 if (klass->init_pending) {
1705 /* Be conservative */
1708 mono_class_init (klass);
1710 return klass->has_references;
1715 * mono_type_get_basic_type_from_generic:
1718 * Returns a closed type corresponding to the possibly open type
1722 mono_type_get_basic_type_from_generic (MonoType *type)
1724 /* When we do generic sharing we let type variables stand for reference types. */
1725 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1726 return &mono_defaults.object_class->byval_arg;
1731 * mono_class_layout_fields:
1734 * Compute the placement of fields inside an object or struct, according to
1735 * the layout rules and set the following fields in @class:
1736 * - has_references (if the class contains instance references firled or structs that contain references)
1737 * - has_static_refs (same, but for static fields)
1738 * - instance_size (size of the object in memory)
1739 * - class_size (size needed for the static fields)
1740 * - size_inited (flag set when the instance_size is set)
1742 * LOCKING: this is supposed to be called with the loader lock held.
1745 mono_class_layout_fields (MonoClass *class)
1748 const int top = class->field.count;
1749 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1750 guint32 pass, passes, real_size;
1751 gboolean gc_aware_layout = FALSE;
1752 MonoClassField *field;
1755 * When we do generic sharing we need to have layout
1756 * information for open generic classes (either with a generic
1757 * context containing type variables or with a generic
1758 * container), so we don't return in that case anymore.
1762 * Enable GC aware auto layout: in this mode, reference
1763 * fields are grouped together inside objects, increasing collector
1765 * Requires that all classes whose layout is known to native code be annotated
1766 * with [StructLayout (LayoutKind.Sequential)]
1767 * Value types have gc_aware_layout disabled by default, as per
1768 * what the default is for other runtimes.
1770 /* corlib is missing [StructLayout] directives in many places */
1771 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1772 if (!class->valuetype)
1773 gc_aware_layout = TRUE;
1776 /* Compute klass->has_references */
1778 * Process non-static fields first, since static fields might recursively
1779 * refer to the class itself.
1781 for (i = 0; i < top; i++) {
1784 field = &class->fields [i];
1786 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1787 ftype = mono_type_get_underlying_type (field->type);
1788 ftype = mono_type_get_basic_type_from_generic (ftype);
1789 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1790 class->has_references = TRUE;
1794 for (i = 0; i < top; i++) {
1797 field = &class->fields [i];
1799 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1800 ftype = mono_type_get_underlying_type (field->type);
1801 ftype = mono_type_get_basic_type_from_generic (ftype);
1802 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1803 class->has_static_refs = TRUE;
1807 for (i = 0; i < top; i++) {
1810 field = &class->fields [i];
1812 ftype = mono_type_get_underlying_type (field->type);
1813 ftype = mono_type_get_basic_type_from_generic (ftype);
1814 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1815 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1816 class->has_static_refs = TRUE;
1818 class->has_references = TRUE;
1823 * Compute field layout and total size (not considering static fields)
1827 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1828 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1830 if (gc_aware_layout)
1835 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1838 if (class->parent) {
1839 mono_class_setup_fields (class->parent);
1840 if (class->parent->exception_type) {
1841 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1844 real_size = class->parent->instance_size;
1846 real_size = sizeof (MonoObject);
1849 for (pass = 0; pass < passes; ++pass) {
1850 for (i = 0; i < top; i++){
1855 field = &class->fields [i];
1857 if (mono_field_is_deleted (field))
1859 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1862 ftype = mono_type_get_underlying_type (field->type);
1863 ftype = mono_type_get_basic_type_from_generic (ftype);
1864 if (gc_aware_layout) {
1865 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1874 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1875 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1876 /* This field is a hack inserted by MCS to empty structures */
1880 size = mono_type_size (field->type, &align);
1882 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1883 align = class->packing_size ? MIN (class->packing_size, align): align;
1884 /* if the field has managed references, we need to force-align it
1887 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1888 align = MAX (align, sizeof (gpointer));
1890 class->min_align = MAX (align, class->min_align);
1891 field->offset = real_size;
1893 field->offset += align - 1;
1894 field->offset &= ~(align - 1);
1896 /*TypeBuilders produce all sort of weird things*/
1897 g_assert (class->image->dynamic || field->offset > 0);
1898 real_size = field->offset + size;
1901 class->instance_size = MAX (real_size, class->instance_size);
1903 if (class->instance_size & (class->min_align - 1)) {
1904 class->instance_size += class->min_align - 1;
1905 class->instance_size &= ~(class->min_align - 1);
1909 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1911 for (i = 0; i < top; i++) {
1916 field = &class->fields [i];
1919 * There must be info about all the fields in a type if it
1920 * uses explicit layout.
1923 if (mono_field_is_deleted (field))
1925 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1928 size = mono_type_size (field->type, &align);
1929 align = class->packing_size ? MIN (class->packing_size, align): align;
1930 class->min_align = MAX (align, class->min_align);
1933 * When we get here, field->offset is already set by the
1934 * loader (for either runtime fields or fields loaded from metadata).
1935 * The offset is from the start of the object: this works for both
1936 * classes and valuetypes.
1938 field->offset += sizeof (MonoObject);
1939 ftype = mono_type_get_underlying_type (field->type);
1940 ftype = mono_type_get_basic_type_from_generic (ftype);
1941 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1942 if (field->offset % sizeof (gpointer)) {
1943 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1950 real_size = MAX (real_size, size + field->offset);
1952 class->instance_size = MAX (real_size, class->instance_size);
1953 if (class->instance_size & (class->min_align - 1)) {
1954 class->instance_size += class->min_align - 1;
1955 class->instance_size &= ~(class->min_align - 1);
1960 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1962 * For small structs, set min_align to at least the struct size to improve
1963 * performance, and since the JIT memset/memcpy code assumes this and generates
1964 * unaligned accesses otherwise. See #78990 for a testcase.
1966 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1967 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1970 mono_memory_barrier ();
1971 class->size_inited = 1;
1974 * Compute static field layout and size
1976 for (i = 0; i < top; i++){
1980 field = &class->fields [i];
1982 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1984 if (mono_field_is_deleted (field))
1987 if (mono_type_has_exceptions (field->type)) {
1988 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1992 size = mono_type_size (field->type, &align);
1993 field->offset = class->sizes.class_size;
1994 /*align is always non-zero here*/
1995 field->offset += align - 1;
1996 field->offset &= ~(align - 1);
1997 class->sizes.class_size = field->offset + size;
2002 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2006 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2007 method->klass = class;
2008 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2009 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2010 method->signature = sig;
2011 method->name = name;
2014 if (name [0] == '.') {
2015 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2017 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2023 * mono_class_setup_methods:
2026 * Initializes the 'methods' array in the klass.
2027 * Calling this method should be avoided if possible since it allocates a lot
2028 * of long-living MonoMethod structures.
2029 * Methods belonging to an interface are assigned a sequential slot starting
2032 * On failure this function sets class->exception_type
2035 mono_class_setup_methods (MonoClass *class)
2038 MonoMethod **methods;
2043 mono_loader_lock ();
2045 if (class->methods) {
2046 mono_loader_unlock ();
2050 if (class->generic_class) {
2052 MonoClass *gklass = class->generic_class->container_class;
2054 mono_class_init (gklass);
2055 if (!gklass->exception_type)
2056 mono_class_setup_methods (gklass);
2057 if (gklass->exception_type) {
2058 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2059 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2060 mono_loader_unlock ();
2064 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2065 class->method.count = gklass->method.count;
2066 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2068 for (i = 0; i < class->method.count; i++) {
2069 methods [i] = mono_class_inflate_generic_method_full_checked (
2070 gklass->methods [i], class, mono_class_get_context (class), &error);
2071 if (!mono_error_ok (&error)) {
2072 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2073 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)));
2076 mono_error_cleanup (&error);
2077 mono_loader_unlock ();
2081 } else if (class->rank) {
2083 MonoMethod *amethod;
2084 MonoMethodSignature *sig;
2085 int count_generic = 0, first_generic = 0;
2088 class->method.count = 3 + (class->rank > 1? 2: 1);
2090 mono_class_setup_interfaces (class, &error);
2091 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2093 if (class->interface_count) {
2094 count_generic = generic_array_methods (class);
2095 first_generic = class->method.count;
2096 class->method.count += class->interface_count * count_generic;
2099 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2101 sig = mono_metadata_signature_alloc (class->image, class->rank);
2102 sig->ret = &mono_defaults.void_class->byval_arg;
2103 sig->pinvoke = TRUE;
2104 sig->hasthis = TRUE;
2105 for (i = 0; i < class->rank; ++i)
2106 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2108 amethod = create_array_method (class, ".ctor", sig);
2109 methods [method_num++] = amethod;
2110 if (class->rank > 1) {
2111 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2112 sig->ret = &mono_defaults.void_class->byval_arg;
2113 sig->pinvoke = TRUE;
2114 sig->hasthis = TRUE;
2115 for (i = 0; i < class->rank * 2; ++i)
2116 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2118 amethod = create_array_method (class, ".ctor", sig);
2119 methods [method_num++] = amethod;
2121 /* element Get (idx11, [idx2, ...]) */
2122 sig = mono_metadata_signature_alloc (class->image, class->rank);
2123 sig->ret = &class->element_class->byval_arg;
2124 sig->pinvoke = TRUE;
2125 sig->hasthis = TRUE;
2126 for (i = 0; i < class->rank; ++i)
2127 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2128 amethod = create_array_method (class, "Get", sig);
2129 methods [method_num++] = amethod;
2130 /* element& Address (idx11, [idx2, ...]) */
2131 sig = mono_metadata_signature_alloc (class->image, class->rank);
2132 sig->ret = &class->element_class->this_arg;
2133 sig->pinvoke = TRUE;
2134 sig->hasthis = TRUE;
2135 for (i = 0; i < class->rank; ++i)
2136 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2137 amethod = create_array_method (class, "Address", sig);
2138 methods [method_num++] = amethod;
2139 /* void Set (idx11, [idx2, ...], element) */
2140 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2141 sig->ret = &mono_defaults.void_class->byval_arg;
2142 sig->pinvoke = TRUE;
2143 sig->hasthis = TRUE;
2144 for (i = 0; i < class->rank; ++i)
2145 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2146 sig->params [i] = &class->element_class->byval_arg;
2147 amethod = create_array_method (class, "Set", sig);
2148 methods [method_num++] = amethod;
2150 for (i = 0; i < class->interface_count; i++)
2151 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2153 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2154 for (i = 0; i < class->method.count; ++i) {
2155 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2156 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2160 if (MONO_CLASS_IS_INTERFACE (class)) {
2162 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2163 for (i = 0; i < class->method.count; ++i) {
2164 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2165 methods [i]->slot = slot++;
2169 /* Needed because of the double-checking locking pattern */
2170 mono_memory_barrier ();
2172 class->methods = methods;
2174 mono_loader_unlock ();
2178 * mono_class_get_method_by_index:
2180 * Returns class->methods [index], initializing class->methods if neccesary.
2182 * LOCKING: Acquires the loader lock.
2185 mono_class_get_method_by_index (MonoClass *class, int index)
2187 /* Avoid calling setup_methods () if possible */
2188 if (class->generic_class && !class->methods) {
2189 MonoClass *gklass = class->generic_class->container_class;
2192 m = mono_class_inflate_generic_method_full (
2193 gklass->methods [index], class, mono_class_get_context (class));
2195 * If setup_methods () is called later for this class, no duplicates are created,
2196 * since inflate_generic_method guarantees that only one instance of a method
2197 * is created for each context.
2200 mono_class_setup_methods (class);
2201 g_assert (m == class->methods [index]);
2205 mono_class_setup_methods (class);
2206 if (class->exception_type) /*FIXME do proper error handling*/
2208 g_assert (index >= 0 && index < class->method.count);
2209 return class->methods [index];
2214 * mono_class_get_inflated_method:
2216 * Given an inflated class CLASS and a method METHOD which should be a method of
2217 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2220 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2222 MonoClass *gklass = class->generic_class->container_class;
2225 g_assert (method->klass == gklass);
2227 mono_class_setup_methods (gklass);
2228 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2230 for (i = 0; i < gklass->method.count; ++i) {
2231 if (gklass->methods [i] == method) {
2233 return class->methods [i];
2235 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2243 * mono_class_get_vtable_entry:
2245 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2246 * LOCKING: Acquires the loader lock.
2249 mono_class_get_vtable_entry (MonoClass *class, int offset)
2253 if (class->rank == 1) {
2255 * szarrays do not overwrite any methods of Array, so we can avoid
2256 * initializing their vtables in some cases.
2258 mono_class_setup_vtable (class->parent);
2259 if (offset < class->parent->vtable_size)
2260 return class->parent->vtable [offset];
2263 if (class->generic_class) {
2264 MonoClass *gklass = class->generic_class->container_class;
2265 mono_class_setup_vtable (gklass);
2266 m = gklass->vtable [offset];
2268 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2270 mono_class_setup_vtable (class);
2271 if (class->exception_type)
2273 m = class->vtable [offset];
2280 * mono_class_get_vtable_size:
2282 * Return the vtable size for KLASS.
2285 mono_class_get_vtable_size (MonoClass *klass)
2287 mono_class_setup_vtable (klass);
2289 return klass->vtable_size;
2292 /*This method can fail the class.*/
2294 mono_class_setup_properties (MonoClass *class)
2296 guint startm, endm, i, j;
2297 guint32 cols [MONO_PROPERTY_SIZE];
2298 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2299 MonoProperty *properties;
2302 if (class->ext && class->ext->properties)
2305 mono_loader_lock ();
2307 if (class->ext && class->ext->properties) {
2308 mono_loader_unlock ();
2312 mono_class_alloc_ext (class);
2314 if (class->generic_class) {
2315 MonoClass *gklass = class->generic_class->container_class;
2317 mono_class_init (gklass);
2318 mono_class_setup_properties (gklass);
2319 if (gklass->exception_type) {
2320 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2321 mono_loader_unlock ();
2325 class->ext->property = gklass->ext->property;
2327 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2329 for (i = 0; i < class->ext->property.count; i++) {
2330 MonoProperty *prop = &properties [i];
2332 *prop = gklass->ext->properties [i];
2335 prop->get = mono_class_inflate_generic_method_full (
2336 prop->get, class, mono_class_get_context (class));
2338 prop->set = mono_class_inflate_generic_method_full (
2339 prop->set, class, mono_class_get_context (class));
2341 prop->parent = class;
2344 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2345 int count = last - first;
2348 mono_class_setup_methods (class);
2349 if (class->exception_type) {
2350 mono_loader_unlock ();
2355 class->ext->property.first = first;
2356 class->ext->property.count = count;
2357 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2358 for (i = first; i < last; ++i) {
2359 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2360 properties [i - first].parent = class;
2361 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2362 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2364 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2365 for (j = startm; j < endm; ++j) {
2368 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2370 if (class->image->uncompressed_metadata)
2371 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2372 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2374 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2376 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2377 case METHOD_SEMANTIC_SETTER:
2378 properties [i - first].set = method;
2380 case METHOD_SEMANTIC_GETTER:
2381 properties [i - first].get = method;
2389 /*Flush any pending writes as we do double checked locking on class->properties */
2390 mono_memory_barrier ();
2392 /* Leave this assignment as the last op in the function */
2393 class->ext->properties = properties;
2395 mono_loader_unlock ();
2399 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2401 MonoMethod **om, **retval;
2404 for (om = methods, count = 0; *om; ++om, ++count)
2407 retval = g_new0 (MonoMethod*, count + 1);
2409 for (om = methods, count = 0; *om; ++om, ++count)
2410 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2415 /*This method can fail the class.*/
2417 mono_class_setup_events (MonoClass *class)
2420 guint startm, endm, i, j;
2421 guint32 cols [MONO_EVENT_SIZE];
2422 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2426 if (class->ext && class->ext->events)
2429 mono_loader_lock ();
2431 if (class->ext && class->ext->events) {
2432 mono_loader_unlock ();
2436 mono_class_alloc_ext (class);
2438 if (class->generic_class) {
2439 MonoClass *gklass = class->generic_class->container_class;
2440 MonoGenericContext *context;
2442 mono_class_setup_events (gklass);
2443 if (gklass->exception_type) {
2444 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2445 mono_loader_unlock ();
2449 class->ext->event = gklass->ext->event;
2450 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2452 if (class->ext->event.count)
2453 context = mono_class_get_context (class);
2455 for (i = 0; i < class->ext->event.count; i++) {
2456 MonoEvent *event = &class->ext->events [i];
2457 MonoEvent *gevent = &gklass->ext->events [i];
2459 event->parent = class;
2460 event->name = gevent->name;
2461 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2462 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2463 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2464 #ifndef MONO_SMALL_CONFIG
2465 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2467 event->attrs = gevent->attrs;
2470 mono_loader_unlock ();
2474 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2475 count = last - first;
2478 mono_class_setup_methods (class);
2479 if (class->exception_type) {
2480 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2481 mono_loader_unlock ();
2485 class->ext->event.first = first;
2486 class->ext->event.count = count;
2487 events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2488 for (i = first; i < last; ++i) {
2489 MonoEvent *event = &events [i - first];
2491 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2492 event->parent = class;
2493 event->attrs = cols [MONO_EVENT_FLAGS];
2494 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2496 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2497 for (j = startm; j < endm; ++j) {
2500 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2502 if (class->image->uncompressed_metadata)
2503 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2504 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2506 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2508 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2509 case METHOD_SEMANTIC_ADD_ON:
2510 event->add = method;
2512 case METHOD_SEMANTIC_REMOVE_ON:
2513 event->remove = method;
2515 case METHOD_SEMANTIC_FIRE:
2516 event->raise = method;
2518 case METHOD_SEMANTIC_OTHER: {
2519 #ifndef MONO_SMALL_CONFIG
2522 if (event->other == NULL) {
2523 event->other = g_new0 (MonoMethod*, 2);
2525 while (event->other [n])
2527 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2529 event->other [n] = method;
2530 /* NULL terminated */
2531 event->other [n + 1] = NULL;
2540 /*Flush any pending writes as we do double checked locking on class->properties */
2541 mono_memory_barrier ();
2543 /* Leave this assignment as the last op in the function */
2544 class->ext->events = events;
2546 mono_loader_unlock ();
2550 * Global pool of interface IDs, represented as a bitset.
2551 * LOCKING: this is supposed to be accessed with the loader lock held.
2553 static MonoBitSet *global_interface_bitset = NULL;
2556 * mono_unload_interface_ids:
2557 * @bitset: bit set of interface IDs
2559 * When an image is unloaded, the interface IDs associated with
2560 * the image are put back in the global pool of IDs so the numbers
2564 mono_unload_interface_ids (MonoBitSet *bitset)
2566 mono_loader_lock ();
2567 mono_bitset_sub (global_interface_bitset, bitset);
2568 mono_loader_unlock ();
2572 mono_unload_interface_id (MonoClass *class)
2574 if (global_interface_bitset && class->interface_id) {
2575 mono_loader_lock ();
2576 mono_bitset_clear (global_interface_bitset, class->interface_id);
2577 mono_loader_unlock ();
2582 * mono_get_unique_iid:
2585 * Assign a unique integer ID to the interface represented by @class.
2586 * The ID will positive and as small as possible.
2587 * LOCKING: this is supposed to be called with the loader lock held.
2588 * Returns: the new ID.
2591 mono_get_unique_iid (MonoClass *class)
2595 g_assert (MONO_CLASS_IS_INTERFACE (class));
2597 if (!global_interface_bitset) {
2598 global_interface_bitset = mono_bitset_new (128, 0);
2601 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2603 int old_size = mono_bitset_size (global_interface_bitset);
2604 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2605 mono_bitset_free (global_interface_bitset);
2606 global_interface_bitset = new_set;
2609 mono_bitset_set (global_interface_bitset, iid);
2610 /* set the bit also in the per-image set */
2611 if (!class->generic_class) {
2612 if (class->image->interface_bitset) {
2613 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2614 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2615 mono_bitset_free (class->image->interface_bitset);
2616 class->image->interface_bitset = new_set;
2619 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2621 mono_bitset_set (class->image->interface_bitset, iid);
2624 #ifndef MONO_SMALL_CONFIG
2625 if (mono_print_vtable) {
2627 char *type_name = mono_type_full_name (&class->byval_arg);
2628 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2629 generic_id = class->generic_class->context.class_inst->id;
2630 g_assert (generic_id != 0);
2634 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2639 g_assert (iid <= 65535);
2644 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2649 mono_class_setup_interfaces (klass, error);
2650 if (!mono_error_ok (error))
2653 for (i = 0; i < klass->interface_count; i++) {
2654 ic = klass->interfaces [i];
2657 *res = g_ptr_array_new ();
2658 g_ptr_array_add (*res, ic);
2659 mono_class_init (ic);
2660 if (ic->exception_type) {
2661 mono_error_set_type_load_class (error, ic, "Error Loading class");
2665 collect_implemented_interfaces_aux (ic, res, error);
2666 if (!mono_error_ok (error))
2672 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2674 GPtrArray *res = NULL;
2676 collect_implemented_interfaces_aux (klass, &res, error);
2677 if (!mono_error_ok (error)) {
2679 g_ptr_array_free (res, TRUE);
2686 compare_interface_ids (const void *p_key, const void *p_element) {
2687 const MonoClass *key = p_key;
2688 const MonoClass *element = *(MonoClass**) p_element;
2690 return (key->interface_id - element->interface_id);
2693 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2695 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2696 MonoClass **result = mono_binary_search (
2698 klass->interfaces_packed,
2699 klass->interface_offsets_count,
2700 sizeof (MonoClass *),
2701 compare_interface_ids);
2703 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2710 * mono_class_interface_offset_with_variance:
2712 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2713 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2715 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2717 * FIXME figure out MS disambiguation rules and fix this function.
2720 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2721 int i = mono_class_interface_offset (klass, itf);
2722 *non_exact_match = FALSE;
2726 if (!mono_class_has_variant_generic_params (itf))
2729 for (i = 0; i < klass->interface_offsets_count; i++) {
2730 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2731 *non_exact_match = TRUE;
2732 return klass->interface_offsets_packed [i];
2740 print_implemented_interfaces (MonoClass *klass) {
2743 GPtrArray *ifaces = NULL;
2745 int ancestor_level = 0;
2747 name = mono_type_get_full_name (klass);
2748 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2751 for (i = 0; i < klass->interface_offsets_count; i++)
2752 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2753 klass->interfaces_packed [i]->interface_id,
2754 klass->interface_offsets_packed [i],
2755 klass->interfaces_packed [i]->method.count,
2756 klass->interfaces_packed [i]->name_space,
2757 klass->interfaces_packed [i]->name );
2758 printf ("Interface flags: ");
2759 for (i = 0; i <= klass->max_interface_id; i++)
2760 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2761 printf ("(%d,T)", i);
2763 printf ("(%d,F)", i);
2765 printf ("Dump interface flags:");
2766 #ifdef COMPRESSED_INTERFACE_BITMAP
2768 const uint8_t* p = klass->interface_bitmap;
2769 i = klass->max_interface_id;
2771 printf (" %d x 00 %02X", p [0], p [1]);
2777 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2778 printf (" %02X", klass->interface_bitmap [i]);
2781 while (klass != NULL) {
2782 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2783 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2784 if (!mono_error_ok (&error)) {
2785 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2786 mono_error_cleanup (&error);
2787 } else if (ifaces) {
2788 for (i = 0; i < ifaces->len; i++) {
2789 MonoClass *ic = g_ptr_array_index (ifaces, i);
2790 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2791 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2793 mono_class_interface_offset (klass, ic),
2798 g_ptr_array_free (ifaces, TRUE);
2801 klass = klass->parent;
2806 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2809 args [0] = &arg0->byval_arg;
2811 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2815 array_class_get_if_rank (MonoClass *class, guint rank)
2817 return rank ? mono_array_class_get (class, rank) : class;
2821 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2823 valuetype_types [0] = eclass;
2824 if (eclass == mono_defaults.int16_class)
2825 valuetype_types [1] = mono_defaults.uint16_class;
2826 else if (eclass == mono_defaults.uint16_class)
2827 valuetype_types [1] = mono_defaults.int16_class;
2828 else if (eclass == mono_defaults.int32_class)
2829 valuetype_types [1] = mono_defaults.uint32_class;
2830 else if (eclass == mono_defaults.uint32_class)
2831 valuetype_types [1] = mono_defaults.int32_class;
2832 else if (eclass == mono_defaults.int64_class)
2833 valuetype_types [1] = mono_defaults.uint64_class;
2834 else if (eclass == mono_defaults.uint64_class)
2835 valuetype_types [1] = mono_defaults.int64_class;
2836 else if (eclass == mono_defaults.byte_class)
2837 valuetype_types [1] = mono_defaults.sbyte_class;
2838 else if (eclass == mono_defaults.sbyte_class)
2839 valuetype_types [1] = mono_defaults.byte_class;
2840 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2841 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2844 /* this won't be needed once bug #325495 is completely fixed
2845 * though we'll need something similar to know which interfaces to allow
2846 * in arrays when they'll be lazyly created
2848 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2849 * MS returns diferrent types based on which instance is called. For example:
2850 * object obj = new byte[10][];
2851 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2852 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2855 * Fixing this should kill quite some code, save some bits and improve compatibility.
2858 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2860 MonoClass *eclass = class->element_class;
2861 static MonoClass* generic_icollection_class = NULL;
2862 static MonoClass* generic_ienumerable_class = NULL;
2863 static MonoClass* generic_ienumerator_class = NULL;
2864 static MonoClass* generic_ireadonlylist_class = NULL;
2865 static MonoClass* generic_ireadonlycollection_class = NULL;
2866 MonoClass *valuetype_types[2] = { NULL, NULL };
2867 MonoClass **interfaces = NULL;
2868 int i, nifaces, interface_count, real_count, original_rank;
2870 gboolean internal_enumerator;
2871 gboolean eclass_is_valuetype;
2873 if (!mono_defaults.generic_ilist_class) {
2877 internal_enumerator = FALSE;
2878 eclass_is_valuetype = FALSE;
2879 original_rank = eclass->rank;
2880 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2881 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2883 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2885 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2886 original_rank = eclass->rank;
2888 eclass = eclass->element_class;
2889 internal_enumerator = TRUE;
2890 *is_enumerator = TRUE;
2898 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2899 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2901 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2903 if (!generic_icollection_class) {
2904 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2905 "System.Collections.Generic", "ICollection`1");
2906 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2907 "System.Collections.Generic", "IEnumerable`1");
2908 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2909 "System.Collections.Generic", "IEnumerator`1");
2910 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2911 "System.Collections.Generic", "IReadOnlyList`1");
2912 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2913 "System.Collections.Generic", "IReadOnlyCollection`1");
2916 mono_class_init (eclass);
2919 * Arrays in 2.0 need to implement a number of generic interfaces
2920 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2921 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2922 * We collect the types needed to build the
2923 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2924 * the generic interfaces needed to implement.
2926 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2927 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2929 if (eclass->valuetype) {
2930 nifaces = generic_ireadonlylist_class ? 5 : 3;
2931 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2933 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2934 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2935 if (internal_enumerator) {
2937 if (valuetype_types [1])
2941 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2942 interfaces [0] = valuetype_types [0];
2943 if (valuetype_types [1])
2944 interfaces [nifaces] = valuetype_types [1];
2946 eclass_is_valuetype = TRUE;
2949 int idepth = eclass->idepth;
2950 if (!internal_enumerator)
2952 nifaces = generic_ireadonlylist_class ? 2 : 3;
2954 // FIXME: This doesn't seem to work/required for generic params
2955 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
2956 mono_class_setup_interface_offsets (eclass);
2958 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2959 /* we add object for interfaces and the supertypes for the other
2960 * types. The last of the supertypes is the element class itself which we
2961 * already created the explicit interfaces for (so we include it for IEnumerator
2962 * and exclude it for arrays).
2964 if (MONO_CLASS_IS_INTERFACE (eclass))
2967 interface_count += idepth;
2968 if (eclass->rank && eclass->element_class->valuetype) {
2969 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2970 if (valuetype_types [1])
2973 /* IList, ICollection, IEnumerable, IReadOnlyList */
2974 interface_count *= nifaces;
2975 real_count = interface_count;
2976 if (internal_enumerator) {
2977 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2978 if (valuetype_types [1])
2981 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2982 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2983 interfaces [0] = mono_defaults.object_class;
2987 for (i = 0; i < idepth; i++) {
2988 mono_class_init (eclass->supertypes [i]);
2989 interfaces [j] = eclass->supertypes [i];
2993 if (all_interfaces) {
2994 for (i = 0; i < eclass->interface_offsets_count; i++) {
2995 interfaces [j] = eclass->interfaces_packed [i];
2999 for (i = 0; i < eclass->interface_count; i++) {
3000 interfaces [j] = eclass->interfaces [i];
3004 if (valuetype_types [1]) {
3005 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3010 /* instantiate the generic interfaces */
3011 for (i = 0; i < interface_count; i += nifaces) {
3012 MonoClass *iface = interfaces [i];
3014 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3015 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3017 if (eclass->valuetype) {
3018 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3019 if (generic_ireadonlylist_class) {
3020 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3021 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3024 if (!generic_ireadonlylist_class)
3025 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3028 if (internal_enumerator) {
3030 /* instantiate IEnumerator<iface> */
3031 for (i = 0; i < interface_count; i++) {
3032 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3034 j = interface_count;
3035 if (!eclass_is_valuetype) {
3036 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3037 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3040 for (i = 0; i < eclass->idepth; i++) {
3041 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3045 for (i = 0; i < eclass->interface_offsets_count; i++) {
3046 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3050 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3052 if (valuetype_types [1])
3053 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3057 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3058 for (i = 0; i < real_count; ++i) {
3059 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3060 g_print ("%s implements %s\n", type_name, name);
3071 find_array_interface (MonoClass *klass, const char *name)
3074 for (i = 0; i < klass->interface_count; ++i) {
3075 if (strcmp (klass->interfaces [i]->name, name) == 0)
3082 * Return the number of virtual methods.
3083 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3084 * Return -1 on failure.
3085 * FIXME It would be nice if this information could be cached somewhere.
3088 count_virtual_methods (MonoClass *class)
3092 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3094 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3095 mono_class_setup_methods (class);
3096 if (class->exception_type)
3099 for (i = 0; i < class->method.count; ++i) {
3100 flags = class->methods [i]->flags;
3101 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3105 for (i = 0; i < class->method.count; ++i) {
3106 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3108 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3116 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3124 m = (l + num_ifaces) / 2;
3125 if (interfaces_full [m] == ic)
3127 if (l == num_ifaces)
3129 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3138 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3140 int i = find_interface (num_ifaces, interfaces_full, ic);
3142 return interface_offsets_full [i];
3147 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3149 int i = find_interface (num_ifaces, interfaces_full, ic);
3153 interface_offsets_full [i] = offset;
3156 for (i = 0; i < num_ifaces; ++i) {
3157 if (interfaces_full [i]) {
3159 if (interfaces_full [i]->interface_id < ic->interface_id)
3162 while (end < num_ifaces && interfaces_full [end]) end++;
3163 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3164 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3166 interfaces_full [i] = ic;
3167 interface_offsets_full [i] = offset;
3173 #ifdef COMPRESSED_INTERFACE_BITMAP
3176 * Compressed interface bitmap design.
3178 * Interface bitmaps take a large amount of memory, because their size is
3179 * linear with the maximum interface id assigned in the process (each interface
3180 * is assigned a unique id as it is loaded). The number of interface classes
3181 * is high because of the many implicit interfaces implemented by arrays (we'll
3182 * need to lazy-load them in the future).
3183 * Most classes implement a very small number of interfaces, so the bitmap is
3184 * sparse. This bitmap needs to be checked by interface casts, so access to the
3185 * needed bit must be fast and doable with few jit instructions.
3187 * The current compression format is as follows:
3188 * *) it is a sequence of one or more two-byte elements
3189 * *) the first byte in the element is the count of empty bitmap bytes
3190 * at the current bitmap position
3191 * *) the second byte in the element is an actual bitmap byte at the current
3194 * As an example, the following compressed bitmap bytes:
3195 * 0x07 0x01 0x00 0x7
3196 * correspond to the following bitmap:
3197 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3199 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3200 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3201 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3205 * mono_compress_bitmap:
3206 * @dest: destination buffer
3207 * @bitmap: bitmap buffer
3208 * @size: size of @bitmap in bytes
3210 * This is a mono internal function.
3211 * The @bitmap data is compressed into a format that is small but
3212 * still searchable in few instructions by the JIT and runtime.
3213 * The compressed data is stored in the buffer pointed to by the
3214 * @dest array. Passing a #NULL value for @dest allows to just compute
3215 * the size of the buffer.
3216 * This compression algorithm assumes the bits set in the bitmap are
3217 * few and far between, like in interface bitmaps.
3218 * Returns: the size of the compressed bitmap in bytes.
3221 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3225 const uint8_t *end = bitmap + size;
3226 while (bitmap < end) {
3227 if (*bitmap || numz == 255) {
3251 * mono_class_interface_match:
3252 * @bitmap: a compressed bitmap buffer
3253 * @id: the index to check in the bitmap
3255 * This is a mono internal function.
3256 * Checks if a bit is set in a compressed interface bitmap. @id must
3257 * be already checked for being smaller than the maximum id encoded in the
3260 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3264 mono_class_interface_match (const uint8_t *bitmap, int id)
3267 id -= bitmap [0] * 8;
3271 return bitmap [1] & (1 << id);
3280 * LOCKING: this is supposed to be called with the loader lock held.
3281 * Return -1 on failure and set exception_type
3284 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3288 int i, j, max_iid, num_ifaces;
3289 MonoClass **interfaces_full = NULL;
3290 int *interface_offsets_full = NULL;
3292 GPtrArray **ifaces_array = NULL;
3293 int interface_offsets_count;
3294 MonoClass **array_interfaces = NULL;
3295 int num_array_interfaces;
3296 int is_enumerator = FALSE;
3298 mono_class_setup_supertypes (class);
3300 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3301 * implicit interfaces have the property that they are assigned the same slot in the
3302 * vtables for compatible interfaces
3304 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3306 /* compute maximum number of slots and maximum interface id */
3308 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3309 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3310 for (j = 0; j < class->idepth; j++) {
3311 k = class->supertypes [j];
3312 num_ifaces += k->interface_count;
3313 for (i = 0; i < k->interface_count; i++) {
3314 ic = k->interfaces [i];
3317 mono_class_init (ic);
3319 if (max_iid < ic->interface_id)
3320 max_iid = ic->interface_id;
3322 ifaces = mono_class_get_implemented_interfaces (k, &error);
3323 if (!mono_error_ok (&error)) {
3324 char *name = mono_type_get_full_name (k);
3325 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)));
3327 mono_error_cleanup (&error);
3332 num_ifaces += ifaces->len;
3333 for (i = 0; i < ifaces->len; ++i) {
3334 ic = g_ptr_array_index (ifaces, i);
3335 if (max_iid < ic->interface_id)
3336 max_iid = ic->interface_id;
3338 ifaces_array [j] = ifaces;
3342 for (i = 0; i < num_array_interfaces; ++i) {
3343 ic = array_interfaces [i];
3344 mono_class_init (ic);
3345 if (max_iid < ic->interface_id)
3346 max_iid = ic->interface_id;
3349 if (MONO_CLASS_IS_INTERFACE (class)) {
3351 if (max_iid < class->interface_id)
3352 max_iid = class->interface_id;
3354 class->max_interface_id = max_iid;
3355 /* compute vtable offset for interfaces */
3356 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3357 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3359 for (i = 0; i < num_ifaces; i++) {
3360 interface_offsets_full [i] = -1;
3363 /* skip the current class */
3364 for (j = 0; j < class->idepth - 1; j++) {
3365 k = class->supertypes [j];
3366 ifaces = ifaces_array [j];
3369 for (i = 0; i < ifaces->len; ++i) {
3371 ic = g_ptr_array_index (ifaces, i);
3373 /*Force the sharing of interface offsets between parent and subtypes.*/
3374 io = mono_class_interface_offset (k, ic);
3376 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3381 g_assert (class == class->supertypes [class->idepth - 1]);
3382 ifaces = ifaces_array [class->idepth - 1];
3384 for (i = 0; i < ifaces->len; ++i) {
3386 ic = g_ptr_array_index (ifaces, i);
3387 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3389 count = count_virtual_methods (ic);
3391 char *name = mono_type_get_full_name (ic);
3392 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3401 if (MONO_CLASS_IS_INTERFACE (class))
3402 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3404 if (num_array_interfaces) {
3405 if (is_enumerator) {
3406 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3407 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3408 g_assert (ienumerator_offset >= 0);
3409 for (i = 0; i < num_array_interfaces; ++i) {
3410 ic = array_interfaces [i];
3411 if (strcmp (ic->name, "IEnumerator`1") == 0)
3412 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3414 g_assert_not_reached ();
3415 /*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);*/
3418 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3419 int ilist_iface_idx = find_array_interface (class, "IList`1");
3420 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3421 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3422 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3423 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3424 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3425 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3426 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3427 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3428 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3429 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3430 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3431 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3432 for (i = 0; i < num_array_interfaces; ++i) {
3434 ic = array_interfaces [i];
3435 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3436 offset = ilist_offset;
3437 else if (strcmp (ic->name, "ICollection`1") == 0)
3438 offset = icollection_offset;
3439 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3440 offset = ienumerable_offset;
3441 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3442 offset = ireadonlylist_offset;
3443 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3444 offset = ireadonlycollection_offset;
3446 g_assert_not_reached ();
3447 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3448 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3453 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3454 if (interface_offsets_full [i] != -1) {
3455 interface_offsets_count ++;
3460 * We might get called multiple times:
3461 * - mono_class_init ()
3462 * - mono_class_setup_vtable ().
3463 * - mono_class_setup_interface_offsets ().
3464 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3465 * means we have to overwrite those when called from other places (#4440).
3467 if (class->interfaces_packed && !overwrite) {
3468 g_assert (class->interface_offsets_count == interface_offsets_count);
3472 class->interface_offsets_count = interface_offsets_count;
3473 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3474 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3475 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3476 #ifdef COMPRESSED_INTERFACE_BITMAP
3477 bitmap = g_malloc0 (bsize);
3479 bitmap = mono_class_alloc0 (class, bsize);
3481 for (i = 0; i < interface_offsets_count; i++) {
3482 int id = interfaces_full [i]->interface_id;
3483 bitmap [id >> 3] |= (1 << (id & 7));
3484 class->interfaces_packed [i] = interfaces_full [i];
3485 class->interface_offsets_packed [i] = interface_offsets_full [i];
3486 /*if (num_array_interfaces)
3487 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]);*/
3489 #ifdef COMPRESSED_INTERFACE_BITMAP
3490 i = mono_compress_bitmap (NULL, bitmap, bsize);
3491 class->interface_bitmap = mono_class_alloc0 (class, i);
3492 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3495 class->interface_bitmap = bitmap;
3500 g_free (interfaces_full);
3501 g_free (interface_offsets_full);
3502 g_free (array_interfaces);
3503 for (i = 0; i < class->idepth; i++) {
3504 ifaces = ifaces_array [i];
3506 g_ptr_array_free (ifaces, TRUE);
3508 g_free (ifaces_array);
3510 //printf ("JUST DONE: ");
3511 //print_implemented_interfaces (class);
3517 * Setup interface offsets for interfaces.
3519 * - class->max_interface_id
3520 * - class->interface_offsets_count
3521 * - class->interfaces_packed
3522 * - class->interface_offsets_packed
3523 * - class->interface_bitmap
3525 * This function can fail @class.
3528 mono_class_setup_interface_offsets (MonoClass *class)
3530 mono_loader_lock ();
3532 setup_interface_offsets (class, 0, FALSE);
3534 mono_loader_unlock ();
3537 /*Checks if @klass has @parent as one of it's parents type gtd
3541 * Bar<T> : Foo<Bar<Bar<T>>>
3545 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3547 klass = mono_class_get_generic_type_definition (klass);
3548 parent = mono_class_get_generic_type_definition (parent);
3549 mono_class_setup_supertypes (klass);
3550 mono_class_setup_supertypes (parent);
3552 return klass->idepth >= parent->idepth &&
3553 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3557 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3559 MonoGenericInst *ginst;
3561 if (!class->generic_class) {
3562 mono_class_setup_vtable_full (class, in_setup);
3563 return class->exception_type == 0;
3566 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3567 if (class->generic_class->container_class->exception_type) {
3568 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3572 ginst = class->generic_class->context.class_inst;
3573 for (i = 0; i < ginst->type_argc; ++i) {
3575 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3577 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3578 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3579 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3581 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3582 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3590 * mono_class_setup_vtable:
3592 * Creates the generic vtable of CLASS.
3593 * Initializes the following fields in MonoClass:
3596 * Plus all the fields initialized by setup_interface_offsets ().
3597 * If there is an error during vtable construction, class->exception_type is set.
3599 * LOCKING: Acquires the loader lock.
3602 mono_class_setup_vtable (MonoClass *class)
3604 mono_class_setup_vtable_full (class, NULL);
3608 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3610 MonoMethod **overrides;
3611 MonoGenericContext *context;
3619 if (MONO_CLASS_IS_INTERFACE (class)) {
3620 /* This sets method->slot for all methods if this is an interface */
3621 mono_class_setup_methods (class);
3625 if (class->exception_type)
3628 if (g_list_find (in_setup, class))
3631 mono_loader_lock ();
3633 if (class->vtable) {
3634 mono_loader_unlock ();
3638 mono_stats.generic_vtable_count ++;
3639 in_setup = g_list_prepend (in_setup, class);
3641 if (class->generic_class) {
3642 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3643 mono_loader_unlock ();
3644 g_list_remove (in_setup, class);
3648 context = mono_class_get_context (class);
3649 type_token = class->generic_class->container_class->type_token;
3651 context = (MonoGenericContext *) class->generic_container;
3652 type_token = class->type_token;
3655 if (class->image->dynamic) {
3656 /* Generic instances can have zero method overrides without causing any harm.
3657 * This is true since we don't do layout all over again for them, we simply inflate
3658 * the layout of the parent.
3660 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3662 /* The following call fails if there are missing methods in the type */
3663 /* FIXME it's probably a good idea to avoid this for generic instances. */
3664 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3668 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3670 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3674 mono_loader_unlock ();
3675 g_list_remove (in_setup, class);
3680 #define DEBUG_INTERFACE_VTABLE_CODE 0
3681 #define TRACE_INTERFACE_VTABLE_CODE 0
3682 #define VERIFY_INTERFACE_VTABLE_CODE 0
3683 #define VTABLE_SELECTOR (1)
3685 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3686 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3687 if (!(VTABLE_SELECTOR)) break; \
3691 #define DEBUG_INTERFACE_VTABLE(stmt)
3694 #if TRACE_INTERFACE_VTABLE_CODE
3695 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3696 if (!(VTABLE_SELECTOR)) break; \
3700 #define TRACE_INTERFACE_VTABLE(stmt)
3703 #if VERIFY_INTERFACE_VTABLE_CODE
3704 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3705 if (!(VTABLE_SELECTOR)) break; \
3709 #define VERIFY_INTERFACE_VTABLE(stmt)
3713 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3715 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3719 GString *res = g_string_new ("");
3721 g_string_append_c (res, '(');
3722 for (i = 0; i < sig->param_count; ++i) {
3724 g_string_append_c (res, ',');
3725 mono_type_get_desc (res, sig->params [i], include_namespace);
3727 g_string_append (res, ")=>");
3728 if (sig->ret != NULL) {
3729 mono_type_get_desc (res, sig->ret, include_namespace);
3731 g_string_append (res, "NULL");
3734 g_string_free (res, FALSE);
3738 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3739 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3740 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3741 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3749 is_wcf_hack_disabled (void)
3751 static gboolean disabled;
3752 static gboolean inited = FALSE;
3754 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3761 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) {
3762 MonoMethodSignature *cmsig, *imsig;
3763 if (strcmp (im->name, cm->name) == 0) {
3764 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3765 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3768 if (! slot_is_empty) {
3769 if (require_newslot) {
3770 if (! interface_is_explicitly_implemented_by_class) {
3771 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3774 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3775 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3779 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3782 cmsig = mono_method_signature (cm);
3783 imsig = mono_method_signature (im);
3784 if (!cmsig || !imsig) {
3785 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3789 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3790 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3791 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3792 TRACE_INTERFACE_VTABLE (printf ("]"));
3795 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3796 /* CAS - SecurityAction.InheritanceDemand on interface */
3797 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3798 mono_secman_inheritancedemand_method (cm, im);
3801 if (mono_security_core_clr_enabled ())
3802 mono_security_core_clr_check_override (class, cm, im);
3804 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3805 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3806 char *body_name = mono_method_full_name (cm, TRUE);
3807 char *decl_name = mono_method_full_name (im, TRUE);
3808 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));
3816 MonoClass *ic = im->klass;
3817 const char *ic_name_space = ic->name_space;
3818 const char *ic_name = ic->name;
3821 if (! require_newslot) {
3822 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3825 if (cm->klass->rank == 0) {
3826 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3829 cmsig = mono_method_signature (cm);
3830 imsig = mono_method_signature (im);
3831 if (!cmsig || !imsig) {
3832 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3836 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3837 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3838 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3839 TRACE_INTERFACE_VTABLE (printf ("]"));
3842 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3843 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3846 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3847 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3850 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))) {
3851 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3855 subname = strstr (cm->name, ic_name_space);
3856 if (subname != cm->name) {
3857 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3860 subname += strlen (ic_name_space);
3861 if (subname [0] != '.') {
3862 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3866 if (strstr (subname, ic_name) != subname) {
3867 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3870 subname += strlen (ic_name);
3871 if (subname [0] != '.') {
3872 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3876 if (strcmp (subname, im->name) != 0) {
3877 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3881 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3882 /* CAS - SecurityAction.InheritanceDemand on interface */
3883 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3884 mono_secman_inheritancedemand_method (cm, im);
3887 if (mono_security_core_clr_enabled ())
3888 mono_security_core_clr_check_override (class, cm, im);
3890 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3891 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3892 char *body_name = mono_method_full_name (cm, TRUE);
3893 char *decl_name = mono_method_full_name (im, TRUE);
3894 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));
3904 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3906 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3907 MonoMethod *method = key;
3908 MonoMethod *override = value;
3909 MonoClass *method_class = mono_method_get_class (method);
3910 MonoClass *override_class = mono_method_get_class (override);
3912 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3913 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3914 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3917 print_overrides (GHashTable *override_map, const char *message) {
3919 printf ("Override map \"%s\" START:\n", message);
3920 g_hash_table_foreach (override_map, foreach_override, NULL);
3921 printf ("Override map \"%s\" END.\n", message);
3923 printf ("Override map \"%s\" EMPTY.\n", message);
3927 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3928 char *full_name = mono_type_full_name (&class->byval_arg);
3932 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3934 if (print_interfaces) {
3935 print_implemented_interfaces (class);
3936 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3939 if (class->parent) {
3940 parent_size = class->parent->vtable_size;
3944 for (i = 0; i < size; ++i) {
3945 MonoMethod *cm = vtable [i];
3946 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3947 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3949 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3957 #if VERIFY_INTERFACE_VTABLE_CODE
3959 mono_method_try_get_vtable_index (MonoMethod *method)
3961 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3962 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3963 if (imethod->declaring->is_generic)
3964 return imethod->declaring->slot;
3966 return method->slot;
3970 mono_class_verify_vtable (MonoClass *class)
3973 char *full_name = mono_type_full_name (&class->byval_arg);
3975 printf ("*** Verifying VTable of class '%s' \n", full_name);
3979 if (!class->methods)
3982 for (i = 0; i < class->method.count; ++i) {
3983 MonoMethod *cm = class->methods [i];
3986 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3990 full_name = mono_method_full_name (cm, TRUE);
3992 slot = mono_method_try_get_vtable_index (cm);
3994 if (slot >= class->vtable_size) {
3995 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
3999 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4000 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4001 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4002 g_free (other_name);
4005 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4012 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4014 char *method_signature;
4017 for (index = 0; index < onum; ++index) {
4018 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4019 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4021 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4022 type_name = mono_type_full_name (&class->byval_arg);
4023 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4024 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4025 g_free (method_signature);
4027 mono_class_setup_methods (class);
4028 if (class->exception_type) {
4029 char *name = mono_type_get_full_name (class);
4030 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4034 for (index = 0; index < class->method.count; ++index) {
4035 MonoMethod *cm = class->methods [index];
4036 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4038 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4039 g_free (method_signature);
4044 mono_method_get_method_definition (MonoMethod *method)
4046 while (method->is_inflated)
4047 method = ((MonoMethodInflated*)method)->declaring;
4052 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4056 for (i = 0; i < onum; ++i) {
4057 MonoMethod *decl = overrides [i * 2];
4058 MonoMethod *body = overrides [i * 2 + 1];
4060 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4061 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4065 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4066 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4067 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4069 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4073 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4074 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4075 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4077 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4081 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4082 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4086 body = mono_method_get_method_definition (body);
4087 decl = mono_method_get_method_definition (decl);
4089 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4090 char *body_name = mono_method_full_name (body, TRUE);
4091 char *decl_name = mono_method_full_name (decl, TRUE);
4092 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));
4102 mono_class_need_stelemref_method (MonoClass *class)
4104 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4108 * LOCKING: this is supposed to be called with the loader lock held.
4111 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4115 MonoMethod **vtable;
4116 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4117 GPtrArray *ifaces = NULL;
4118 GHashTable *override_map = NULL;
4119 gboolean security_enabled = mono_security_enabled ();
4121 gpointer class_iter;
4122 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4123 int first_non_interface_slot;
4125 GSList *virt_methods = NULL, *l;
4126 int stelemref_slot = 0;
4131 if (overrides && !verify_class_overrides (class, overrides, onum))
4134 ifaces = mono_class_get_implemented_interfaces (class, &error);
4135 if (!mono_error_ok (&error)) {
4136 char *name = mono_type_get_full_name (class);
4137 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)));
4139 mono_error_cleanup (&error);
4141 } else if (ifaces) {
4142 for (i = 0; i < ifaces->len; i++) {
4143 MonoClass *ic = g_ptr_array_index (ifaces, i);
4144 max_vtsize += ic->method.count;
4146 g_ptr_array_free (ifaces, TRUE);
4150 if (class->parent) {
4151 mono_class_init (class->parent);
4152 mono_class_setup_vtable_full (class->parent, in_setup);
4154 if (class->parent->exception_type) {
4155 char *name = mono_type_get_full_name (class->parent);
4156 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4161 max_vtsize += class->parent->vtable_size;
4162 cur_slot = class->parent->vtable_size;
4165 max_vtsize += class->method.count;
4167 /*Array have a slot for stelemref*/
4168 if (mono_class_need_stelemref_method (class)) {
4169 stelemref_slot = cur_slot;
4174 vtable = alloca (sizeof (gpointer) * max_vtsize);
4175 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4177 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4179 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4180 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4183 max_iid = class->max_interface_id;
4184 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4186 /* Optimized version for generic instances */
4187 if (class->generic_class) {
4189 MonoClass *gklass = class->generic_class->container_class;
4192 mono_class_setup_vtable_full (gklass, in_setup);
4193 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4194 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4198 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4199 class->vtable_size = gklass->vtable_size;
4200 for (i = 0; i < gklass->vtable_size; ++i)
4201 if (gklass->vtable [i]) {
4202 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4203 if (!mono_error_ok (&error)) {
4204 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4205 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4207 mono_error_cleanup (&error);
4211 tmp [i]->slot = gklass->vtable [i]->slot;
4213 mono_memory_barrier ();
4214 class->vtable = tmp;
4216 /* Have to set method->slot for abstract virtual methods */
4217 if (class->methods && gklass->methods) {
4218 for (i = 0; i < class->method.count; ++i)
4219 if (class->methods [i]->slot == -1)
4220 class->methods [i]->slot = gklass->methods [i]->slot;
4226 if (class->parent && class->parent->vtable_size) {
4227 MonoClass *parent = class->parent;
4230 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4232 // Also inherit parent interface vtables, just as a starting point.
4233 // This is needed otherwise bug-77127.exe fails when the property methods
4234 // have different names in the iterface and the class, because for child
4235 // classes the ".override" information is not used anymore.
4236 for (i = 0; i < parent->interface_offsets_count; i++) {
4237 MonoClass *parent_interface = parent->interfaces_packed [i];
4238 int interface_offset = mono_class_interface_offset (class, parent_interface);
4239 /*FIXME this is now dead code as this condition will never hold true.
4240 Since interface offsets are inherited then the offset of an interface implemented
4241 by a parent will never be the out of it's vtable boundary.
4243 if (interface_offset >= parent->vtable_size) {
4244 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4247 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4248 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4249 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4250 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4251 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4252 parent_interface_offset + j, parent_interface_offset, j,
4253 interface_offset + j, interface_offset, j));
4260 /*Array have a slot for stelemref*/
4261 if (mono_class_need_stelemref_method (class)) {
4262 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4264 method->slot = stelemref_slot;
4266 g_assert (method->slot == stelemref_slot);
4268 vtable [stelemref_slot] = method;
4271 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4272 /* override interface methods */
4273 for (i = 0; i < onum; i++) {
4274 MonoMethod *decl = overrides [i*2];
4275 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4277 dslot = mono_method_get_vtable_slot (decl);
4279 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4283 dslot += mono_class_interface_offset (class, decl->klass);
4284 vtable [dslot] = overrides [i*2 + 1];
4285 vtable [dslot]->slot = dslot;
4287 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4289 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4291 if (mono_security_core_clr_enabled ())
4292 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4295 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4296 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4299 * Create a list of virtual methods to avoid calling
4300 * mono_class_get_virtual_methods () which is slow because of the metadata
4304 gpointer iter = NULL;
4307 virt_methods = NULL;
4308 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4309 virt_methods = g_slist_prepend (virt_methods, cm);
4311 if (class->exception_type)
4315 // Loop on all implemented interfaces...
4316 for (i = 0; i < class->interface_offsets_count; i++) {
4317 MonoClass *parent = class->parent;
4319 gboolean interface_is_explicitly_implemented_by_class;
4322 ic = class->interfaces_packed [i];
4323 ic_offset = mono_class_interface_offset (class, ic);
4325 mono_class_setup_methods (ic);
4326 if (ic->exception_type)
4329 // Check if this interface is explicitly implemented (instead of just inherited)
4330 if (parent != NULL) {
4331 int implemented_interfaces_index;
4332 interface_is_explicitly_implemented_by_class = FALSE;
4333 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4334 if (ic == class->interfaces [implemented_interfaces_index]) {
4335 interface_is_explicitly_implemented_by_class = TRUE;
4340 interface_is_explicitly_implemented_by_class = TRUE;
4343 // Loop on all interface methods...
4344 for (im_index = 0; im_index < ic->method.count; im_index++) {
4345 MonoMethod *im = ic->methods [im_index];
4346 int im_slot = ic_offset + im->slot;
4347 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4349 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4352 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4354 // If there is an explicit implementation, just use it right away,
4355 // otherwise look for a matching method
4356 if (override_im == NULL) {
4361 // First look for a suitable method among the class methods
4363 for (l = virt_methods; l; l = l->next) {
4365 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)));
4366 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4367 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4368 vtable [im_slot] = cm;
4369 /* Why do we need this? */
4374 TRACE_INTERFACE_VTABLE (printf ("\n"));
4375 if (class->exception_type) /*Might be set by check_interface_method_override*/
4379 // If the slot is still empty, look in all the inherited virtual methods...
4380 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4381 MonoClass *parent = class->parent;
4382 // Reverse order, so that last added methods are preferred
4383 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4384 MonoMethod *cm = parent->vtable [cm_index];
4386 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));
4387 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4388 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4389 vtable [im_slot] = cm;
4390 /* Why do we need this? */
4396 if (class->exception_type) /*Might be set by check_interface_method_override*/
4398 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4402 g_assert (vtable [im_slot] == override_im);
4407 // If the class is not abstract, check that all its interface slots are full.
4408 // The check is done here and not directly at the end of the loop above because
4409 // it can happen (for injected generic array interfaces) that the same slot is
4410 // processed multiple times (those interfaces have overlapping slots), and it
4411 // will not always be the first pass the one that fills the slot.
4412 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4413 for (i = 0; i < class->interface_offsets_count; i++) {
4417 ic = class->interfaces_packed [i];
4418 ic_offset = mono_class_interface_offset (class, ic);
4420 for (im_index = 0; im_index < ic->method.count; im_index++) {
4421 MonoMethod *im = ic->methods [im_index];
4422 int im_slot = ic_offset + im->slot;
4424 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4427 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4428 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4429 if (vtable [im_slot] == NULL) {
4430 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4437 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4439 for (l = virt_methods; l; l = l->next) {
4442 * If the method is REUSE_SLOT, we must check in the
4443 * base class for a method to override.
4445 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4447 for (k = class->parent; k ; k = k->parent) {
4452 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4453 MonoMethodSignature *cmsig, *m1sig;
4455 cmsig = mono_method_signature (cm);
4456 m1sig = mono_method_signature (m1);
4458 if (!cmsig || !m1sig) {
4459 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4463 if (!strcmp(cm->name, m1->name) &&
4464 mono_metadata_signature_equal (cmsig, m1sig)) {
4466 /* CAS - SecurityAction.InheritanceDemand */
4467 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4468 mono_secman_inheritancedemand_method (cm, m1);
4471 if (mono_security_core_clr_enabled ())
4472 mono_security_core_clr_check_override (class, cm, m1);
4474 slot = mono_method_get_vtable_slot (m1);
4478 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4479 char *body_name = mono_method_full_name (cm, TRUE);
4480 char *decl_name = mono_method_full_name (m1, TRUE);
4481 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));
4487 g_assert (cm->slot < max_vtsize);
4489 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4490 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4491 mono_method_full_name (m1, 1), m1,
4492 mono_method_full_name (cm, 1), cm));
4493 g_hash_table_insert (override_map, m1, cm);
4497 if (k->exception_type)
4507 /*Non final newslot methods must be given a non-interface vtable slot*/
4508 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4512 cm->slot = cur_slot++;
4514 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4515 vtable [cm->slot] = cm;
4518 /* override non interface methods */
4519 for (i = 0; i < onum; i++) {
4520 MonoMethod *decl = overrides [i*2];
4521 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4522 g_assert (decl->slot != -1);
4523 vtable [decl->slot] = overrides [i*2 + 1];
4524 overrides [i * 2 + 1]->slot = decl->slot;
4526 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4527 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4528 mono_method_full_name (decl, 1), decl,
4529 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4530 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4532 if (mono_security_core_clr_enabled ())
4533 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4538 * If a method occupies more than one place in the vtable, and it is
4539 * overriden, then change the other occurances too.
4544 for (i = 0; i < max_vtsize; ++i)
4546 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4548 cm = g_hash_table_lookup (override_map, vtable [i]);
4553 g_hash_table_destroy (override_map);
4554 override_map = NULL;
4557 g_slist_free (virt_methods);
4558 virt_methods = NULL;
4560 /* Ensure that all vtable slots are filled with concrete instance methods */
4561 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4562 for (i = 0; i < cur_slot; ++i) {
4563 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4564 char *type_name = mono_type_get_full_name (class);
4565 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4566 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));
4568 g_free (method_name);
4574 if (class->generic_class) {
4575 MonoClass *gklass = class->generic_class->container_class;
4577 mono_class_init (gklass);
4579 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4581 /* Check that the vtable_size value computed in mono_class_init () is correct */
4582 if (class->vtable_size)
4583 g_assert (cur_slot == class->vtable_size);
4584 class->vtable_size = cur_slot;
4587 /* Try to share the vtable with our parent. */
4588 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4589 mono_memory_barrier ();
4590 class->vtable = class->parent->vtable;
4592 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4593 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4594 mono_memory_barrier ();
4595 class->vtable = tmp;
4598 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4599 if (mono_print_vtable) {
4602 print_implemented_interfaces (class);
4604 for (i = 0; i <= max_iid; i++)
4605 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4608 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4609 class->vtable_size, icount);
4611 for (i = 0; i < cur_slot; ++i) {
4616 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4617 mono_method_full_name (cm, TRUE));
4623 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4624 class->name, max_iid);
4626 for (i = 0; i < class->interface_count; i++) {
4627 ic = class->interfaces [i];
4628 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4629 mono_class_interface_offset (class, ic),
4630 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4633 for (k = class->parent; k ; k = k->parent) {
4634 for (i = 0; i < k->interface_count; i++) {
4635 ic = k->interfaces [i];
4636 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4637 mono_class_interface_offset (class, ic),
4638 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4644 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4649 char *name = mono_type_get_full_name (class);
4650 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4653 g_hash_table_destroy (override_map);
4655 g_slist_free (virt_methods);
4660 * mono_method_get_vtable_slot:
4662 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4663 * LOCKING: Acquires the loader lock.
4665 * FIXME Use proper MonoError machinery here.
4668 mono_method_get_vtable_slot (MonoMethod *method)
4670 if (method->slot == -1) {
4671 mono_class_setup_vtable (method->klass);
4672 if (method->klass->exception_type)
4674 if (method->slot == -1) {
4678 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4679 g_assert (method->klass->generic_class);
4680 gklass = method->klass->generic_class->container_class;
4681 mono_class_setup_methods (method->klass);
4682 g_assert (method->klass->methods);
4683 for (i = 0; i < method->klass->method.count; ++i) {
4684 if (method->klass->methods [i] == method)
4687 g_assert (i < method->klass->method.count);
4688 g_assert (gklass->methods);
4689 method->slot = gklass->methods [i]->slot;
4691 g_assert (method->slot != -1);
4693 return method->slot;
4697 * mono_method_get_vtable_index:
4700 * Returns the index into the runtime vtable to access the method or,
4701 * in the case of a virtual generic method, the virtual generic method
4702 * thunk. Returns -1 on failure.
4704 * FIXME Use proper MonoError machinery here.
4707 mono_method_get_vtable_index (MonoMethod *method)
4709 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4710 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4711 if (imethod->declaring->is_generic)
4712 return mono_method_get_vtable_slot (imethod->declaring);
4714 return mono_method_get_vtable_slot (method);
4717 static MonoMethod *default_ghc = NULL;
4718 static MonoMethod *default_finalize = NULL;
4719 static int finalize_slot = -1;
4720 static int ghc_slot = -1;
4723 initialize_object_slots (MonoClass *class)
4728 if (class == mono_defaults.object_class) {
4729 mono_class_setup_vtable (class);
4730 for (i = 0; i < class->vtable_size; ++i) {
4731 MonoMethod *cm = class->vtable [i];
4733 if (!strcmp (cm->name, "GetHashCode"))
4735 else if (!strcmp (cm->name, "Finalize"))
4739 g_assert (ghc_slot > 0);
4740 default_ghc = class->vtable [ghc_slot];
4742 g_assert (finalize_slot > 0);
4743 default_finalize = class->vtable [finalize_slot];
4748 MonoMethod *array_method;
4750 } GenericArrayMethodInfo;
4752 static int generic_array_method_num = 0;
4753 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4756 generic_array_methods (MonoClass *class)
4758 int i, count_generic = 0;
4759 GList *list = NULL, *tmp;
4760 if (generic_array_method_num)
4761 return generic_array_method_num;
4762 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4763 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4764 for (i = 0; i < class->parent->method.count; i++) {
4765 MonoMethod *m = class->parent->methods [i];
4766 if (!strncmp (m->name, "InternalArray__", 15)) {
4768 list = g_list_prepend (list, m);
4771 list = g_list_reverse (list);
4772 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4774 for (tmp = list; tmp; tmp = tmp->next) {
4775 const char *mname, *iname;
4777 MonoMethod *m = tmp->data;
4778 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4779 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4781 generic_array_method_info [i].array_method = m;
4782 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4783 iname = "System.Collections.Generic.ICollection`1.";
4784 mname = m->name + 27;
4785 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4786 iname = "System.Collections.Generic.IEnumerable`1.";
4787 mname = m->name + 27;
4788 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4789 iname = "System.Collections.Generic.IReadOnlyList`1.";
4790 mname = m->name + strlen (ireadonlylist_prefix);
4791 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4792 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4793 mname = m->name + strlen (ireadonlycollection_prefix);
4794 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4795 iname = "System.Collections.Generic.IList`1.";
4796 mname = m->name + 15;
4798 g_assert_not_reached ();
4801 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4802 strcpy (name, iname);
4803 strcpy (name + strlen (iname), mname);
4804 generic_array_method_info [i].name = name;
4807 /*g_print ("array generic methods: %d\n", count_generic);*/
4809 generic_array_method_num = count_generic;
4811 return generic_array_method_num;
4815 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4817 MonoGenericContext tmp_context;
4820 tmp_context.class_inst = NULL;
4821 tmp_context.method_inst = iface->generic_class->context.class_inst;
4822 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4824 for (i = 0; i < generic_array_method_num; i++) {
4825 MonoMethod *m = generic_array_method_info [i].array_method;
4826 MonoMethod *inflated;
4828 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4829 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4834 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4836 int null_length = strlen ("(null)");
4837 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4838 char *s = mono_image_alloc (image, len);
4841 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4842 g_assert (result == len - 1);
4848 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4850 gpointer exception_data = NULL;
4852 switch (error->exception_type) {
4853 case MONO_EXCEPTION_TYPE_LOAD:
4854 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4857 case MONO_EXCEPTION_MISSING_METHOD:
4858 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4861 case MONO_EXCEPTION_MISSING_FIELD: {
4862 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4863 const char *class_name;
4866 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4868 class_name = error->klass->name;
4870 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4873 g_free ((void*)class_name);
4877 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4880 if (error->ref_only)
4881 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.";
4883 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4885 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4889 case MONO_EXCEPTION_BAD_IMAGE:
4890 exception_data = error->msg;
4894 g_assert_not_reached ();
4897 mono_class_set_failure (class, error->exception_type, exception_data);
4902 * @class: the class to initialize
4904 * Compute the instance_size, class_size and other infos that cannot be
4905 * computed at mono_class_get() time. Also compute vtable_size if possible.
4906 * Returns TRUE on success or FALSE if there was a problem in loading
4907 * the type (incorrect assemblies, missing assemblies, methods, etc).
4909 * LOCKING: Acquires the loader lock.
4912 mono_class_init (MonoClass *class)
4915 MonoCachedClassInfo cached_info;
4916 gboolean has_cached_info;
4920 /* Double-checking locking pattern */
4921 if (class->inited || class->exception_type)
4922 return class->exception_type == MONO_EXCEPTION_NONE;
4924 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4926 /* We do everything inside the lock to prevent races */
4927 mono_loader_lock ();
4929 if (class->inited || class->exception_type) {
4930 mono_loader_unlock ();
4931 /* Somebody might have gotten in before us */
4932 return class->exception_type == MONO_EXCEPTION_NONE;
4935 if (class->init_pending) {
4936 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4940 class->init_pending = 1;
4942 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4943 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4948 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4949 MonoClass *element_class = class->element_class;
4950 if (!element_class->inited)
4951 mono_class_init (element_class);
4952 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4953 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4958 /* CAS - SecurityAction.InheritanceDemand */
4959 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4960 mono_secman_inheritancedemand_class (class, class->parent);
4963 mono_stats.initialized_class_count++;
4965 if (class->generic_class && !class->generic_class->is_dynamic) {
4966 MonoClass *gklass = class->generic_class->container_class;
4968 mono_stats.generic_class_count++;
4970 class->method = gklass->method;
4971 class->field = gklass->field;
4973 mono_class_init (gklass);
4974 // FIXME: Why is this needed ?
4975 if (!gklass->exception_type)
4976 mono_class_setup_methods (gklass);
4977 if (gklass->exception_type) {
4978 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4982 if (MONO_CLASS_IS_INTERFACE (class))
4983 class->interface_id = mono_get_unique_iid (class);
4986 if (class->parent && !class->parent->inited)
4987 mono_class_init (class->parent);
4989 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
4991 if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
4992 class->nested_classes_inited = TRUE;
4995 * Computes the size used by the fields, and their locations
4997 if (has_cached_info) {
4998 class->instance_size = cached_info.instance_size;
4999 class->sizes.class_size = cached_info.class_size;
5000 class->packing_size = cached_info.packing_size;
5001 class->min_align = cached_info.min_align;
5002 class->blittable = cached_info.blittable;
5003 class->has_references = cached_info.has_references;
5004 class->has_static_refs = cached_info.has_static_refs;
5005 class->no_special_static_fields = cached_info.no_special_static_fields;
5008 if (!class->size_inited){
5009 mono_class_setup_fields (class);
5010 if (class->exception_type || mono_loader_get_last_error ())
5014 /* Initialize arrays */
5016 class->method.count = 3 + (class->rank > 1? 2: 1);
5018 if (class->interface_count) {
5019 int count_generic = generic_array_methods (class);
5020 class->method.count += class->interface_count * count_generic;
5024 mono_class_setup_supertypes (class);
5027 initialize_object_slots (class);
5030 * Initialize the rest of the data without creating a generic vtable if possible.
5031 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5032 * also avoid computing a generic vtable.
5034 if (has_cached_info) {
5036 class->vtable_size = cached_info.vtable_size;
5037 class->has_finalize = cached_info.has_finalize;
5038 class->has_finalize_inited = TRUE;
5039 class->ghcimpl = cached_info.ghcimpl;
5040 class->has_cctor = cached_info.has_cctor;
5041 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5042 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5043 * The first slot if for array with.
5045 static int szarray_vtable_size[2] = { 0 };
5047 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5050 if (!szarray_vtable_size [slot]) {
5051 mono_class_setup_vtable (class);
5052 szarray_vtable_size [slot] = class->vtable_size;
5054 class->vtable_size = szarray_vtable_size[slot];
5056 class->has_finalize_inited = TRUE;
5057 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5058 MonoClass *gklass = class->generic_class->container_class;
5060 /* Generic instance case */
5061 class->ghcimpl = gklass->ghcimpl;
5062 class->has_finalize = mono_class_has_finalizer (gklass);
5063 class->has_finalize_inited = TRUE;
5064 class->has_cctor = gklass->has_cctor;
5066 mono_class_setup_vtable (gklass);
5067 if (gklass->exception_type) {
5068 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5072 class->vtable_size = gklass->vtable_size;
5076 /* ghcimpl is not currently used
5078 if (class->parent) {
5079 MonoMethod *cmethod = class->vtable [ghc_slot];
5080 if (cmethod->is_inflated)
5081 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5082 if (cmethod == default_ghc) {
5088 /* C# doesn't allow interfaces to have cctors */
5089 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5090 MonoMethod *cmethod = NULL;
5092 if (class->type_token) {
5093 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5094 /* The find_method function ignores the 'flags' argument */
5095 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5096 class->has_cctor = 1;
5098 mono_class_setup_methods (class);
5099 if (class->exception_type)
5102 for (i = 0; i < class->method.count; ++i) {
5103 MonoMethod *method = class->methods [i];
5104 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5105 (strcmp (".cctor", method->name) == 0)) {
5106 class->has_cctor = 1;
5114 if (class->parent) {
5115 int first_iface_slot;
5116 /* This will compute class->parent->vtable_size for some classes */
5117 mono_class_init (class->parent);
5118 if (class->parent->exception_type) {
5119 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5122 if (mono_loader_get_last_error ())
5124 if (!class->parent->vtable_size) {
5125 /* FIXME: Get rid of this somehow */
5126 mono_class_setup_vtable (class->parent);
5127 if (class->parent->exception_type) {
5128 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5131 if (mono_loader_get_last_error ())
5134 first_iface_slot = class->parent->vtable_size;
5135 if (mono_class_need_stelemref_method (class))
5137 setup_interface_offsets (class, first_iface_slot, TRUE);
5139 setup_interface_offsets (class, 0, TRUE);
5142 if (mono_security_core_clr_enabled ())
5143 mono_security_core_clr_check_inheritance (class);
5145 if (mono_loader_get_last_error ()) {
5146 if (class->exception_type == MONO_EXCEPTION_NONE) {
5147 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5149 mono_loader_clear_error ();
5152 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5153 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5158 /* Because of the double-checking locking pattern */
5159 mono_memory_barrier ();
5161 class->init_pending = 0;
5163 mono_loader_unlock ();
5165 if (mono_debugger_class_init_func)
5166 mono_debugger_class_init_func (class);
5168 return class->exception_type == MONO_EXCEPTION_NONE;
5172 * mono_class_has_finalizer:
5174 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5178 mono_class_has_finalizer (MonoClass *klass)
5180 if (!klass->has_finalize_inited) {
5181 MonoClass *class = klass;
5183 mono_loader_lock ();
5185 /* Interfaces and valuetypes are not supposed to have finalizers */
5186 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5187 MonoMethod *cmethod = NULL;
5189 if (class->parent && class->parent->has_finalize) {
5190 class->has_finalize = 1;
5192 if (class->parent) {
5194 * Can't search in metadata for a method named Finalize, because that
5195 * ignores overrides.
5197 mono_class_setup_vtable (class);
5198 if (class->exception_type || mono_loader_get_last_error ())
5200 cmethod = class->vtable [finalize_slot];
5204 g_assert (class->vtable_size > finalize_slot);
5206 class->has_finalize = 0;
5207 if (class->parent) {
5208 if (cmethod->is_inflated)
5209 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5210 if (cmethod != default_finalize) {
5211 class->has_finalize = 1;
5218 mono_memory_barrier ();
5219 klass->has_finalize_inited = TRUE;
5221 mono_loader_unlock ();
5224 return klass->has_finalize;
5227 mono_loader_unlock ();
5232 mono_is_corlib_image (MonoImage *image)
5234 /* FIXME: allow the dynamic case for our compilers and with full trust */
5236 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5238 return image == mono_defaults.corlib;
5242 * LOCKING: this assumes the loader lock is held
5245 mono_class_setup_mono_type (MonoClass *class)
5247 const char *name = class->name;
5248 const char *nspace = class->name_space;
5249 gboolean is_corlib = mono_is_corlib_image (class->image);
5251 class->this_arg.byref = 1;
5252 class->this_arg.data.klass = class;
5253 class->this_arg.type = MONO_TYPE_CLASS;
5254 class->byval_arg.data.klass = class;
5255 class->byval_arg.type = MONO_TYPE_CLASS;
5257 if (is_corlib && !strcmp (nspace, "System")) {
5258 if (!strcmp (name, "ValueType")) {
5260 * do not set the valuetype bit for System.ValueType.
5261 * class->valuetype = 1;
5263 class->blittable = TRUE;
5264 } else if (!strcmp (name, "Enum")) {
5266 * do not set the valuetype bit for System.Enum.
5267 * class->valuetype = 1;
5269 class->valuetype = 0;
5270 class->enumtype = 0;
5271 } else if (!strcmp (name, "Object")) {
5272 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5273 } else if (!strcmp (name, "String")) {
5274 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5275 } else if (!strcmp (name, "TypedReference")) {
5276 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5280 if (class->valuetype) {
5281 int t = MONO_TYPE_VALUETYPE;
5283 if (is_corlib && !strcmp (nspace, "System")) {
5286 if (!strcmp (name, "Boolean")) {
5287 t = MONO_TYPE_BOOLEAN;
5288 } else if (!strcmp(name, "Byte")) {
5290 class->blittable = TRUE;
5294 if (!strcmp (name, "Char")) {
5299 if (!strcmp (name, "Double")) {
5301 class->blittable = TRUE;
5305 if (!strcmp (name, "Int32")) {
5307 class->blittable = TRUE;
5308 } else if (!strcmp(name, "Int16")) {
5310 class->blittable = TRUE;
5311 } else if (!strcmp(name, "Int64")) {
5313 class->blittable = TRUE;
5314 } else if (!strcmp(name, "IntPtr")) {
5316 class->blittable = TRUE;
5320 if (!strcmp (name, "Single")) {
5322 class->blittable = TRUE;
5323 } else if (!strcmp(name, "SByte")) {
5325 class->blittable = TRUE;
5329 if (!strcmp (name, "UInt32")) {
5331 class->blittable = TRUE;
5332 } else if (!strcmp(name, "UInt16")) {
5334 class->blittable = TRUE;
5335 } else if (!strcmp(name, "UInt64")) {
5337 class->blittable = TRUE;
5338 } else if (!strcmp(name, "UIntPtr")) {
5340 class->blittable = TRUE;
5344 if (!strcmp (name, "TypedReference")) {
5345 t = MONO_TYPE_TYPEDBYREF;
5346 class->blittable = TRUE;
5350 if (!strcmp (name, "Void")) {
5358 class->this_arg.type = class->byval_arg.type = t;
5361 if (MONO_CLASS_IS_INTERFACE (class))
5362 class->interface_id = mono_get_unique_iid (class);
5368 * COM initialization is delayed until needed.
5369 * However when a [ComImport] attribute is present on a type it will trigger
5370 * the initialization. This is not a problem unless the BCL being executed
5371 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5374 init_com_from_comimport (MonoClass *class)
5376 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5377 if (mono_security_core_clr_enabled ()) {
5378 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5379 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5380 /* but it can not be made available for application (i.e. user code) since all COM calls
5381 * are considered native calls. In this case we fail with a TypeLoadException (just like
5382 * Silverlight 2 does */
5383 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5388 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5390 #endif /*DISABLE_COM*/
5393 * LOCKING: this assumes the loader lock is held
5396 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5398 gboolean system_namespace;
5399 gboolean is_corlib = mono_is_corlib_image (class->image);
5401 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5403 /* if root of the hierarchy */
5404 if (system_namespace && !strcmp (class->name, "Object")) {
5405 class->parent = NULL;
5406 class->instance_size = sizeof (MonoObject);
5409 if (!strcmp (class->name, "<Module>")) {
5410 class->parent = NULL;
5411 class->instance_size = 0;
5415 if (!MONO_CLASS_IS_INTERFACE (class)) {
5416 /* Imported COM Objects always derive from __ComObject. */
5418 if (MONO_CLASS_IS_IMPORT (class)) {
5419 init_com_from_comimport (class);
5420 if (parent == mono_defaults.object_class)
5421 parent = mono_class_get_com_object_class ();
5425 /* set the parent to something useful and safe, but mark the type as broken */
5426 parent = mono_defaults.object_class;
5427 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5430 class->parent = parent;
5432 if (parent->generic_class && !parent->name) {
5434 * If the parent is a generic instance, we may get
5435 * called before it is fully initialized, especially
5436 * before it has its name.
5441 #ifndef DISABLE_REMOTING
5442 class->marshalbyref = parent->marshalbyref;
5443 class->contextbound = parent->contextbound;
5446 class->delegate = parent->delegate;
5448 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5449 mono_class_set_is_com_object (class);
5451 if (system_namespace) {
5452 #ifndef DISABLE_REMOTING
5453 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5454 class->marshalbyref = 1;
5456 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5457 class->contextbound = 1;
5459 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5460 class->delegate = 1;
5463 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5464 (strcmp (class->parent->name_space, "System") == 0)))
5465 class->valuetype = 1;
5466 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5467 class->valuetype = class->enumtype = 1;
5469 /*class->enumtype = class->parent->enumtype; */
5471 /* initialize com types if COM interfaces are present */
5473 if (MONO_CLASS_IS_IMPORT (class))
5474 init_com_from_comimport (class);
5476 class->parent = NULL;
5482 * mono_class_setup_supertypes:
5485 * Build the data structure needed to make fast type checks work.
5486 * This currently sets two fields in @class:
5487 * - idepth: distance between @class and System.Object in the type
5489 * - supertypes: array of classes: each element has a class in the hierarchy
5490 * starting from @class up to System.Object
5492 * LOCKING: This function is atomic, in case of contention we waste memory.
5495 mono_class_setup_supertypes (MonoClass *class)
5498 MonoClass **supertypes;
5500 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5504 if (class->parent && !class->parent->supertypes)
5505 mono_class_setup_supertypes (class->parent);
5507 class->idepth = class->parent->idepth + 1;
5511 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5512 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5514 if (class->parent) {
5515 supertypes [class->idepth - 1] = class;
5516 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5518 supertypes [0] = class;
5521 mono_atomic_store_release (&class->supertypes, supertypes);
5525 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5527 MonoClass *gtd = (MonoClass*)user_data;
5528 /* Only try to fix generic instances of @gtd */
5529 if (gclass->generic_class->container_class != gtd)
5532 /* Check if the generic instance has no parent. */
5533 if (gtd->parent && !gclass->parent)
5534 mono_generic_class_setup_parent (gclass, gtd);
5540 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5542 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5543 mono_error_set_type_load_class (error, class, msg);
5547 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5549 MonoLoaderError *lerror = mono_loader_get_last_error ();
5552 set_failure_from_loader_error (class, lerror);
5553 mono_error_set_from_loader_error (error);
5557 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5558 mono_error_set_type_load_class (error, class, msg);
5563 * mono_class_create_from_typedef:
5564 * @image: image where the token is valid
5565 * @type_token: typedef token
5566 * @error: used to return any error found while creating the type
5568 * Create the MonoClass* representing the specified type token.
5569 * @type_token must be a TypeDef token.
5571 * FIXME: don't return NULL on failure, just the the caller figure it out.
5574 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5576 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5577 MonoClass *class, *parent = NULL;
5578 guint32 cols [MONO_TYPEDEF_SIZE];
5579 guint32 cols_next [MONO_TYPEDEF_SIZE];
5580 guint tidx = mono_metadata_token_index (type_token);
5581 MonoGenericContext *context = NULL;
5582 const char *name, *nspace;
5584 MonoClass **interfaces;
5585 guint32 field_last, method_last;
5586 guint32 nesting_tokeen;
5588 mono_error_init (error);
5590 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5591 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5592 g_assert (!mono_loader_get_last_error ());
5596 mono_loader_lock ();
5598 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5599 mono_loader_unlock ();
5600 g_assert (!mono_loader_get_last_error ());
5604 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5606 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5607 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5609 class = mono_image_alloc0 (image, sizeof (MonoClass));
5612 class->name_space = nspace;
5614 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5616 class->image = image;
5617 class->type_token = type_token;
5618 class->flags = cols [MONO_TYPEDEF_FLAGS];
5620 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5622 classes_size += sizeof (MonoClass);
5625 * Check whether we're a generic type definition.
5627 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5628 if (class->generic_container) {
5629 class->is_generic = 1;
5630 class->generic_container->owner.klass = class;
5631 context = &class->generic_container->context;
5634 if (class->generic_container)
5635 enable_gclass_recording ();
5637 if (cols [MONO_TYPEDEF_EXTENDS]) {
5639 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5641 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5642 /*WARNING: this must satisfy mono_metadata_type_hash*/
5643 class->this_arg.byref = 1;
5644 class->this_arg.data.klass = class;
5645 class->this_arg.type = MONO_TYPE_CLASS;
5646 class->byval_arg.data.klass = class;
5647 class->byval_arg.type = MONO_TYPE_CLASS;
5649 parent = mono_class_get_full (image, parent_token, context);
5651 if (parent == NULL) {
5652 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5653 goto parent_failure;
5656 for (tmp = parent; tmp; tmp = tmp->parent) {
5658 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5659 goto parent_failure;
5661 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5662 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5663 goto parent_failure;
5668 mono_class_setup_parent (class, parent);
5670 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5671 mono_class_setup_mono_type (class);
5673 if (class->generic_container)
5674 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5677 * This might access class->byval_arg for recursion generated by generic constraints,
5678 * so it has to come after setup_mono_type ().
5680 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5681 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5682 if (!mono_error_ok (error)) {
5683 /*FIXME implement a mono_class_set_failure_from_mono_error */
5684 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5685 mono_loader_unlock ();
5686 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5687 g_assert (!mono_loader_get_last_error ());
5692 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5696 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5700 class->cast_class = class->element_class = class;
5702 if (!class->enumtype) {
5703 if (!mono_metadata_interfaces_from_typedef_full (
5704 image, type_token, &interfaces, &icount, FALSE, context)){
5705 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5706 mono_loader_unlock ();
5707 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5711 class->interfaces = interfaces;
5712 class->interface_count = icount;
5713 class->interfaces_inited = 1;
5716 /*g_print ("Load class %s\n", name);*/
5719 * Compute the field and method lists
5721 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5722 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5724 if (tt->rows > tidx){
5725 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5726 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5727 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5729 field_last = image->tables [MONO_TABLE_FIELD].rows;
5730 method_last = image->tables [MONO_TABLE_METHOD].rows;
5733 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5734 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5735 class->field.count = field_last - class->field.first;
5737 class->field.count = 0;
5739 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5740 class->method.count = method_last - class->method.first;
5742 class->method.count = 0;
5744 /* reserve space to store vector pointer in arrays */
5745 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5746 class->instance_size += 2 * sizeof (gpointer);
5747 g_assert (class->field.count == 0);
5750 if (class->enumtype) {
5751 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5752 if (!enum_basetype) {
5753 /*set it to a default value as the whole runtime can't handle this to be null*/
5754 class->cast_class = class->element_class = mono_defaults.int32_class;
5755 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5756 mono_loader_unlock ();
5757 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5758 g_assert (!mono_loader_get_last_error ());
5761 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5765 * If we're a generic type definition, load the constraints.
5766 * We must do this after the class has been constructed to make certain recursive scenarios
5769 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5770 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5771 mono_loader_unlock ();
5772 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5773 g_assert (!mono_loader_get_last_error ());
5777 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5778 if (!strncmp (name, "Vector", 6))
5779 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");
5782 mono_loader_unlock ();
5784 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5785 g_assert (!mono_loader_get_last_error ());
5790 mono_class_setup_mono_type (class);
5791 mono_loader_unlock ();
5792 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5793 g_assert (!mono_loader_get_last_error ());
5797 /** is klass Nullable<T>? */
5799 mono_class_is_nullable (MonoClass *klass)
5801 return klass->generic_class != NULL &&
5802 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5806 /** if klass is T? return T */
5808 mono_class_get_nullable_param (MonoClass *klass)
5810 g_assert (mono_class_is_nullable (klass));
5811 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5815 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5819 MonoGenericClass *gclass = klass->generic_class;
5821 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5822 if (!mono_error_ok (&error)) {
5823 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5824 klass->parent = mono_defaults.object_class;
5825 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5826 mono_error_cleanup (&error);
5830 mono_class_setup_parent (klass, klass->parent);
5832 if (klass->enumtype) {
5833 klass->cast_class = gtd->cast_class;
5834 klass->element_class = gtd->element_class;
5840 * Create the `MonoClass' for an instantiation of a generic type.
5841 * We only do this if we actually need it.
5844 mono_generic_class_get_class (MonoGenericClass *gclass)
5846 MonoClass *klass, *gklass;
5848 if (gclass->cached_class)
5849 return gclass->cached_class;
5851 mono_loader_lock ();
5852 if (gclass->cached_class) {
5853 mono_loader_unlock ();
5854 return gclass->cached_class;
5857 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5859 gklass = gclass->container_class;
5861 if (record_gclass_instantiation > 0)
5862 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5864 if (gklass->nested_in) {
5865 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5866 klass->nested_in = gklass->nested_in;
5869 klass->name = gklass->name;
5870 klass->name_space = gklass->name_space;
5872 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5874 klass->image = gklass->image;
5875 klass->flags = gklass->flags;
5876 klass->type_token = gklass->type_token;
5877 klass->field.count = gklass->field.count;
5879 klass->is_inflated = 1;
5880 klass->generic_class = gclass;
5882 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5883 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5884 klass->this_arg.byref = TRUE;
5885 klass->enumtype = gklass->enumtype;
5886 klass->valuetype = gklass->valuetype;
5888 klass->cast_class = klass->element_class = klass;
5890 if (mono_class_is_nullable (klass))
5891 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5894 * We're not interested in the nested classes of a generic instance.
5895 * We use the generic type definition to look for nested classes.
5898 mono_generic_class_setup_parent (klass, gklass);
5900 if (gclass->is_dynamic) {
5903 mono_class_setup_supertypes (klass);
5905 if (klass->enumtype) {
5907 * For enums, gklass->fields might not been set, but instance_size etc. is
5908 * already set in mono_reflection_create_internal_class (). For non-enums,
5909 * these will be computed normally in mono_class_layout_fields ().
5911 klass->instance_size = gklass->instance_size;
5912 klass->sizes.class_size = gklass->sizes.class_size;
5913 mono_memory_barrier ();
5914 klass->size_inited = 1;
5918 mono_memory_barrier ();
5919 gclass->cached_class = klass;
5921 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5923 inflated_classes ++;
5924 inflated_classes_size += sizeof (MonoClass);
5926 mono_loader_unlock ();
5932 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5934 MonoClass *klass, **ptr;
5936 MonoGenericContainer *container = mono_generic_param_owner (param);
5940 image = mono_defaults.corlib;
5942 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5943 classes_size += sizeof (MonoClass);
5946 klass->name = pinfo->name;
5948 int n = mono_generic_param_num (param);
5949 klass->name = mono_image_alloc0 (image, 16);
5950 sprintf ((char*)klass->name, "%d", n);
5955 MonoMethod *omethod = container->owner.method;
5956 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5958 MonoClass *oklass = container->owner.klass;
5959 klass->name_space = oklass ? oklass->name_space : "";
5962 klass->name_space = "";
5965 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5969 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5973 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5974 klass->parent = pinfo->constraints [0];
5976 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5977 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5979 klass->parent = mono_defaults.object_class;
5982 if (count - pos > 0) {
5983 klass->interface_count = count - pos;
5984 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5985 klass->interfaces_inited = TRUE;
5986 for (i = pos; i < count; i++)
5987 klass->interfaces [i - pos] = pinfo->constraints [i];
5990 klass->image = image;
5992 klass->inited = TRUE;
5993 klass->cast_class = klass->element_class = klass;
5994 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5996 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5997 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5998 klass->this_arg.byref = TRUE;
6000 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6001 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6003 /*Init these fields to sane values*/
6004 klass->min_align = 1;
6005 klass->instance_size = sizeof (gpointer);
6006 mono_memory_barrier ();
6007 klass->size_inited = 1;
6009 mono_class_setup_supertypes (klass);
6011 if (count - pos > 0) {
6012 mono_class_setup_vtable (klass->parent);
6013 if (klass->parent->exception_type)
6014 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6016 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6022 #define FAST_CACHE_SIZE 16
6025 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6027 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6028 MonoImage *image = param->image;
6033 if (n < FAST_CACHE_SIZE) {
6035 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6037 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6039 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6040 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6045 * LOCKING: Acquires the loader lock.
6048 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6050 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6051 MonoImage *image = param->image;
6056 if (n < FAST_CACHE_SIZE) {
6058 /* No locking needed */
6059 if (!image->mvar_cache_fast)
6060 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6061 image->mvar_cache_fast [n] = klass;
6063 if (!image->var_cache_fast)
6064 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6065 image->var_cache_fast [n] = klass;
6069 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6071 mono_loader_lock ();
6072 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6074 ht = g_hash_table_new (NULL, NULL);
6075 mono_memory_barrier ();
6077 image->mvar_cache_slow = ht;
6079 image->var_cache_slow = ht;
6081 mono_loader_unlock ();
6084 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6088 * LOCKING: Acquires the loader lock.
6091 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6093 MonoGenericContainer *container = mono_generic_param_owner (param);
6094 MonoGenericParamInfo *pinfo;
6097 mono_loader_lock ();
6100 pinfo = mono_generic_param_info (param);
6101 if (pinfo->pklass) {
6102 mono_loader_unlock ();
6103 return pinfo->pklass;
6109 klass = get_anon_gparam_class (param, is_mvar);
6111 mono_loader_unlock ();
6116 if (!image && container) {
6118 MonoMethod *method = container->owner.method;
6119 image = (method && method->klass) ? method->klass->image : NULL;
6121 MonoClass *klass = container->owner.klass;
6122 // FIXME: 'klass' should not be null
6123 // But, monodis creates GenericContainers without associating a owner to it
6124 image = klass ? klass->image : NULL;
6128 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6130 mono_memory_barrier ();
6133 pinfo->pklass = klass;
6135 set_anon_gparam_class (param, is_mvar, klass);
6137 mono_loader_unlock ();
6139 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6140 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6146 mono_ptr_class_get (MonoType *type)
6149 MonoClass *el_class;
6153 el_class = mono_class_from_mono_type (type);
6154 image = el_class->image;
6156 mono_loader_lock ();
6158 if (!image->ptr_cache)
6159 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6161 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6162 mono_loader_unlock ();
6165 result = mono_image_alloc0 (image, sizeof (MonoClass));
6167 classes_size += sizeof (MonoClass);
6169 result->parent = NULL; /* no parent for PTR types */
6170 result->name_space = el_class->name_space;
6171 name = g_strdup_printf ("%s*", el_class->name);
6172 result->name = mono_image_strdup (image, name);
6175 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6177 result->image = el_class->image;
6178 result->inited = TRUE;
6179 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6180 /* Can pointers get boxed? */
6181 result->instance_size = sizeof (gpointer);
6182 result->cast_class = result->element_class = el_class;
6183 result->blittable = TRUE;
6185 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6186 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6187 result->this_arg.byref = TRUE;
6189 mono_class_setup_supertypes (result);
6191 g_hash_table_insert (image->ptr_cache, el_class, result);
6193 mono_loader_unlock ();
6195 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6201 mono_fnptr_class_get (MonoMethodSignature *sig)
6204 static GHashTable *ptr_hash = NULL;
6206 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6208 mono_loader_lock ();
6211 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6213 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6214 mono_loader_unlock ();
6217 result = g_new0 (MonoClass, 1);
6219 result->parent = NULL; /* no parent for PTR types */
6220 result->name_space = "System";
6221 result->name = "MonoFNPtrFakeClass";
6223 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6225 result->image = mono_defaults.corlib; /* need to fix... */
6226 result->inited = TRUE;
6227 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6228 /* Can pointers get boxed? */
6229 result->instance_size = sizeof (gpointer);
6230 result->cast_class = result->element_class = result;
6231 result->blittable = TRUE;
6233 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6234 result->this_arg.data.method = result->byval_arg.data.method = sig;
6235 result->this_arg.byref = TRUE;
6236 result->blittable = TRUE;
6238 mono_class_setup_supertypes (result);
6240 g_hash_table_insert (ptr_hash, sig, result);
6242 mono_loader_unlock ();
6244 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6250 mono_class_from_mono_type (MonoType *type)
6252 switch (type->type) {
6253 case MONO_TYPE_OBJECT:
6254 return type->data.klass? type->data.klass: mono_defaults.object_class;
6255 case MONO_TYPE_VOID:
6256 return type->data.klass? type->data.klass: mono_defaults.void_class;
6257 case MONO_TYPE_BOOLEAN:
6258 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6259 case MONO_TYPE_CHAR:
6260 return type->data.klass? type->data.klass: mono_defaults.char_class;
6262 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6264 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6266 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6268 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6270 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6272 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6274 return type->data.klass? type->data.klass: mono_defaults.int_class;
6276 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6278 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6280 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6282 return type->data.klass? type->data.klass: mono_defaults.single_class;
6284 return type->data.klass? type->data.klass: mono_defaults.double_class;
6285 case MONO_TYPE_STRING:
6286 return type->data.klass? type->data.klass: mono_defaults.string_class;
6287 case MONO_TYPE_TYPEDBYREF:
6288 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6289 case MONO_TYPE_ARRAY:
6290 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6292 return mono_ptr_class_get (type->data.type);
6293 case MONO_TYPE_FNPTR:
6294 return mono_fnptr_class_get (type->data.method);
6295 case MONO_TYPE_SZARRAY:
6296 return mono_array_class_get (type->data.klass, 1);
6297 case MONO_TYPE_CLASS:
6298 case MONO_TYPE_VALUETYPE:
6299 return type->data.klass;
6300 case MONO_TYPE_GENERICINST:
6301 return mono_generic_class_get_class (type->data.generic_class);
6303 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6304 case MONO_TYPE_MVAR:
6305 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6307 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6308 g_assert_not_reached ();
6315 * mono_type_retrieve_from_typespec
6316 * @image: context where the image is created
6317 * @type_spec: typespec token
6318 * @context: the generic context used to evaluate generic instantiations in
6321 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6323 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6325 mono_error_init (error);
6326 *did_inflate = FALSE;
6329 char *name = mono_class_name_from_token (image, type_spec);
6330 char *assembly = mono_assembly_name_from_token (image, type_spec);
6331 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6335 if (context && (context->class_inst || context->method_inst)) {
6336 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6338 if (!mono_error_ok (error))
6343 *did_inflate = TRUE;
6350 * mono_class_create_from_typespec
6351 * @image: context where the image is created
6352 * @type_spec: typespec token
6353 * @context: the generic context used to evaluate generic instantiations in
6356 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6359 gboolean inflated = FALSE;
6360 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6361 if (!mono_error_ok (error))
6363 ret = mono_class_from_mono_type (t);
6365 mono_metadata_free_type (t);
6370 * mono_bounded_array_class_get:
6371 * @element_class: element class
6372 * @rank: the dimension of the array class
6373 * @bounded: whenever the array has non-zero bounds
6375 * Returns: a class object describing the array with element type @element_type and
6379 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6383 MonoClass *parent = NULL;
6384 GSList *list, *rootlist = NULL;
6387 gboolean corlib_type = FALSE;
6389 g_assert (rank <= 255);
6392 /* bounded only matters for one-dimensional arrays */
6395 image = eclass->image;
6397 if (rank == 1 && !bounded) {
6399 * This case is very frequent not just during compilation because of calls
6400 * from mono_class_from_mono_type (), mono_array_new (),
6401 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6403 EnterCriticalSection (&image->szarray_cache_lock);
6404 if (!image->szarray_cache)
6405 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6406 class = g_hash_table_lookup (image->szarray_cache, eclass);
6407 LeaveCriticalSection (&image->szarray_cache_lock);
6411 mono_loader_lock ();
6413 mono_loader_lock ();
6415 if (!image->array_cache)
6416 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6418 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6419 for (; list; list = list->next) {
6421 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6422 mono_loader_unlock ();
6429 /* for the building corlib use System.Array from it */
6430 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6431 parent = mono_class_from_name (image, "System", "Array");
6434 parent = mono_defaults.array_class;
6435 if (!parent->inited)
6436 mono_class_init (parent);
6439 class = mono_image_alloc0 (image, sizeof (MonoClass));
6441 class->image = image;
6442 class->name_space = eclass->name_space;
6443 nsize = strlen (eclass->name);
6444 name = g_malloc (nsize + 2 + rank + 1);
6445 memcpy (name, eclass->name, nsize);
6448 memset (name + nsize + 1, ',', rank - 1);
6450 name [nsize + rank] = '*';
6451 name [nsize + rank + bounded] = ']';
6452 name [nsize + rank + bounded + 1] = 0;
6453 class->name = mono_image_strdup (image, name);
6456 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6458 classes_size += sizeof (MonoClass);
6460 class->type_token = 0;
6461 /* all arrays are marked serializable and sealed, bug #42779 */
6462 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6463 class->parent = parent;
6464 class->instance_size = mono_class_instance_size (class->parent);
6466 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6467 /*Arrays of those two types are invalid.*/
6468 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6469 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6470 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6471 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6472 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6474 /* element_size -1 is ok as this is not an instantitable type*/
6475 class->sizes.element_size = -1;
6477 class->sizes.element_size = mono_class_array_element_size (eclass);
6479 mono_class_setup_supertypes (class);
6481 if (eclass->generic_class)
6482 mono_class_init (eclass);
6483 if (!eclass->size_inited)
6484 mono_class_setup_fields (eclass);
6485 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6486 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6488 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6492 if (eclass->enumtype)
6493 class->cast_class = eclass->element_class;
6495 class->cast_class = eclass;
6497 switch (class->cast_class->byval_arg.type) {
6499 class->cast_class = mono_defaults.byte_class;
6502 class->cast_class = mono_defaults.int16_class;
6505 #if SIZEOF_VOID_P == 4
6509 class->cast_class = mono_defaults.int32_class;
6512 #if SIZEOF_VOID_P == 8
6516 class->cast_class = mono_defaults.int64_class;
6520 class->element_class = eclass;
6522 if ((rank > 1) || bounded) {
6523 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6524 class->byval_arg.type = MONO_TYPE_ARRAY;
6525 class->byval_arg.data.array = at;
6526 at->eklass = eclass;
6528 /* FIXME: complete.... */
6530 class->byval_arg.type = MONO_TYPE_SZARRAY;
6531 class->byval_arg.data.klass = eclass;
6533 class->this_arg = class->byval_arg;
6534 class->this_arg.byref = 1;
6539 class->generic_container = eclass->generic_container;
6541 if (rank == 1 && !bounded) {
6542 MonoClass *prev_class;
6544 EnterCriticalSection (&image->szarray_cache_lock);
6545 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6547 /* Someone got in before us */
6550 g_hash_table_insert (image->szarray_cache, eclass, class);
6551 LeaveCriticalSection (&image->szarray_cache_lock);
6553 list = g_slist_append (rootlist, class);
6554 g_hash_table_insert (image->array_cache, eclass, list);
6557 mono_loader_unlock ();
6559 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6565 * mono_array_class_get:
6566 * @element_class: element class
6567 * @rank: the dimension of the array class
6569 * Returns: a class object describing the array with element type @element_type and
6573 mono_array_class_get (MonoClass *eclass, guint32 rank)
6575 return mono_bounded_array_class_get (eclass, rank, FALSE);
6579 * mono_class_instance_size:
6582 * Returns: the size of an object instance
6585 mono_class_instance_size (MonoClass *klass)
6587 if (!klass->size_inited)
6588 mono_class_init (klass);
6590 return klass->instance_size;
6594 * mono_class_min_align:
6597 * Returns: minimm alignment requirements
6600 mono_class_min_align (MonoClass *klass)
6602 if (!klass->size_inited)
6603 mono_class_init (klass);
6605 return klass->min_align;
6609 * mono_class_value_size:
6612 * This function is used for value types, and return the
6613 * space and the alignment to store that kind of value object.
6615 * Returns: the size of a value of kind @klass
6618 mono_class_value_size (MonoClass *klass, guint32 *align)
6622 /* fixme: check disable, because we still have external revereces to
6623 * mscorlib and Dummy Objects
6625 /*g_assert (klass->valuetype);*/
6627 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6630 *align = klass->min_align;
6636 * mono_class_data_size:
6639 * Returns: the size of the static class data
6642 mono_class_data_size (MonoClass *klass)
6645 mono_class_init (klass);
6646 /* This can happen with dynamically created types */
6647 if (!klass->fields_inited)
6648 mono_class_setup_fields_locking (klass);
6650 /* in arrays, sizes.class_size is unioned with element_size
6651 * and arrays have no static fields
6655 return klass->sizes.class_size;
6659 * Auxiliary routine to mono_class_get_field
6661 * Takes a field index instead of a field token.
6663 static MonoClassField *
6664 mono_class_get_field_idx (MonoClass *class, int idx)
6666 mono_class_setup_fields_locking (class);
6667 if (class->exception_type)
6671 if (class->image->uncompressed_metadata) {
6673 * class->field.first points to the FieldPtr table, while idx points into the
6674 * Field table, so we have to do a search.
6676 /*FIXME this is broken for types with multiple fields with the same name.*/
6677 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6680 for (i = 0; i < class->field.count; ++i)
6681 if (mono_field_get_name (&class->fields [i]) == name)
6682 return &class->fields [i];
6683 g_assert_not_reached ();
6685 if (class->field.count) {
6686 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6687 return &class->fields [idx - class->field.first];
6691 class = class->parent;
6697 * mono_class_get_field:
6698 * @class: the class to lookup the field.
6699 * @field_token: the field token
6701 * Returns: A MonoClassField representing the type and offset of
6702 * the field, or a NULL value if the field does not belong to this
6706 mono_class_get_field (MonoClass *class, guint32 field_token)
6708 int idx = mono_metadata_token_index (field_token);
6710 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6712 return mono_class_get_field_idx (class, idx - 1);
6716 * mono_class_get_field_from_name:
6717 * @klass: the class to lookup the field.
6718 * @name: the field name
6720 * Search the class @klass and it's parents for a field with the name @name.
6722 * Returns: the MonoClassField pointer of the named field or NULL
6725 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6727 return mono_class_get_field_from_name_full (klass, name, NULL);
6731 * mono_class_get_field_from_name_full:
6732 * @klass: the class to lookup the field.
6733 * @name: the field name
6734 * @type: the type of the fields. This optional.
6736 * Search the class @klass and it's parents for a field with the name @name and type @type.
6738 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6739 * of its generic type definition.
6741 * Returns: the MonoClassField pointer of the named field or NULL
6744 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6748 mono_class_setup_fields_locking (klass);
6749 if (klass->exception_type)
6753 for (i = 0; i < klass->field.count; ++i) {
6754 MonoClassField *field = &klass->fields [i];
6756 if (strcmp (name, mono_field_get_name (field)) != 0)
6760 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6761 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6766 klass = klass->parent;
6772 * mono_class_get_field_token:
6773 * @field: the field we need the token of
6775 * Get the token of a field. Note that the tokesn is only valid for the image
6776 * the field was loaded from. Don't use this function for fields in dynamic types.
6778 * Returns: the token representing the field in the image it was loaded from.
6781 mono_class_get_field_token (MonoClassField *field)
6783 MonoClass *klass = field->parent;
6786 mono_class_setup_fields_locking (klass);
6791 for (i = 0; i < klass->field.count; ++i) {
6792 if (&klass->fields [i] == field) {
6793 int idx = klass->field.first + i + 1;
6795 if (klass->image->uncompressed_metadata)
6796 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6797 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6800 klass = klass->parent;
6803 g_assert_not_reached ();
6808 mono_field_get_index (MonoClassField *field)
6810 int index = field - field->parent->fields;
6812 g_assert (index >= 0 && index < field->parent->field.count);
6818 * mono_class_get_field_default_value:
6820 * Return the default value of the field as a pointer into the metadata blob.
6823 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6826 guint32 constant_cols [MONO_CONSTANT_SIZE];
6828 MonoClass *klass = field->parent;
6830 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6832 if (!klass->ext || !klass->ext->field_def_values) {
6833 mono_loader_lock ();
6834 mono_class_alloc_ext (klass);
6835 if (!klass->ext->field_def_values)
6836 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6837 mono_loader_unlock ();
6840 field_index = mono_field_get_index (field);
6842 if (!klass->ext->field_def_values [field_index].data) {
6843 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6847 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6849 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6850 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6851 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6854 *def_type = klass->ext->field_def_values [field_index].def_type;
6855 return klass->ext->field_def_values [field_index].data;
6859 mono_property_get_index (MonoProperty *prop)
6861 int index = prop - prop->parent->ext->properties;
6863 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6869 * mono_class_get_property_default_value:
6871 * Return the default value of the field as a pointer into the metadata blob.
6874 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6877 guint32 constant_cols [MONO_CONSTANT_SIZE];
6878 MonoClass *klass = property->parent;
6880 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6882 * We don't cache here because it is not used by C# so it's quite rare, but
6883 * we still do the lookup in klass->ext because that is where the data
6884 * is stored for dynamic assemblies.
6887 if (klass->image->dynamic) {
6888 int prop_index = mono_property_get_index (property);
6889 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6890 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6891 return klass->ext->prop_def_values [prop_index].data;
6895 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6899 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6900 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6901 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6905 mono_class_get_event_token (MonoEvent *event)
6907 MonoClass *klass = event->parent;
6912 for (i = 0; i < klass->ext->event.count; ++i) {
6913 if (&klass->ext->events [i] == event)
6914 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6917 klass = klass->parent;
6920 g_assert_not_reached ();
6925 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6929 gpointer iter = NULL;
6930 while ((p = mono_class_get_properties (klass, &iter))) {
6931 if (! strcmp (name, p->name))
6934 klass = klass->parent;
6940 mono_class_get_property_token (MonoProperty *prop)
6942 MonoClass *klass = prop->parent;
6946 gpointer iter = NULL;
6947 while ((p = mono_class_get_properties (klass, &iter))) {
6948 if (&klass->ext->properties [i] == prop)
6949 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6953 klass = klass->parent;
6956 g_assert_not_reached ();
6961 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6963 const char *name, *nspace;
6965 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6967 switch (type_token & 0xff000000){
6968 case MONO_TOKEN_TYPE_DEF: {
6969 guint32 cols [MONO_TYPEDEF_SIZE];
6970 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6971 guint tidx = mono_metadata_token_index (type_token);
6973 if (tidx > tt->rows)
6974 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6976 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6977 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6978 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6979 if (strlen (nspace) == 0)
6980 return g_strdup_printf ("%s", name);
6982 return g_strdup_printf ("%s.%s", nspace, name);
6985 case MONO_TOKEN_TYPE_REF: {
6987 guint32 cols [MONO_TYPEREF_SIZE];
6988 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6989 guint tidx = mono_metadata_token_index (type_token);
6992 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6994 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6995 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6996 mono_error_cleanup (&error);
7000 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7001 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7002 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7003 if (strlen (nspace) == 0)
7004 return g_strdup_printf ("%s", name);
7006 return g_strdup_printf ("%s.%s", nspace, name);
7009 case MONO_TOKEN_TYPE_SPEC:
7010 return g_strdup_printf ("Typespec 0x%08x", type_token);
7012 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7017 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7020 return g_strdup_printf ("DynamicAssembly %s", image->name);
7022 switch (type_token & 0xff000000){
7023 case MONO_TOKEN_TYPE_DEF:
7024 if (image->assembly)
7025 return mono_stringify_assembly_name (&image->assembly->aname);
7026 else if (image->assembly_name)
7027 return g_strdup (image->assembly_name);
7028 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7029 case MONO_TOKEN_TYPE_REF: {
7031 MonoAssemblyName aname;
7032 guint32 cols [MONO_TYPEREF_SIZE];
7033 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7034 guint32 idx = mono_metadata_token_index (type_token);
7037 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7039 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7040 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7041 mono_error_cleanup (&error);
7044 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7046 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7047 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7048 case MONO_RESOLTION_SCOPE_MODULE:
7050 return g_strdup ("");
7051 case MONO_RESOLTION_SCOPE_MODULEREF:
7053 return g_strdup ("");
7054 case MONO_RESOLTION_SCOPE_TYPEREF:
7056 return g_strdup ("");
7057 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7058 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7059 return mono_stringify_assembly_name (&aname);
7061 g_assert_not_reached ();
7065 case MONO_TOKEN_TYPE_SPEC:
7067 return g_strdup ("");
7069 g_assert_not_reached ();
7076 * mono_class_get_full:
7077 * @image: the image where the class resides
7078 * @type_token: the token for the class
7079 * @context: the generic context used to evaluate generic instantiations in
7081 * Returns: the MonoClass that represents @type_token in @image
7084 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7087 MonoClass *class = NULL;
7089 if (image->dynamic) {
7090 int table = mono_metadata_token_table (type_token);
7092 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7093 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7096 return mono_lookup_dynamic_token (image, type_token, context);
7099 switch (type_token & 0xff000000){
7100 case MONO_TOKEN_TYPE_DEF:
7101 class = mono_class_create_from_typedef (image, type_token, &error);
7102 if (!mono_error_ok (&error)) {
7103 mono_loader_set_error_from_mono_error (&error);
7104 /*FIXME don't swallow the error message*/
7105 mono_error_cleanup (&error);
7109 case MONO_TOKEN_TYPE_REF:
7110 class = mono_class_from_typeref (image, type_token);
7112 case MONO_TOKEN_TYPE_SPEC:
7113 class = mono_class_create_from_typespec (image, type_token, context, &error);
7114 if (!mono_error_ok (&error)) {
7115 /*FIXME don't swallow the error message*/
7116 mono_error_cleanup (&error);
7120 g_warning ("unknown token type %x", type_token & 0xff000000);
7121 g_assert_not_reached ();
7125 char *name = mono_class_name_from_token (image, type_token);
7126 char *assembly = mono_assembly_name_from_token (image, type_token);
7127 mono_loader_set_error_type_load (name, assembly);
7137 * mono_type_get_full:
7138 * @image: the image where the type resides
7139 * @type_token: the token for the type
7140 * @context: the generic context used to evaluate generic instantiations in
7142 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7144 * Returns: the MonoType that represents @type_token in @image
7147 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7150 MonoType *type = NULL;
7151 gboolean inflated = FALSE;
7153 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7155 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7157 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7158 MonoClass *class = mono_class_get_full (image, type_token, context);
7159 return class ? mono_class_get_type (class) : NULL;
7162 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7164 if (!mono_error_ok (&error)) {
7165 /*FIXME don't swalloc the error message.*/
7166 char *name = mono_class_name_from_token (image, type_token);
7167 char *assembly = mono_assembly_name_from_token (image, type_token);
7169 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7171 mono_error_cleanup (&error);
7172 mono_loader_set_error_type_load (name, assembly);
7177 MonoType *tmp = type;
7178 type = mono_class_get_type (mono_class_from_mono_type (type));
7179 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7180 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7181 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7183 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7185 if (type->type != tmp->type)
7188 mono_metadata_free_type (tmp);
7195 mono_class_get (MonoImage *image, guint32 type_token)
7197 return mono_class_get_full (image, type_token, NULL);
7201 * mono_image_init_name_cache:
7203 * Initializes the class name cache stored in image->name_cache.
7205 * LOCKING: Acquires the corresponding image lock.
7208 mono_image_init_name_cache (MonoImage *image)
7210 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7211 guint32 cols [MONO_TYPEDEF_SIZE];
7214 guint32 i, visib, nspace_index;
7215 GHashTable *name_cache2, *nspace_table;
7217 mono_image_lock (image);
7219 if (image->name_cache) {
7220 mono_image_unlock (image);
7224 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7226 if (image->dynamic) {
7227 mono_image_unlock (image);
7231 /* Temporary hash table to avoid lookups in the nspace_table */
7232 name_cache2 = g_hash_table_new (NULL, NULL);
7234 for (i = 1; i <= t->rows; ++i) {
7235 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7236 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7238 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7239 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7241 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7243 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7244 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7246 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7247 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7248 if (!nspace_table) {
7249 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7250 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7251 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7254 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7257 /* Load type names from EXPORTEDTYPES table */
7259 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7260 guint32 cols [MONO_EXP_TYPE_SIZE];
7263 for (i = 0; i < t->rows; ++i) {
7264 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7265 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7266 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7268 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7269 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7270 if (!nspace_table) {
7271 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7272 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7273 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7276 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7280 g_hash_table_destroy (name_cache2);
7281 mono_image_unlock (image);
7284 /*FIXME Only dynamic assemblies should allow this operation.*/
7286 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7287 const char *name, guint32 index)
7289 GHashTable *nspace_table;
7290 GHashTable *name_cache;
7293 mono_image_lock (image);
7295 if (!image->name_cache)
7296 mono_image_init_name_cache (image);
7298 name_cache = image->name_cache;
7299 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7300 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7301 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7304 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7305 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7307 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7309 mono_image_unlock (image);
7318 find_nocase (gpointer key, gpointer value, gpointer user_data)
7320 char *name = (char*)key;
7321 FindUserData *data = (FindUserData*)user_data;
7323 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7324 data->value = value;
7328 * mono_class_from_name_case:
7329 * @image: The MonoImage where the type is looked up in
7330 * @name_space: the type namespace
7331 * @name: the type short name.
7333 * Obtains a MonoClass with a given namespace and a given name which
7334 * is located in the given MonoImage. The namespace and name
7335 * lookups are case insensitive.
7338 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7340 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7341 guint32 cols [MONO_TYPEDEF_SIZE];
7346 if (image->dynamic) {
7348 FindUserData user_data;
7350 mono_image_lock (image);
7352 if (!image->name_cache)
7353 mono_image_init_name_cache (image);
7355 user_data.key = name_space;
7356 user_data.value = NULL;
7357 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7359 if (user_data.value) {
7360 GHashTable *nspace_table = (GHashTable*)user_data.value;
7362 user_data.key = name;
7363 user_data.value = NULL;
7365 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7367 if (user_data.value)
7368 token = GPOINTER_TO_UINT (user_data.value);
7371 mono_image_unlock (image);
7374 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7380 /* add a cache if needed */
7381 for (i = 1; i <= t->rows; ++i) {
7382 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7383 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7385 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7386 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7388 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7390 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7391 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7392 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7393 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7399 return_nested_in (MonoClass *class, char *nested)
7402 char *s = strchr (nested, '/');
7403 gpointer iter = NULL;
7410 while ((found = mono_class_get_nested_types (class, &iter))) {
7411 if (strcmp (found->name, nested) == 0) {
7413 return return_nested_in (found, s);
7421 search_modules (MonoImage *image, const char *name_space, const char *name)
7423 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7424 MonoImage *file_image;
7429 * The EXPORTEDTYPES table only contains public types, so have to search the
7431 * Note: image->modules contains the contents of the MODULEREF table, while
7432 * the real module list is in the FILE table.
7434 for (i = 0; i < file_table->rows; i++) {
7435 guint32 cols [MONO_FILE_SIZE];
7436 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7437 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7440 file_image = mono_image_load_file_for_image (image, i + 1);
7442 class = mono_class_from_name (file_image, name_space, name);
7452 * mono_class_from_name:
7453 * @image: The MonoImage where the type is looked up in
7454 * @name_space: the type namespace
7455 * @name: the type short name.
7457 * Obtains a MonoClass with a given namespace and a given name which
7458 * is located in the given MonoImage.
7460 * To reference nested classes, use the "/" character as a separator.
7461 * For example use "Foo/Bar" to reference the class Bar that is nested
7462 * inside Foo, like this: "class Foo { class Bar {} }".
7465 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7467 GHashTable *nspace_table;
7468 MonoImage *loaded_image;
7475 if ((nested = strchr (name, '/'))) {
7476 int pos = nested - name;
7477 int len = strlen (name);
7480 memcpy (buf, name, len + 1);
7482 nested = buf + pos + 1;
7486 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7487 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7488 gboolean res = get_class_from_name (image, name_space, name, &class);
7491 class = search_modules (image, name_space, name);
7493 return class ? return_nested_in (class, nested) : NULL;
7499 mono_image_lock (image);
7501 if (!image->name_cache)
7502 mono_image_init_name_cache (image);
7504 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7507 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7509 mono_image_unlock (image);
7511 if (!token && image->dynamic && image->modules) {
7512 /* Search modules as well */
7513 for (i = 0; i < image->module_count; ++i) {
7514 MonoImage *module = image->modules [i];
7516 class = mono_class_from_name (module, name_space, name);
7523 class = search_modules (image, name_space, name);
7531 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7532 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7533 guint32 cols [MONO_EXP_TYPE_SIZE];
7536 idx = mono_metadata_token_index (token);
7538 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7540 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7541 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7542 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7545 class = mono_class_from_name (loaded_image, name_space, name);
7547 return return_nested_in (class, nested);
7549 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7550 guint32 assembly_idx;
7552 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7554 mono_assembly_load_reference (image, assembly_idx - 1);
7555 g_assert (image->references [assembly_idx - 1]);
7556 if (image->references [assembly_idx - 1] == (gpointer)-1)
7559 /* FIXME: Cycle detection */
7560 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7562 g_error ("not yet implemented");
7566 token = MONO_TOKEN_TYPE_DEF | token;
7568 class = mono_class_get (image, token);
7570 return return_nested_in (class, nested);
7575 * mono_class_is_subclass_of:
7576 * @klass: class to probe if it is a subclass of another one
7577 * @klassc: the class we suspect is the base class
7578 * @check_interfaces: whether we should perform interface checks
7580 * This method determines whether @klass is a subclass of @klassc.
7582 * If the @check_interfaces flag is set, then if @klassc is an interface
7583 * this method return true if the @klass implements the interface or
7584 * if @klass is an interface, if one of its base classes is @klass.
7586 * If @check_interfaces is false then, then if @klass is not an interface
7587 * then it returns true if the @klass is a subclass of @klassc.
7589 * if @klass is an interface and @klassc is System.Object, then this function
7594 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7595 gboolean check_interfaces)
7597 /*FIXME test for interfaces with variant generic arguments*/
7599 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7600 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7602 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7605 for (i = 0; i < klass->interface_count; i ++) {
7606 MonoClass *ic = klass->interfaces [i];
7611 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7616 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7619 if (klassc == mono_defaults.object_class)
7626 mono_type_is_generic_argument (MonoType *type)
7628 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7632 mono_class_has_variant_generic_params (MonoClass *klass)
7635 MonoGenericContainer *container;
7637 if (!klass->generic_class)
7640 container = klass->generic_class->container_class->generic_container;
7642 for (i = 0; i < container->type_argc; ++i)
7643 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7650 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7652 if (target == candidate)
7655 if (check_for_reference_conv &&
7656 mono_type_is_generic_argument (&target->byval_arg) &&
7657 mono_type_is_generic_argument (&candidate->byval_arg)) {
7658 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7659 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7661 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7664 if (!mono_class_is_assignable_from (target, candidate))
7670 * @container the generic container from the GTD
7671 * @klass: the class to be assigned to
7672 * @oklass: the source class
7674 * Both klass and oklass must be instances of the same generic interface.
7675 * Return true if @klass can be assigned to a @klass variable
7678 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7681 MonoType **klass_argv, **oklass_argv;
7682 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7683 MonoGenericContainer *container = klass_gtd->generic_container;
7685 if (klass == oklass)
7688 /*Viable candidates are instances of the same generic interface*/
7689 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7692 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7693 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7695 for (j = 0; j < container->type_argc; ++j) {
7696 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7697 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7699 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7703 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7704 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7706 if (param1_class != param2_class) {
7707 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7708 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7710 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7711 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7721 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7723 MonoGenericParam *gparam, *ogparam;
7724 MonoGenericParamInfo *tinfo, *cinfo;
7725 MonoClass **candidate_class;
7726 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7729 if (target == candidate)
7731 if (target->byval_arg.type != candidate->byval_arg.type)
7734 gparam = target->byval_arg.data.generic_param;
7735 ogparam = candidate->byval_arg.data.generic_param;
7736 tinfo = mono_generic_param_info (gparam);
7737 cinfo = mono_generic_param_info (ogparam);
7739 class_constraint_satisfied = FALSE;
7740 valuetype_constraint_satisfied = FALSE;
7742 /*candidate must have a super set of target's special constraints*/
7743 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7744 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7746 if (cinfo->constraints) {
7747 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7748 MonoClass *cc = *candidate_class;
7750 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7751 class_constraint_satisfied = TRUE;
7752 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7753 valuetype_constraint_satisfied = TRUE;
7756 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7757 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7759 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7761 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7763 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7764 valuetype_constraint_satisfied)) {
7769 /*candidate type constraints must be a superset of target's*/
7770 if (tinfo->constraints) {
7771 MonoClass **target_class;
7772 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7773 MonoClass *tc = *target_class;
7776 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7777 * check it's constraints since it satisfy the constraint by itself.
7779 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7782 if (!cinfo->constraints)
7785 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7786 MonoClass *cc = *candidate_class;
7788 if (mono_class_is_assignable_from (tc, cc))
7792 * This happens when we have the following:
7794 * Bar<K> where K : IFace
7795 * Foo<T, U> where T : U where U : IFace
7797 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7800 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7801 if (mono_gparam_is_assignable_from (target, cc))
7805 if (!*candidate_class)
7810 /*candidate itself must have a constraint that satisfy target*/
7811 if (cinfo->constraints) {
7812 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7813 MonoClass *cc = *candidate_class;
7814 if (mono_class_is_assignable_from (target, cc))
7822 * mono_class_is_assignable_from:
7823 * @klass: the class to be assigned to
7824 * @oklass: the source class
7826 * Return: true if an instance of object oklass can be assigned to an
7827 * instance of object @klass
7830 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7832 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7834 mono_class_init (klass);
7836 if (!oklass->inited)
7837 mono_class_init (oklass);
7839 if (klass->exception_type || oklass->exception_type)
7842 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7843 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7845 return mono_gparam_is_assignable_from (klass, oklass);
7848 if (MONO_CLASS_IS_INTERFACE (klass)) {
7849 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7850 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7851 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7855 for (i = 0; constraints [i]; ++i) {
7856 if (mono_class_is_assignable_from (klass, constraints [i]))
7864 /* interface_offsets might not be set for dynamic classes */
7865 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7867 * oklass might be a generic type parameter but they have
7868 * interface_offsets set.
7870 return mono_reflection_call_is_assignable_to (oklass, klass);
7871 if (!oklass->interface_bitmap)
7872 /* Happens with generic instances of not-yet created dynamic types */
7874 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7877 if (mono_class_has_variant_generic_params (klass)) {
7880 mono_class_setup_interfaces (oklass, &error);
7881 if (!mono_error_ok (&error)) {
7882 mono_error_cleanup (&error);
7886 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7887 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7888 MonoClass *iface = oklass->interfaces_packed [i];
7890 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7895 } else if (klass->delegate) {
7896 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7898 }else if (klass->rank) {
7899 MonoClass *eclass, *eoclass;
7901 if (oklass->rank != klass->rank)
7904 /* vectors vs. one dimensional arrays */
7905 if (oklass->byval_arg.type != klass->byval_arg.type)
7908 eclass = klass->cast_class;
7909 eoclass = oklass->cast_class;
7912 * a is b does not imply a[] is b[] when a is a valuetype, and
7913 * b is a reference type.
7916 if (eoclass->valuetype) {
7917 if ((eclass == mono_defaults.enum_class) ||
7918 (eclass == mono_defaults.enum_class->parent) ||
7919 (eclass == mono_defaults.object_class))
7923 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7924 } else if (mono_class_is_nullable (klass)) {
7925 if (mono_class_is_nullable (oklass))
7926 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7928 return mono_class_is_assignable_from (klass->cast_class, oklass);
7929 } else if (klass == mono_defaults.object_class)
7932 return mono_class_has_parent (oklass, klass);
7935 /*Check if @oklass is variant compatible with @klass.*/
7937 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7940 MonoType **klass_argv, **oklass_argv;
7941 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7942 MonoGenericContainer *container = klass_gtd->generic_container;
7944 /*Viable candidates are instances of the same generic interface*/
7945 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7948 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7949 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7951 for (j = 0; j < container->type_argc; ++j) {
7952 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7953 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7955 if (param1_class->valuetype != param2_class->valuetype)
7959 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7960 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7962 if (param1_class != param2_class) {
7963 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7964 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7966 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7967 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7975 /*Check if @candidate implements the interface @target*/
7977 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7981 gboolean is_variant = mono_class_has_variant_generic_params (target);
7983 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7984 if (mono_class_is_variant_compatible_slow (target, candidate))
7989 if (candidate == target)
7992 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7993 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7994 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7996 if (tb && tb->interfaces) {
7997 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7998 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7999 MonoClass *iface_class;
8001 /* we can't realize the type here since it can do pretty much anything. */
8004 iface_class = mono_class_from_mono_type (iface->type);
8005 if (iface_class == target)
8007 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8009 if (mono_class_implement_interface_slow (target, iface_class))
8014 /*setup_interfaces don't mono_class_init anything*/
8015 /*FIXME this doesn't handle primitive type arrays.
8016 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8017 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8019 mono_class_setup_interfaces (candidate, &error);
8020 if (!mono_error_ok (&error)) {
8021 mono_error_cleanup (&error);
8025 for (i = 0; i < candidate->interface_count; ++i) {
8026 if (candidate->interfaces [i] == target)
8029 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8032 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8036 candidate = candidate->parent;
8037 } while (candidate);
8043 * Check if @oklass can be assigned to @klass.
8044 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8047 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8049 if (candidate == target)
8051 if (target == mono_defaults.object_class)
8054 if (mono_class_has_parent (candidate, target))
8057 /*If target is not an interface there is no need to check them.*/
8058 if (MONO_CLASS_IS_INTERFACE (target))
8059 return mono_class_implement_interface_slow (target, candidate);
8061 if (target->delegate && mono_class_has_variant_generic_params (target))
8062 return mono_class_is_variant_compatible (target, candidate, FALSE);
8065 MonoClass *eclass, *eoclass;
8067 if (target->rank != candidate->rank)
8070 /* vectors vs. one dimensional arrays */
8071 if (target->byval_arg.type != candidate->byval_arg.type)
8074 eclass = target->cast_class;
8075 eoclass = candidate->cast_class;
8078 * a is b does not imply a[] is b[] when a is a valuetype, and
8079 * b is a reference type.
8082 if (eoclass->valuetype) {
8083 if ((eclass == mono_defaults.enum_class) ||
8084 (eclass == mono_defaults.enum_class->parent) ||
8085 (eclass == mono_defaults.object_class))
8089 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8091 /*FIXME properly handle nullables */
8092 /*FIXME properly handle (M)VAR */
8097 * mono_class_get_cctor:
8098 * @klass: A MonoClass pointer
8100 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8103 mono_class_get_cctor (MonoClass *klass)
8105 MonoCachedClassInfo cached_info;
8107 if (klass->image->dynamic) {
8109 * has_cctor is not set for these classes because mono_class_init () is
8112 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8115 if (!klass->has_cctor)
8118 if (mono_class_get_cached_class_info (klass, &cached_info))
8119 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8121 if (klass->generic_class && !klass->methods)
8122 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8124 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8128 * mono_class_get_finalizer:
8129 * @klass: The MonoClass pointer
8131 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8134 mono_class_get_finalizer (MonoClass *klass)
8136 MonoCachedClassInfo cached_info;
8139 mono_class_init (klass);
8140 if (!mono_class_has_finalizer (klass))
8143 if (mono_class_get_cached_class_info (klass, &cached_info))
8144 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8146 mono_class_setup_vtable (klass);
8147 return klass->vtable [finalize_slot];
8152 * mono_class_needs_cctor_run:
8153 * @klass: the MonoClass pointer
8154 * @caller: a MonoMethod describing the caller
8156 * Determines whenever the class has a static constructor and whenever it
8157 * needs to be called when executing CALLER.
8160 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8164 method = mono_class_get_cctor (klass);
8166 return (method == caller) ? FALSE : TRUE;
8172 * mono_class_array_element_size:
8175 * Returns: the number of bytes an element of type @klass
8176 * uses when stored into an array.
8179 mono_class_array_element_size (MonoClass *klass)
8181 MonoType *type = &klass->byval_arg;
8184 switch (type->type) {
8187 case MONO_TYPE_BOOLEAN:
8191 case MONO_TYPE_CHAR:
8200 case MONO_TYPE_CLASS:
8201 case MONO_TYPE_STRING:
8202 case MONO_TYPE_OBJECT:
8203 case MONO_TYPE_SZARRAY:
8204 case MONO_TYPE_ARRAY:
8206 case MONO_TYPE_MVAR:
8207 return sizeof (gpointer);
8212 case MONO_TYPE_VALUETYPE:
8213 if (type->data.klass->enumtype) {
8214 type = mono_class_enum_basetype (type->data.klass);
8215 klass = klass->element_class;
8218 return mono_class_instance_size (klass) - sizeof (MonoObject);
8219 case MONO_TYPE_GENERICINST:
8220 type = &type->data.generic_class->container_class->byval_arg;
8223 case MONO_TYPE_VOID:
8227 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8233 * mono_array_element_size:
8234 * @ac: pointer to a #MonoArrayClass
8236 * Returns: the size of single array element.
8239 mono_array_element_size (MonoClass *ac)
8241 g_assert (ac->rank);
8242 return ac->sizes.element_size;
8246 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8247 MonoGenericContext *context)
8249 if (image->dynamic) {
8250 MonoClass *tmp_handle_class;
8251 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8253 g_assert (tmp_handle_class);
8255 *handle_class = tmp_handle_class;
8257 if (tmp_handle_class == mono_defaults.typehandle_class)
8258 return &((MonoClass*)obj)->byval_arg;
8263 switch (token & 0xff000000) {
8264 case MONO_TOKEN_TYPE_DEF:
8265 case MONO_TOKEN_TYPE_REF:
8266 case MONO_TOKEN_TYPE_SPEC: {
8269 *handle_class = mono_defaults.typehandle_class;
8270 type = mono_type_get_full (image, token, context);
8273 mono_class_init (mono_class_from_mono_type (type));
8274 /* We return a MonoType* as handle */
8277 case MONO_TOKEN_FIELD_DEF: {
8279 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8283 *handle_class = mono_defaults.fieldhandle_class;
8284 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8287 mono_class_init (class);
8288 return mono_class_get_field (class, token);
8290 case MONO_TOKEN_METHOD_DEF:
8291 case MONO_TOKEN_METHOD_SPEC: {
8293 meth = mono_get_method_full (image, token, NULL, context);
8295 *handle_class = mono_defaults.methodhandle_class;
8298 case MONO_TOKEN_MEMBER_REF: {
8299 guint32 cols [MONO_MEMBERREF_SIZE];
8301 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8302 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8303 mono_metadata_decode_blob_size (sig, &sig);
8304 if (*sig == 0x6) { /* it's a field */
8306 MonoClassField *field;
8307 field = mono_field_from_token (image, token, &klass, context);
8309 *handle_class = mono_defaults.fieldhandle_class;
8313 meth = mono_get_method_full (image, token, NULL, context);
8315 *handle_class = mono_defaults.methodhandle_class;
8320 g_warning ("Unknown token 0x%08x in ldtoken", token);
8327 * This function might need to call runtime functions so it can't be part
8328 * of the metadata library.
8330 static MonoLookupDynamicToken lookup_dynamic = NULL;
8333 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8335 lookup_dynamic = func;
8339 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8341 MonoClass *handle_class;
8343 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8347 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8349 return lookup_dynamic (image, token, valid_token, handle_class, context);
8352 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8355 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8357 get_cached_class_info = func;
8361 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8363 if (!get_cached_class_info)
8366 return get_cached_class_info (klass, res);
8370 mono_install_get_class_from_name (MonoGetClassFromName func)
8372 get_class_from_name = func;
8376 mono_class_get_image (MonoClass *klass)
8378 return klass->image;
8382 * mono_class_get_element_class:
8383 * @klass: the MonoClass to act on
8385 * Returns: the element class of an array or an enumeration.
8388 mono_class_get_element_class (MonoClass *klass)
8390 return klass->element_class;
8394 * mono_class_is_valuetype:
8395 * @klass: the MonoClass to act on
8397 * Returns: true if the MonoClass represents a ValueType.
8400 mono_class_is_valuetype (MonoClass *klass)
8402 return klass->valuetype;
8406 * mono_class_is_enum:
8407 * @klass: the MonoClass to act on
8409 * Returns: true if the MonoClass represents an enumeration.
8412 mono_class_is_enum (MonoClass *klass)
8414 return klass->enumtype;
8418 * mono_class_enum_basetype:
8419 * @klass: the MonoClass to act on
8421 * Returns: the underlying type representation for an enumeration.
8424 mono_class_enum_basetype (MonoClass *klass)
8426 if (klass->element_class == klass)
8427 /* SRE or broken types */
8430 return &klass->element_class->byval_arg;
8434 * mono_class_get_parent
8435 * @klass: the MonoClass to act on
8437 * Returns: the parent class for this class.
8440 mono_class_get_parent (MonoClass *klass)
8442 return klass->parent;
8446 * mono_class_get_nesting_type;
8447 * @klass: the MonoClass to act on
8449 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8452 mono_class_get_nesting_type (MonoClass *klass)
8454 return klass->nested_in;
8458 * mono_class_get_rank:
8459 * @klass: the MonoClass to act on
8461 * Returns: the rank for the array (the number of dimensions).
8464 mono_class_get_rank (MonoClass *klass)
8470 * mono_class_get_flags:
8471 * @klass: the MonoClass to act on
8473 * The type flags from the TypeDef table from the metadata.
8474 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8477 * Returns: the flags from the TypeDef table.
8480 mono_class_get_flags (MonoClass *klass)
8482 return klass->flags;
8486 * mono_class_get_name
8487 * @klass: the MonoClass to act on
8489 * Returns: the name of the class.
8492 mono_class_get_name (MonoClass *klass)
8498 * mono_class_get_namespace:
8499 * @klass: the MonoClass to act on
8501 * Returns: the namespace of the class.
8504 mono_class_get_namespace (MonoClass *klass)
8506 return klass->name_space;
8510 * mono_class_get_type:
8511 * @klass: the MonoClass to act on
8513 * This method returns the internal Type representation for the class.
8515 * Returns: the MonoType from the class.
8518 mono_class_get_type (MonoClass *klass)
8520 return &klass->byval_arg;
8524 * mono_class_get_type_token
8525 * @klass: the MonoClass to act on
8527 * This method returns type token for the class.
8529 * Returns: the type token for the class.
8532 mono_class_get_type_token (MonoClass *klass)
8534 return klass->type_token;
8538 * mono_class_get_byref_type:
8539 * @klass: the MonoClass to act on
8544 mono_class_get_byref_type (MonoClass *klass)
8546 return &klass->this_arg;
8550 * mono_class_num_fields:
8551 * @klass: the MonoClass to act on
8553 * Returns: the number of static and instance fields in the class.
8556 mono_class_num_fields (MonoClass *klass)
8558 return klass->field.count;
8562 * mono_class_num_methods:
8563 * @klass: the MonoClass to act on
8565 * Returns: the number of methods in the class.
8568 mono_class_num_methods (MonoClass *klass)
8570 return klass->method.count;
8574 * mono_class_num_properties
8575 * @klass: the MonoClass to act on
8577 * Returns: the number of properties in the class.
8580 mono_class_num_properties (MonoClass *klass)
8582 mono_class_setup_properties (klass);
8584 return klass->ext->property.count;
8588 * mono_class_num_events:
8589 * @klass: the MonoClass to act on
8591 * Returns: the number of events in the class.
8594 mono_class_num_events (MonoClass *klass)
8596 mono_class_setup_events (klass);
8598 return klass->ext->event.count;
8602 * mono_class_get_fields:
8603 * @klass: the MonoClass to act on
8605 * This routine is an iterator routine for retrieving the fields in a class.
8607 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8608 * iterate over all of the elements. When no more values are
8609 * available, the return value is NULL.
8611 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8614 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8616 MonoClassField* field;
8620 mono_class_setup_fields_locking (klass);
8621 if (klass->exception_type)
8623 /* start from the first */
8624 if (klass->field.count) {
8625 return *iter = &klass->fields [0];
8633 if (field < &klass->fields [klass->field.count]) {
8634 return *iter = field;
8640 * mono_class_get_methods
8641 * @klass: the MonoClass to act on
8643 * This routine is an iterator routine for retrieving the fields in a class.
8645 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8646 * iterate over all of the elements. When no more values are
8647 * available, the return value is NULL.
8649 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8652 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8654 MonoMethod** method;
8658 mono_class_setup_methods (klass);
8661 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8662 * FIXME we should better report this error to the caller
8664 if (!klass->methods)
8666 /* start from the first */
8667 if (klass->method.count) {
8668 *iter = &klass->methods [0];
8669 return klass->methods [0];
8677 if (method < &klass->methods [klass->method.count]) {
8685 * mono_class_get_virtual_methods:
8687 * Iterate over the virtual methods of KLASS.
8689 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8692 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8694 MonoMethod** method;
8697 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8699 mono_class_setup_methods (klass);
8701 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8702 * FIXME we should better report this error to the caller
8704 if (!klass->methods)
8706 /* start from the first */
8707 method = &klass->methods [0];
8712 while (method < &klass->methods [klass->method.count]) {
8713 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8717 if (method < &klass->methods [klass->method.count]) {
8724 /* Search directly in metadata to avoid calling setup_methods () */
8725 MonoMethod *res = NULL;
8731 start_index = GPOINTER_TO_UINT (*iter);
8734 for (i = start_index; i < klass->method.count; ++i) {
8737 /* class->method.first points into the methodptr table */
8738 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8740 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8744 if (i < klass->method.count) {
8745 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8746 /* Add 1 here so the if (*iter) check fails */
8747 *iter = GUINT_TO_POINTER (i + 1);
8756 * mono_class_get_properties:
8757 * @klass: the MonoClass to act on
8759 * This routine is an iterator routine for retrieving the properties in a class.
8761 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8762 * iterate over all of the elements. When no more values are
8763 * available, the return value is NULL.
8765 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8768 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8770 MonoProperty* property;
8774 mono_class_setup_properties (klass);
8775 /* start from the first */
8776 if (klass->ext->property.count) {
8777 return *iter = &klass->ext->properties [0];
8785 if (property < &klass->ext->properties [klass->ext->property.count]) {
8786 return *iter = property;
8792 * mono_class_get_events:
8793 * @klass: the MonoClass to act on
8795 * This routine is an iterator routine for retrieving the properties in a class.
8797 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8798 * iterate over all of the elements. When no more values are
8799 * available, the return value is NULL.
8801 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8804 mono_class_get_events (MonoClass* klass, gpointer *iter)
8810 mono_class_setup_events (klass);
8811 /* start from the first */
8812 if (klass->ext->event.count) {
8813 return *iter = &klass->ext->events [0];
8821 if (event < &klass->ext->events [klass->ext->event.count]) {
8822 return *iter = event;
8828 * mono_class_get_interfaces
8829 * @klass: the MonoClass to act on
8831 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8833 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8834 * iterate over all of the elements. When no more values are
8835 * available, the return value is NULL.
8837 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8840 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8848 mono_class_init (klass);
8849 if (!klass->interfaces_inited) {
8850 mono_class_setup_interfaces (klass, &error);
8851 if (!mono_error_ok (&error)) {
8852 mono_error_cleanup (&error);
8856 /* start from the first */
8857 if (klass->interface_count) {
8858 *iter = &klass->interfaces [0];
8859 return klass->interfaces [0];
8867 if (iface < &klass->interfaces [klass->interface_count]) {
8875 * mono_class_get_nested_types
8876 * @klass: the MonoClass to act on
8878 * This routine is an iterator routine for retrieving the nested types of a class.
8879 * This works only if @klass is non-generic, or a generic type definition.
8881 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8882 * iterate over all of the elements. When no more values are
8883 * available, the return value is NULL.
8885 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8888 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8896 if (!klass->nested_classes_inited) {
8897 if (!klass->type_token)
8898 klass->nested_classes_inited = TRUE;
8899 mono_loader_lock ();
8900 if (!klass->nested_classes_inited) {
8901 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8904 guint32 cols [MONO_NESTED_CLASS_SIZE];
8905 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8906 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8907 if (!mono_error_ok (&error)) {
8908 /*FIXME don't swallow the error message*/
8909 mono_error_cleanup (&error);
8911 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8914 mono_class_alloc_ext (klass);
8915 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8917 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8920 mono_memory_barrier ();
8921 klass->nested_classes_inited = TRUE;
8922 mono_loader_unlock ();
8926 /* start from the first */
8927 if (klass->ext && klass->ext->nested_classes) {
8928 *iter = klass->ext->nested_classes;
8929 return klass->ext->nested_classes->data;
8931 /* no nested types */
8946 * mono_class_is_delegate
8947 * @klass: the MonoClass to act on
8949 * Returns: true if the MonoClass represents a System.Delegate.
8952 mono_class_is_delegate (MonoClass *klass)
8954 return klass->delegate;
8958 * mono_class_implements_interface
8959 * @klass: The MonoClass to act on
8960 * @interface: The interface to check if @klass implements.
8962 * Returns: true if @klass implements @interface.
8965 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
8967 return mono_class_is_assignable_from (iface, klass);
8971 * mono_field_get_name:
8972 * @field: the MonoClassField to act on
8974 * Returns: the name of the field.
8977 mono_field_get_name (MonoClassField *field)
8983 * mono_field_get_type:
8984 * @field: the MonoClassField to act on
8986 * Returns: MonoType of the field.
8989 mono_field_get_type (MonoClassField *field)
8992 MonoType *type = mono_field_get_type_checked (field, &error);
8993 if (!mono_error_ok (&error)) {
8994 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8995 mono_error_cleanup (&error);
9002 * mono_field_get_type_checked:
9003 * @field: the MonoClassField to act on
9004 * @error: used to return any erro found while retrieving @field type
9006 * Returns: MonoType of the field.
9009 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9011 mono_error_init (error);
9013 mono_field_resolve_type (field, error);
9018 * mono_field_get_parent:
9019 * @field: the MonoClassField to act on
9021 * Returns: MonoClass where the field was defined.
9024 mono_field_get_parent (MonoClassField *field)
9026 return field->parent;
9030 * mono_field_get_flags;
9031 * @field: the MonoClassField to act on
9033 * The metadata flags for a field are encoded using the
9034 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9036 * Returns: the flags for the field.
9039 mono_field_get_flags (MonoClassField *field)
9042 return mono_field_resolve_flags (field);
9043 return field->type->attrs;
9047 * mono_field_get_offset;
9048 * @field: the MonoClassField to act on
9050 * Returns: the field offset.
9053 mono_field_get_offset (MonoClassField *field)
9055 return field->offset;
9059 mono_field_get_rva (MonoClassField *field)
9063 MonoClass *klass = field->parent;
9065 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9067 if (!klass->ext || !klass->ext->field_def_values) {
9068 mono_loader_lock ();
9069 mono_class_alloc_ext (klass);
9070 if (!klass->ext->field_def_values)
9071 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9072 mono_loader_unlock ();
9075 field_index = mono_field_get_index (field);
9077 if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
9078 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9080 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9081 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9084 return klass->ext->field_def_values [field_index].data;
9088 * mono_field_get_data;
9089 * @field: the MonoClassField to act on
9091 * Returns: pointer to the metadata constant value or to the field
9092 * data if it has an RVA flag.
9095 mono_field_get_data (MonoClassField *field)
9097 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9098 MonoTypeEnum def_type;
9100 return mono_class_get_field_default_value (field, &def_type);
9101 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9102 return mono_field_get_rva (field);
9109 * mono_property_get_name:
9110 * @prop: the MonoProperty to act on
9112 * Returns: the name of the property
9115 mono_property_get_name (MonoProperty *prop)
9121 * mono_property_get_set_method
9122 * @prop: the MonoProperty to act on.
9124 * Returns: the setter method of the property (A MonoMethod)
9127 mono_property_get_set_method (MonoProperty *prop)
9133 * mono_property_get_get_method
9134 * @prop: the MonoProperty to act on.
9136 * Returns: the setter method of the property (A MonoMethod)
9139 mono_property_get_get_method (MonoProperty *prop)
9145 * mono_property_get_parent:
9146 * @prop: the MonoProperty to act on.
9148 * Returns: the MonoClass where the property was defined.
9151 mono_property_get_parent (MonoProperty *prop)
9153 return prop->parent;
9157 * mono_property_get_flags:
9158 * @prop: the MonoProperty to act on.
9160 * The metadata flags for a property are encoded using the
9161 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9163 * Returns: the flags for the property.
9166 mono_property_get_flags (MonoProperty *prop)
9172 * mono_event_get_name:
9173 * @event: the MonoEvent to act on
9175 * Returns: the name of the event.
9178 mono_event_get_name (MonoEvent *event)
9184 * mono_event_get_add_method:
9185 * @event: The MonoEvent to act on.
9187 * Returns: the @add' method for the event (a MonoMethod).
9190 mono_event_get_add_method (MonoEvent *event)
9196 * mono_event_get_remove_method:
9197 * @event: The MonoEvent to act on.
9199 * Returns: the @remove method for the event (a MonoMethod).
9202 mono_event_get_remove_method (MonoEvent *event)
9204 return event->remove;
9208 * mono_event_get_raise_method:
9209 * @event: The MonoEvent to act on.
9211 * Returns: the @raise method for the event (a MonoMethod).
9214 mono_event_get_raise_method (MonoEvent *event)
9216 return event->raise;
9220 * mono_event_get_parent:
9221 * @event: the MonoEvent to act on.
9223 * Returns: the MonoClass where the event is defined.
9226 mono_event_get_parent (MonoEvent *event)
9228 return event->parent;
9232 * mono_event_get_flags
9233 * @event: the MonoEvent to act on.
9235 * The metadata flags for an event are encoded using the
9236 * EVENT_* constants. See the tabledefs.h file for details.
9238 * Returns: the flags for the event.
9241 mono_event_get_flags (MonoEvent *event)
9243 return event->attrs;
9247 * mono_class_get_method_from_name:
9248 * @klass: where to look for the method
9249 * @name_space: name of the method
9250 * @param_count: number of parameters. -1 for any number.
9252 * Obtains a MonoMethod with a given name and number of parameters.
9253 * It only works if there are no multiple signatures for any given method name.
9256 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9258 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9262 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9264 MonoMethod *res = NULL;
9267 /* Search directly in the metadata to avoid calling setup_methods () */
9268 for (i = 0; i < klass->method.count; ++i) {
9269 guint32 cols [MONO_METHOD_SIZE];
9271 MonoMethodSignature *sig;
9273 /* class->method.first points into the methodptr table */
9274 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9276 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9277 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9278 if (param_count == -1) {
9282 sig = mono_method_signature (method);
9283 if (sig && sig->param_count == param_count) {
9294 * mono_class_get_method_from_name_flags:
9295 * @klass: where to look for the method
9296 * @name_space: name of the method
9297 * @param_count: number of parameters. -1 for any number.
9298 * @flags: flags which must be set in the method
9300 * Obtains a MonoMethod with a given name and number of parameters.
9301 * It only works if there are no multiple signatures for any given method name.
9304 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9306 MonoMethod *res = NULL;
9309 mono_class_init (klass);
9311 if (klass->generic_class && !klass->methods) {
9312 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9314 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9318 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9319 mono_class_setup_methods (klass);
9321 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9322 See mono/tests/array_load_exception.il
9323 FIXME we should better report this error to the caller
9325 if (!klass->methods)
9327 for (i = 0; i < klass->method.count; ++i) {
9328 MonoMethod *method = klass->methods [i];
9330 if (method->name[0] == name [0] &&
9331 !strcmp (name, method->name) &&
9332 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9333 ((method->flags & flags) == flags)) {
9340 res = find_method_in_metadata (klass, name, param_count, flags);
9347 * mono_class_set_failure:
9348 * @klass: class in which the failure was detected
9349 * @ex_type: the kind of exception/error to be thrown (later)
9350 * @ex_data: exception data (specific to each type of exception/error)
9352 * Keep a detected failure informations in the class for later processing.
9353 * Note that only the first failure is kept.
9355 * LOCKING: Acquires the loader lock.
9358 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9360 if (klass->exception_type)
9363 mono_loader_lock ();
9364 klass->exception_type = ex_type;
9366 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9367 mono_loader_unlock ();
9373 * mono_class_get_exception_data:
9375 * Return the exception_data property of KLASS.
9377 * LOCKING: Acquires the loader lock.
9380 mono_class_get_exception_data (MonoClass *klass)
9382 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9386 * mono_classes_init:
9388 * Initialize the resources used by this module.
9391 mono_classes_init (void)
9393 mono_counters_register ("Inflated methods size",
9394 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9395 mono_counters_register ("Inflated classes",
9396 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9397 mono_counters_register ("Inflated classes size",
9398 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9399 mono_counters_register ("MonoClass size",
9400 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9401 mono_counters_register ("MonoClassExt size",
9402 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9406 * mono_classes_cleanup:
9408 * Free the resources used by this module.
9411 mono_classes_cleanup (void)
9413 if (global_interface_bitset)
9414 mono_bitset_free (global_interface_bitset);
9415 global_interface_bitset = NULL;
9419 * mono_class_get_exception_for_failure:
9420 * @klass: class in which the failure was detected
9422 * Return a constructed MonoException than the caller can then throw
9423 * using mono_raise_exception - or NULL if no failure is present (or
9424 * doesn't result in an exception).
9427 mono_class_get_exception_for_failure (MonoClass *klass)
9429 gpointer exception_data = mono_class_get_exception_data (klass);
9431 switch (klass->exception_type) {
9432 #ifndef DISABLE_SECURITY
9433 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9434 MonoDomain *domain = mono_domain_get ();
9435 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9436 MonoMethod *method = exception_data;
9437 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9438 MonoObject *exc = NULL;
9442 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9443 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9444 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9446 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9447 return (MonoException*) exc;
9450 case MONO_EXCEPTION_TYPE_LOAD: {
9453 char *str = mono_type_get_full_name (klass);
9454 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9455 name = mono_string_new (mono_domain_get (), str);
9457 ex = mono_get_exception_type_load (name, astr);
9461 case MONO_EXCEPTION_MISSING_METHOD: {
9462 char *class_name = exception_data;
9463 char *assembly_name = class_name + strlen (class_name) + 1;
9465 return mono_get_exception_missing_method (class_name, assembly_name);
9467 case MONO_EXCEPTION_MISSING_FIELD: {
9468 char *class_name = exception_data;
9469 char *member_name = class_name + strlen (class_name) + 1;
9471 return mono_get_exception_missing_field (class_name, member_name);
9473 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9474 char *msg_format = exception_data;
9475 char *assembly_name = msg_format + strlen (msg_format) + 1;
9476 char *msg = g_strdup_printf (msg_format, assembly_name);
9479 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9485 case MONO_EXCEPTION_BAD_IMAGE: {
9486 return mono_get_exception_bad_image_format (exception_data);
9489 MonoLoaderError *error;
9492 error = mono_loader_get_last_error ();
9494 ex = mono_loader_error_prepare_exception (error);
9498 /* TODO - handle other class related failures */
9505 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9507 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9508 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9510 if (outer_klass == inner_klass)
9512 inner_klass = inner_klass->nested_in;
9513 } while (inner_klass);
9518 mono_class_get_generic_type_definition (MonoClass *klass)
9520 return klass->generic_class ? klass->generic_class->container_class : klass;
9524 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9526 * Generic instantiations are ignored for all super types of @klass.
9528 * Visibility checks ignoring generic instantiations.
9531 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9534 klass = mono_class_get_generic_type_definition (klass);
9535 parent = mono_class_get_generic_type_definition (parent);
9536 mono_class_setup_supertypes (klass);
9538 for (i = 0; i < klass->idepth; ++i) {
9539 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9545 * Subtype can only access parent members with family protection if the site object
9546 * is subclass of Subtype. For example:
9547 * class A { protected int x; }
9549 * void valid_access () {
9553 * void invalid_access () {
9560 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9562 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9565 if (context_klass == NULL)
9567 /*if access_klass is not member_klass context_klass must be type compat*/
9568 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9574 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9577 if (accessing == accessed)
9579 if (!accessed || !accessing)
9582 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9583 * anywhere so untrusted friends are not safe to access platform's code internals */
9584 if (mono_security_core_clr_enabled ()) {
9585 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9589 mono_assembly_load_friends (accessed);
9590 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9591 MonoAssemblyName *friend = tmp->data;
9592 /* Be conservative with checks */
9595 if (strcmp (accessing->aname.name, friend->name))
9597 if (friend->public_key_token [0]) {
9598 if (!accessing->aname.public_key_token [0])
9600 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9609 * If klass is a generic type or if it is derived from a generic type, return the
9610 * MonoClass of the generic definition
9611 * Returns NULL if not found
9614 get_generic_definition_class (MonoClass *klass)
9617 if (klass->generic_class && klass->generic_class->container_class)
9618 return klass->generic_class->container_class;
9619 klass = klass->parent;
9625 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9628 for (i = 0; i < ginst->type_argc; ++i) {
9629 MonoType *type = ginst->type_argv[i];
9630 switch (type->type) {
9631 case MONO_TYPE_SZARRAY:
9632 if (!can_access_type (access_klass, type->data.klass))
9635 case MONO_TYPE_ARRAY:
9636 if (!can_access_type (access_klass, type->data.array->eklass))
9640 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9643 case MONO_TYPE_CLASS:
9644 case MONO_TYPE_VALUETYPE:
9645 case MONO_TYPE_GENERICINST:
9646 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9654 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9658 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9661 if (access_klass->element_class && !access_klass->enumtype)
9662 access_klass = access_klass->element_class;
9664 if (member_klass->element_class && !member_klass->enumtype)
9665 member_klass = member_klass->element_class;
9667 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9669 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9672 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9675 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9678 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9681 /*Non nested type with nested visibility. We just fail it.*/
9682 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9685 switch (access_level) {
9686 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9687 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9689 case TYPE_ATTRIBUTE_PUBLIC:
9692 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9695 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9696 return is_nesting_type (member_klass, access_klass);
9698 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9699 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9701 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9702 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9704 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9705 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9706 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9708 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9709 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9710 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9715 /* FIXME: check visibility of type, too */
9717 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9719 MonoClass *member_generic_def;
9720 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9723 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9724 access_klass->generic_container) &&
9725 (member_generic_def = get_generic_definition_class (member_klass))) {
9726 MonoClass *access_container;
9728 if (access_klass->generic_container)
9729 access_container = access_klass;
9731 access_container = access_klass->generic_class->container_class;
9733 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9737 /* Partition I 8.5.3.2 */
9738 /* the access level values are the same for fields and methods */
9739 switch (access_level) {
9740 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9741 /* same compilation unit */
9742 return access_klass->image == member_klass->image;
9743 case FIELD_ATTRIBUTE_PRIVATE:
9744 return access_klass == member_klass;
9745 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9746 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9747 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9750 case FIELD_ATTRIBUTE_ASSEMBLY:
9751 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9752 case FIELD_ATTRIBUTE_FAMILY:
9753 if (is_valid_family_access (access_klass, member_klass, context_klass))
9756 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9757 if (is_valid_family_access (access_klass, member_klass, context_klass))
9759 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9760 case FIELD_ATTRIBUTE_PUBLIC:
9767 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9769 /* FIXME: check all overlapping fields */
9770 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9772 MonoClass *nested = method->klass->nested_in;
9774 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9777 nested = nested->nested_in;
9784 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9786 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9788 MonoClass *nested = method->klass->nested_in;
9790 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9793 nested = nested->nested_in;
9798 * with generics calls to explicit interface implementations can be expressed
9799 * directly: the method is private, but we must allow it. This may be opening
9800 * a hole or the generics code should handle this differently.
9801 * Maybe just ensure the interface type is public.
9803 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9809 * mono_method_can_access_method_full:
9810 * @method: The caller method
9811 * @called: The called method
9812 * @context_klass: The static type on stack of the owner @called object used
9814 * This function must be used with instance calls, as they have more strict family accessibility.
9815 * It can be used with static methods, but context_klass should be NULL.
9817 * Returns: TRUE if caller have proper visibility and acessibility to @called
9820 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9822 MonoClass *access_class = method->klass;
9823 MonoClass *member_class = called->klass;
9824 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9826 MonoClass *nested = access_class->nested_in;
9828 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9831 nested = nested->nested_in;
9838 can = can_access_type (access_class, member_class);
9840 MonoClass *nested = access_class->nested_in;
9842 can = can_access_type (nested, member_class);
9845 nested = nested->nested_in;
9852 if (called->is_inflated) {
9853 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9854 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9863 * mono_method_can_access_field_full:
9864 * @method: The caller method
9865 * @field: The accessed field
9866 * @context_klass: The static type on stack of the owner @field object used
9868 * This function must be used with instance fields, as they have more strict family accessibility.
9869 * It can be used with static fields, but context_klass should be NULL.
9871 * Returns: TRUE if caller have proper visibility and acessibility to @field
9874 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9876 MonoClass *access_class = method->klass;
9877 MonoClass *member_class = field->parent;
9878 /* FIXME: check all overlapping fields */
9879 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9881 MonoClass *nested = access_class->nested_in;
9883 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9886 nested = nested->nested_in;
9893 can = can_access_type (access_class, member_class);
9895 MonoClass *nested = access_class->nested_in;
9897 can = can_access_type (nested, member_class);
9900 nested = nested->nested_in;
9910 * mono_class_can_access_class:
9911 * @source_class: The source class
9912 * @target_class: The accessed class
9914 * This function returns is @target_class is visible to @source_class
9916 * Returns: TRUE if source have proper visibility and acessibility to target
9919 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9921 return can_access_type (source_class, target_class);
9925 * mono_type_is_valid_enum_basetype:
9926 * @type: The MonoType to check
9928 * Returns: TRUE if the type can be used as the basetype of an enum
9930 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9931 switch (type->type) {
9934 case MONO_TYPE_BOOLEAN:
9937 case MONO_TYPE_CHAR:
9950 * mono_class_is_valid_enum:
9951 * @klass: An enum class to be validated
9953 * This method verify the required properties an enum should have.
9955 * Returns: TRUE if the informed enum class is valid
9957 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9958 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9959 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9961 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9962 MonoClassField * field;
9963 gpointer iter = NULL;
9964 gboolean found_base_field = FALSE;
9966 g_assert (klass->enumtype);
9967 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9968 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9972 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9975 while ((field = mono_class_get_fields (klass, &iter))) {
9976 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9977 if (found_base_field)
9979 found_base_field = TRUE;
9980 if (!mono_type_is_valid_enum_basetype (field->type))
9985 if (!found_base_field)
9988 if (klass->method.count > 0)
9995 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9997 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10001 * mono_class_setup_interface_id:
10003 * Initializes MonoClass::interface_id if required.
10005 * LOCKING: Acquires the loader lock.
10008 mono_class_setup_interface_id (MonoClass *class)
10010 mono_loader_lock ();
10011 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10012 class->interface_id = mono_get_unique_iid (class);
10013 mono_loader_unlock ();
10017 * mono_class_alloc_ext:
10019 * Allocate klass->ext if not already done.
10020 * LOCKING: Assumes the loader lock is held.
10023 mono_class_alloc_ext (MonoClass *klass)
10026 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10027 class_ext_size += sizeof (MonoClassExt);
10032 * mono_class_setup_interfaces:
10034 * Initialize class->interfaces/interfaces_count.
10035 * LOCKING: Acquires the loader lock.
10036 * This function can fail the type.
10039 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10043 mono_error_init (error);
10045 if (klass->interfaces_inited)
10048 mono_loader_lock ();
10050 if (klass->interfaces_inited) {
10051 mono_loader_unlock ();
10055 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10056 MonoType *args [1];
10058 /* generic IList, ICollection, IEnumerable */
10059 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10060 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
10062 args [0] = &klass->element_class->byval_arg;
10063 klass->interfaces [0] = mono_class_bind_generic_parameters (
10064 mono_defaults.generic_ilist_class, 1, args, FALSE);
10065 if (klass->interface_count > 1)
10066 klass->interfaces [1] = mono_class_bind_generic_parameters (
10067 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10068 } else if (klass->generic_class) {
10069 MonoClass *gklass = klass->generic_class->container_class;
10071 klass->interface_count = gklass->interface_count;
10072 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
10073 for (i = 0; i < klass->interface_count; i++) {
10074 klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10075 if (!mono_error_ok (error)) {
10076 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10077 klass->interfaces = NULL;
10083 mono_memory_barrier ();
10085 klass->interfaces_inited = TRUE;
10087 mono_loader_unlock ();
10091 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10093 MonoClass *class = field->parent;
10094 MonoImage *image = class->image;
10095 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10096 int field_idx = field - class->fields;
10098 mono_error_init (error);
10101 MonoClassField *gfield = >d->fields [field_idx];
10102 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10103 if (!mono_error_ok (error)) {
10104 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10105 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10109 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10110 if (!mono_error_ok (error)) {
10111 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10112 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10117 guint32 cols [MONO_FIELD_SIZE];
10118 MonoGenericContainer *container = NULL;
10119 int idx = class->field.first + field_idx;
10121 /*FIXME, in theory we do not lazy load SRE fields*/
10122 g_assert (!image->dynamic);
10124 if (class->generic_container) {
10125 container = class->generic_container;
10127 container = gtd->generic_container;
10128 g_assert (container);
10131 /* class->field.first and idx points into the fieldptr table */
10132 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10134 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10135 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10136 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10140 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10142 mono_metadata_decode_value (sig, &sig);
10143 /* FIELD signature == 0x06 */
10144 g_assert (*sig == 0x06);
10145 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10147 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10152 mono_field_resolve_flags (MonoClassField *field)
10154 MonoClass *class = field->parent;
10155 MonoImage *image = class->image;
10156 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10157 int field_idx = field - class->fields;
10161 MonoClassField *gfield = >d->fields [field_idx];
10162 return mono_field_get_flags (gfield);
10164 int idx = class->field.first + field_idx;
10166 /*FIXME, in theory we do not lazy load SRE fields*/
10167 g_assert (!image->dynamic);
10169 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10174 * mono_class_setup_basic_field_info:
10175 * @class: The class to initialize
10177 * Initializes the class->fields array of fields.
10178 * Aquires the loader lock.
10181 mono_class_setup_basic_field_info_locking (MonoClass *class)
10183 mono_loader_lock ();
10184 mono_class_setup_basic_field_info (class);
10185 mono_loader_unlock ();
10189 * mono_class_get_fields_lazy:
10190 * @klass: the MonoClass to act on
10192 * This routine is an iterator routine for retrieving the fields in a class.
10193 * Only minimal information about fields are loaded. Accessors must be used
10194 * for all MonoClassField returned.
10196 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10197 * iterate over all of the elements. When no more values are
10198 * available, the return value is NULL.
10200 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10203 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10205 MonoClassField* field;
10209 mono_class_setup_basic_field_info_locking (klass);
10210 if (!klass->fields)
10212 /* start from the first */
10213 if (klass->field.count) {
10214 return *iter = &klass->fields [0];
10222 if (field < &klass->fields [klass->field.count]) {
10223 return *iter = field;
10229 mono_class_full_name (MonoClass *klass)
10231 return mono_type_full_name (&klass->byval_arg);