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, image_is_dynamic (klass->image));
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 image_is_dynamic (method->klass->image) && !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 && image_is_dynamic (class->generic_class->container_class->image) && !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 && image_is_dynamic (class->generic_class->container_class->image) && !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 gboolean has_static_fields = FALSE;
1753 MonoClassField *field;
1756 * When we do generic sharing we need to have layout
1757 * information for open generic classes (either with a generic
1758 * context containing type variables or with a generic
1759 * container), so we don't return in that case anymore.
1763 * Enable GC aware auto layout: in this mode, reference
1764 * fields are grouped together inside objects, increasing collector
1766 * Requires that all classes whose layout is known to native code be annotated
1767 * with [StructLayout (LayoutKind.Sequential)]
1768 * Value types have gc_aware_layout disabled by default, as per
1769 * what the default is for other runtimes.
1771 /* corlib is missing [StructLayout] directives in many places */
1772 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1773 if (!class->valuetype)
1774 gc_aware_layout = TRUE;
1777 /* Compute klass->has_references */
1779 * Process non-static fields first, since static fields might recursively
1780 * refer to the class itself.
1782 for (i = 0; i < top; i++) {
1785 field = &class->fields [i];
1787 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1788 ftype = mono_type_get_underlying_type (field->type);
1789 ftype = mono_type_get_basic_type_from_generic (ftype);
1790 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1791 class->has_references = TRUE;
1795 for (i = 0; i < top; i++) {
1798 field = &class->fields [i];
1800 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1801 ftype = mono_type_get_underlying_type (field->type);
1802 ftype = mono_type_get_basic_type_from_generic (ftype);
1803 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1804 class->has_static_refs = TRUE;
1808 for (i = 0; i < top; i++) {
1811 field = &class->fields [i];
1813 ftype = mono_type_get_underlying_type (field->type);
1814 ftype = mono_type_get_basic_type_from_generic (ftype);
1815 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1816 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1817 class->has_static_refs = TRUE;
1819 class->has_references = TRUE;
1824 * Compute field layout and total size (not considering static fields)
1828 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1829 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1831 if (gc_aware_layout)
1836 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1839 if (class->parent) {
1840 mono_class_setup_fields (class->parent);
1841 if (class->parent->exception_type) {
1842 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1845 real_size = class->parent->instance_size;
1847 real_size = sizeof (MonoObject);
1850 for (pass = 0; pass < passes; ++pass) {
1851 for (i = 0; i < top; i++){
1856 field = &class->fields [i];
1858 if (mono_field_is_deleted (field))
1860 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1863 ftype = mono_type_get_underlying_type (field->type);
1864 ftype = mono_type_get_basic_type_from_generic (ftype);
1865 if (gc_aware_layout) {
1866 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1875 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1876 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1877 /* This field is a hack inserted by MCS to empty structures */
1881 size = mono_type_size (field->type, &align);
1883 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1884 align = class->packing_size ? MIN (class->packing_size, align): align;
1885 /* if the field has managed references, we need to force-align it
1888 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1889 align = MAX (align, sizeof (gpointer));
1891 class->min_align = MAX (align, class->min_align);
1892 field->offset = real_size;
1894 field->offset += align - 1;
1895 field->offset &= ~(align - 1);
1897 /*TypeBuilders produce all sort of weird things*/
1898 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1899 real_size = field->offset + size;
1902 class->instance_size = MAX (real_size, class->instance_size);
1904 if (class->instance_size & (class->min_align - 1)) {
1905 class->instance_size += class->min_align - 1;
1906 class->instance_size &= ~(class->min_align - 1);
1910 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1912 for (i = 0; i < top; i++) {
1917 field = &class->fields [i];
1920 * There must be info about all the fields in a type if it
1921 * uses explicit layout.
1924 if (mono_field_is_deleted (field))
1926 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1929 size = mono_type_size (field->type, &align);
1930 align = class->packing_size ? MIN (class->packing_size, align): align;
1931 class->min_align = MAX (align, class->min_align);
1934 * When we get here, field->offset is already set by the
1935 * loader (for either runtime fields or fields loaded from metadata).
1936 * The offset is from the start of the object: this works for both
1937 * classes and valuetypes.
1939 field->offset += sizeof (MonoObject);
1940 ftype = mono_type_get_underlying_type (field->type);
1941 ftype = mono_type_get_basic_type_from_generic (ftype);
1942 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1943 if (field->offset % sizeof (gpointer)) {
1944 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1951 real_size = MAX (real_size, size + field->offset);
1953 class->instance_size = MAX (real_size, class->instance_size);
1954 if (class->instance_size & (class->min_align - 1)) {
1955 class->instance_size += class->min_align - 1;
1956 class->instance_size &= ~(class->min_align - 1);
1961 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1963 * For small structs, set min_align to at least the struct size to improve
1964 * performance, and since the JIT memset/memcpy code assumes this and generates
1965 * unaligned accesses otherwise. See #78990 for a testcase.
1967 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1968 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1971 mono_memory_barrier ();
1972 class->size_inited = 1;
1975 * Compute static field layout and size
1977 for (i = 0; i < top; i++){
1981 field = &class->fields [i];
1983 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1985 if (mono_field_is_deleted (field))
1988 if (mono_type_has_exceptions (field->type)) {
1989 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1993 has_static_fields = TRUE;
1995 size = mono_type_size (field->type, &align);
1996 field->offset = class->sizes.class_size;
1997 /*align is always non-zero here*/
1998 field->offset += align - 1;
1999 field->offset &= ~(align - 1);
2000 class->sizes.class_size = field->offset + size;
2003 if (has_static_fields && class->sizes.class_size == 0)
2004 /* Simplify code which depends on class_size != 0 if the class has static fields */
2005 class->sizes.class_size = 8;
2009 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2013 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2014 method->klass = class;
2015 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2016 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2017 method->signature = sig;
2018 method->name = name;
2021 if (name [0] == '.') {
2022 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2024 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2030 * mono_class_setup_methods:
2033 * Initializes the 'methods' array in CLASS.
2034 * Calling this method should be avoided if possible since it allocates a lot
2035 * of long-living MonoMethod structures.
2036 * Methods belonging to an interface are assigned a sequential slot starting
2039 * On failure this function sets class->exception_type
2042 mono_class_setup_methods (MonoClass *class)
2045 MonoMethod **methods;
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"));
2063 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2064 count = gklass->method.count;
2065 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2067 for (i = 0; i < count; i++) {
2068 methods [i] = mono_class_inflate_generic_method_full_checked (
2069 gklass->methods [i], class, mono_class_get_context (class), &error);
2070 if (!mono_error_ok (&error)) {
2071 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2072 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)));
2075 mono_error_cleanup (&error);
2079 } else if (class->rank) {
2081 MonoMethod *amethod;
2082 MonoMethodSignature *sig;
2083 int count_generic = 0, first_generic = 0;
2086 count = 3 + (class->rank > 1? 2: 1);
2088 mono_class_setup_interfaces (class, &error);
2089 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2091 if (class->interface_count) {
2092 count_generic = generic_array_methods (class);
2093 first_generic = count;
2094 count += class->interface_count * count_generic;
2097 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2099 sig = mono_metadata_signature_alloc (class->image, class->rank);
2100 sig->ret = &mono_defaults.void_class->byval_arg;
2101 sig->pinvoke = TRUE;
2102 sig->hasthis = TRUE;
2103 for (i = 0; i < class->rank; ++i)
2104 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2106 amethod = create_array_method (class, ".ctor", sig);
2107 methods [method_num++] = amethod;
2108 if (class->rank > 1) {
2109 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2110 sig->ret = &mono_defaults.void_class->byval_arg;
2111 sig->pinvoke = TRUE;
2112 sig->hasthis = TRUE;
2113 for (i = 0; i < class->rank * 2; ++i)
2114 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2116 amethod = create_array_method (class, ".ctor", sig);
2117 methods [method_num++] = amethod;
2119 /* element Get (idx11, [idx2, ...]) */
2120 sig = mono_metadata_signature_alloc (class->image, class->rank);
2121 sig->ret = &class->element_class->byval_arg;
2122 sig->pinvoke = TRUE;
2123 sig->hasthis = TRUE;
2124 for (i = 0; i < class->rank; ++i)
2125 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2126 amethod = create_array_method (class, "Get", sig);
2127 methods [method_num++] = amethod;
2128 /* element& Address (idx11, [idx2, ...]) */
2129 sig = mono_metadata_signature_alloc (class->image, class->rank);
2130 sig->ret = &class->element_class->this_arg;
2131 sig->pinvoke = TRUE;
2132 sig->hasthis = TRUE;
2133 for (i = 0; i < class->rank; ++i)
2134 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2135 amethod = create_array_method (class, "Address", sig);
2136 methods [method_num++] = amethod;
2137 /* void Set (idx11, [idx2, ...], element) */
2138 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2139 sig->ret = &mono_defaults.void_class->byval_arg;
2140 sig->pinvoke = TRUE;
2141 sig->hasthis = TRUE;
2142 for (i = 0; i < class->rank; ++i)
2143 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2144 sig->params [i] = &class->element_class->byval_arg;
2145 amethod = create_array_method (class, "Set", sig);
2146 methods [method_num++] = amethod;
2148 for (i = 0; i < class->interface_count; i++)
2149 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2151 count = class->method.count;
2152 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2153 for (i = 0; i < count; ++i) {
2154 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2155 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2159 if (MONO_CLASS_IS_INTERFACE (class)) {
2161 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2162 for (i = 0; i < count; ++i) {
2163 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2164 methods [i]->slot = slot++;
2168 mono_loader_lock ();
2170 if (class->methods) {
2171 mono_loader_unlock ();
2175 class->method.count = count;
2177 /* Needed because of the double-checking locking pattern */
2178 mono_memory_barrier ();
2180 class->methods = methods;
2182 mono_loader_unlock ();
2186 * mono_class_get_method_by_index:
2188 * Returns class->methods [index], initializing class->methods if neccesary.
2190 * LOCKING: Acquires the loader lock.
2193 mono_class_get_method_by_index (MonoClass *class, int index)
2195 /* Avoid calling setup_methods () if possible */
2196 if (class->generic_class && !class->methods) {
2197 MonoClass *gklass = class->generic_class->container_class;
2200 m = mono_class_inflate_generic_method_full (
2201 gklass->methods [index], class, mono_class_get_context (class));
2203 * If setup_methods () is called later for this class, no duplicates are created,
2204 * since inflate_generic_method guarantees that only one instance of a method
2205 * is created for each context.
2208 mono_class_setup_methods (class);
2209 g_assert (m == class->methods [index]);
2213 mono_class_setup_methods (class);
2214 if (class->exception_type) /*FIXME do proper error handling*/
2216 g_assert (index >= 0 && index < class->method.count);
2217 return class->methods [index];
2222 * mono_class_get_inflated_method:
2224 * Given an inflated class CLASS and a method METHOD which should be a method of
2225 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2228 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2230 MonoClass *gklass = class->generic_class->container_class;
2233 g_assert (method->klass == gklass);
2235 mono_class_setup_methods (gklass);
2236 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2238 for (i = 0; i < gklass->method.count; ++i) {
2239 if (gklass->methods [i] == method) {
2241 return class->methods [i];
2243 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2251 * mono_class_get_vtable_entry:
2253 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2254 * LOCKING: Acquires the loader lock.
2257 mono_class_get_vtable_entry (MonoClass *class, int offset)
2261 if (class->rank == 1) {
2263 * szarrays do not overwrite any methods of Array, so we can avoid
2264 * initializing their vtables in some cases.
2266 mono_class_setup_vtable (class->parent);
2267 if (offset < class->parent->vtable_size)
2268 return class->parent->vtable [offset];
2271 if (class->generic_class) {
2272 MonoClass *gklass = class->generic_class->container_class;
2273 mono_class_setup_vtable (gklass);
2274 m = gklass->vtable [offset];
2276 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2278 mono_class_setup_vtable (class);
2279 if (class->exception_type)
2281 m = class->vtable [offset];
2288 * mono_class_get_vtable_size:
2290 * Return the vtable size for KLASS.
2293 mono_class_get_vtable_size (MonoClass *klass)
2295 mono_class_setup_vtable (klass);
2297 return klass->vtable_size;
2301 * mono_class_setup_properties:
2303 * Initialize class->ext.property and class->ext.properties.
2305 * This method can fail the class.
2308 mono_class_setup_properties (MonoClass *class)
2310 guint startm, endm, i, j;
2311 guint32 cols [MONO_PROPERTY_SIZE];
2312 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2313 MonoProperty *properties;
2317 if (class->ext && class->ext->properties)
2320 if (class->generic_class) {
2321 MonoClass *gklass = class->generic_class->container_class;
2323 mono_class_init (gklass);
2324 mono_class_setup_properties (gklass);
2325 if (gklass->exception_type) {
2326 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2330 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2332 for (i = 0; i < gklass->ext->property.count; i++) {
2333 MonoProperty *prop = &properties [i];
2335 *prop = gklass->ext->properties [i];
2338 prop->get = mono_class_inflate_generic_method_full (
2339 prop->get, class, mono_class_get_context (class));
2341 prop->set = mono_class_inflate_generic_method_full (
2342 prop->set, class, mono_class_get_context (class));
2344 prop->parent = class;
2347 first = gklass->ext->property.first;
2348 count = gklass->ext->property.count;
2350 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2351 count = last - first;
2354 mono_class_setup_methods (class);
2355 if (class->exception_type)
2359 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2360 for (i = first; i < last; ++i) {
2361 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2362 properties [i - first].parent = class;
2363 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2364 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2366 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2367 for (j = startm; j < endm; ++j) {
2370 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2372 if (class->image->uncompressed_metadata)
2373 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2374 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2376 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2378 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2379 case METHOD_SEMANTIC_SETTER:
2380 properties [i - first].set = method;
2382 case METHOD_SEMANTIC_GETTER:
2383 properties [i - first].get = method;
2392 mono_loader_lock ();
2394 if (class->ext && class->ext->properties) {
2395 /* We leak 'properties' which was allocated from the image mempool */
2396 mono_loader_unlock ();
2400 mono_class_alloc_ext (class);
2402 class->ext->property.first = first;
2403 class->ext->property.count = count;
2405 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2406 mono_memory_barrier ();
2408 /* Leave this assignment as the last op in the function */
2409 class->ext->properties = properties;
2411 mono_loader_unlock ();
2415 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2417 MonoMethod **om, **retval;
2420 for (om = methods, count = 0; *om; ++om, ++count)
2423 retval = g_new0 (MonoMethod*, count + 1);
2425 for (om = methods, count = 0; *om; ++om, ++count)
2426 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2431 /*This method can fail the class.*/
2433 mono_class_setup_events (MonoClass *class)
2436 guint startm, endm, i, j;
2437 guint32 cols [MONO_EVENT_SIZE];
2438 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2442 if (class->ext && class->ext->events)
2445 if (class->generic_class) {
2446 MonoClass *gklass = class->generic_class->container_class;
2447 MonoGenericContext *context;
2449 mono_class_setup_events (gklass);
2450 if (gklass->exception_type) {
2451 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2455 first = gklass->ext->event.first;
2456 count = gklass->ext->event.count;
2458 events = mono_class_new0 (class, MonoEvent, count);
2461 context = mono_class_get_context (class);
2463 for (i = 0; i < count; i++) {
2464 MonoEvent *event = &events [i];
2465 MonoEvent *gevent = &gklass->ext->events [i];
2467 event->parent = class;
2468 event->name = gevent->name;
2469 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2470 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2471 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2472 #ifndef MONO_SMALL_CONFIG
2473 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2475 event->attrs = gevent->attrs;
2478 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2479 count = last - first;
2482 mono_class_setup_methods (class);
2483 if (class->exception_type) {
2484 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2489 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2490 for (i = first; i < last; ++i) {
2491 MonoEvent *event = &events [i - first];
2493 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2494 event->parent = class;
2495 event->attrs = cols [MONO_EVENT_FLAGS];
2496 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2498 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2499 for (j = startm; j < endm; ++j) {
2502 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2504 if (class->image->uncompressed_metadata)
2505 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2506 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2508 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2510 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2511 case METHOD_SEMANTIC_ADD_ON:
2512 event->add = method;
2514 case METHOD_SEMANTIC_REMOVE_ON:
2515 event->remove = method;
2517 case METHOD_SEMANTIC_FIRE:
2518 event->raise = method;
2520 case METHOD_SEMANTIC_OTHER: {
2521 #ifndef MONO_SMALL_CONFIG
2524 if (event->other == NULL) {
2525 event->other = g_new0 (MonoMethod*, 2);
2527 while (event->other [n])
2529 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2531 event->other [n] = method;
2532 /* NULL terminated */
2533 event->other [n + 1] = NULL;
2544 mono_loader_lock ();
2546 if (class->ext && class->ext->events) {
2547 mono_loader_unlock ();
2551 mono_class_alloc_ext (class);
2553 class->ext->event.first = first;
2554 class->ext->event.count = count;
2556 /* Flush any pending writes as we do double checked locking on class->ext.events */
2557 mono_memory_barrier ();
2559 /* Leave this assignment as the last op in the function */
2560 class->ext->events = events;
2562 mono_loader_unlock ();
2566 * Global pool of interface IDs, represented as a bitset.
2567 * LOCKING: this is supposed to be accessed with the loader lock held.
2569 static MonoBitSet *global_interface_bitset = NULL;
2572 * mono_unload_interface_ids:
2573 * @bitset: bit set of interface IDs
2575 * When an image is unloaded, the interface IDs associated with
2576 * the image are put back in the global pool of IDs so the numbers
2580 mono_unload_interface_ids (MonoBitSet *bitset)
2582 mono_loader_lock ();
2583 mono_bitset_sub (global_interface_bitset, bitset);
2584 mono_loader_unlock ();
2588 mono_unload_interface_id (MonoClass *class)
2590 if (global_interface_bitset && class->interface_id) {
2591 mono_loader_lock ();
2592 mono_bitset_clear (global_interface_bitset, class->interface_id);
2593 mono_loader_unlock ();
2598 * mono_get_unique_iid:
2601 * Assign a unique integer ID to the interface represented by @class.
2602 * The ID will positive and as small as possible.
2603 * LOCKING: this is supposed to be called with the loader lock held.
2604 * Returns: the new ID.
2607 mono_get_unique_iid (MonoClass *class)
2611 g_assert (MONO_CLASS_IS_INTERFACE (class));
2613 if (!global_interface_bitset) {
2614 global_interface_bitset = mono_bitset_new (128, 0);
2617 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2619 int old_size = mono_bitset_size (global_interface_bitset);
2620 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2621 mono_bitset_free (global_interface_bitset);
2622 global_interface_bitset = new_set;
2625 mono_bitset_set (global_interface_bitset, iid);
2626 /* set the bit also in the per-image set */
2627 if (!class->generic_class) {
2628 if (class->image->interface_bitset) {
2629 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2630 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2631 mono_bitset_free (class->image->interface_bitset);
2632 class->image->interface_bitset = new_set;
2635 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2637 mono_bitset_set (class->image->interface_bitset, iid);
2640 #ifndef MONO_SMALL_CONFIG
2641 if (mono_print_vtable) {
2643 char *type_name = mono_type_full_name (&class->byval_arg);
2644 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2645 generic_id = class->generic_class->context.class_inst->id;
2646 g_assert (generic_id != 0);
2650 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2655 g_assert (iid <= 65535);
2660 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2665 mono_class_setup_interfaces (klass, error);
2666 if (!mono_error_ok (error))
2669 for (i = 0; i < klass->interface_count; i++) {
2670 ic = klass->interfaces [i];
2673 *res = g_ptr_array_new ();
2674 g_ptr_array_add (*res, ic);
2675 mono_class_init (ic);
2676 if (ic->exception_type) {
2677 mono_error_set_type_load_class (error, ic, "Error Loading class");
2681 collect_implemented_interfaces_aux (ic, res, error);
2682 if (!mono_error_ok (error))
2688 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2690 GPtrArray *res = NULL;
2692 collect_implemented_interfaces_aux (klass, &res, error);
2693 if (!mono_error_ok (error)) {
2695 g_ptr_array_free (res, TRUE);
2702 compare_interface_ids (const void *p_key, const void *p_element) {
2703 const MonoClass *key = p_key;
2704 const MonoClass *element = *(MonoClass**) p_element;
2706 return (key->interface_id - element->interface_id);
2709 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2711 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2712 MonoClass **result = mono_binary_search (
2714 klass->interfaces_packed,
2715 klass->interface_offsets_count,
2716 sizeof (MonoClass *),
2717 compare_interface_ids);
2719 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2726 * mono_class_interface_offset_with_variance:
2728 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2729 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2731 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2733 * FIXME figure out MS disambiguation rules and fix this function.
2736 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2737 int i = mono_class_interface_offset (klass, itf);
2738 *non_exact_match = FALSE;
2742 if (!mono_class_has_variant_generic_params (itf))
2745 for (i = 0; i < klass->interface_offsets_count; i++) {
2746 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2747 *non_exact_match = TRUE;
2748 return klass->interface_offsets_packed [i];
2756 print_implemented_interfaces (MonoClass *klass) {
2759 GPtrArray *ifaces = NULL;
2761 int ancestor_level = 0;
2763 name = mono_type_get_full_name (klass);
2764 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2767 for (i = 0; i < klass->interface_offsets_count; i++)
2768 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2769 klass->interfaces_packed [i]->interface_id,
2770 klass->interface_offsets_packed [i],
2771 klass->interfaces_packed [i]->method.count,
2772 klass->interfaces_packed [i]->name_space,
2773 klass->interfaces_packed [i]->name );
2774 printf ("Interface flags: ");
2775 for (i = 0; i <= klass->max_interface_id; i++)
2776 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2777 printf ("(%d,T)", i);
2779 printf ("(%d,F)", i);
2781 printf ("Dump interface flags:");
2782 #ifdef COMPRESSED_INTERFACE_BITMAP
2784 const uint8_t* p = klass->interface_bitmap;
2785 i = klass->max_interface_id;
2787 printf (" %d x 00 %02X", p [0], p [1]);
2793 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2794 printf (" %02X", klass->interface_bitmap [i]);
2797 while (klass != NULL) {
2798 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2799 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2800 if (!mono_error_ok (&error)) {
2801 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2802 mono_error_cleanup (&error);
2803 } else if (ifaces) {
2804 for (i = 0; i < ifaces->len; i++) {
2805 MonoClass *ic = g_ptr_array_index (ifaces, i);
2806 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2807 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2809 mono_class_interface_offset (klass, ic),
2814 g_ptr_array_free (ifaces, TRUE);
2817 klass = klass->parent;
2822 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2825 args [0] = &arg0->byval_arg;
2827 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2831 array_class_get_if_rank (MonoClass *class, guint rank)
2833 return rank ? mono_array_class_get (class, rank) : class;
2837 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2839 valuetype_types [0] = eclass;
2840 if (eclass == mono_defaults.int16_class)
2841 valuetype_types [1] = mono_defaults.uint16_class;
2842 else if (eclass == mono_defaults.uint16_class)
2843 valuetype_types [1] = mono_defaults.int16_class;
2844 else if (eclass == mono_defaults.int32_class)
2845 valuetype_types [1] = mono_defaults.uint32_class;
2846 else if (eclass == mono_defaults.uint32_class)
2847 valuetype_types [1] = mono_defaults.int32_class;
2848 else if (eclass == mono_defaults.int64_class)
2849 valuetype_types [1] = mono_defaults.uint64_class;
2850 else if (eclass == mono_defaults.uint64_class)
2851 valuetype_types [1] = mono_defaults.int64_class;
2852 else if (eclass == mono_defaults.byte_class)
2853 valuetype_types [1] = mono_defaults.sbyte_class;
2854 else if (eclass == mono_defaults.sbyte_class)
2855 valuetype_types [1] = mono_defaults.byte_class;
2856 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2857 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2860 /* this won't be needed once bug #325495 is completely fixed
2861 * though we'll need something similar to know which interfaces to allow
2862 * in arrays when they'll be lazyly created
2864 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2865 * MS returns diferrent types based on which instance is called. For example:
2866 * object obj = new byte[10][];
2867 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2868 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2871 * Fixing this should kill quite some code, save some bits and improve compatibility.
2874 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2876 MonoClass *eclass = class->element_class;
2877 static MonoClass* generic_icollection_class = NULL;
2878 static MonoClass* generic_ienumerable_class = NULL;
2879 static MonoClass* generic_ienumerator_class = NULL;
2880 static MonoClass* generic_ireadonlylist_class = NULL;
2881 static MonoClass* generic_ireadonlycollection_class = NULL;
2882 MonoClass *valuetype_types[2] = { NULL, NULL };
2883 MonoClass **interfaces = NULL;
2884 int i, nifaces, interface_count, real_count, original_rank;
2886 gboolean internal_enumerator;
2887 gboolean eclass_is_valuetype;
2889 if (!mono_defaults.generic_ilist_class) {
2893 internal_enumerator = FALSE;
2894 eclass_is_valuetype = FALSE;
2895 original_rank = eclass->rank;
2896 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2897 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2899 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2901 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2902 original_rank = eclass->rank;
2904 eclass = eclass->element_class;
2905 internal_enumerator = TRUE;
2906 *is_enumerator = TRUE;
2914 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2915 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2917 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2919 if (!generic_icollection_class) {
2920 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2921 "System.Collections.Generic", "ICollection`1");
2922 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2923 "System.Collections.Generic", "IEnumerable`1");
2924 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2925 "System.Collections.Generic", "IEnumerator`1");
2926 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2927 "System.Collections.Generic", "IReadOnlyList`1");
2928 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2929 "System.Collections.Generic", "IReadOnlyCollection`1");
2932 mono_class_init (eclass);
2935 * Arrays in 2.0 need to implement a number of generic interfaces
2936 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2937 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2938 * We collect the types needed to build the
2939 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2940 * the generic interfaces needed to implement.
2942 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2943 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2945 if (eclass->valuetype) {
2946 nifaces = generic_ireadonlylist_class ? 5 : 3;
2947 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2949 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2950 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2951 if (internal_enumerator) {
2953 if (valuetype_types [1])
2957 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2958 interfaces [0] = valuetype_types [0];
2959 if (valuetype_types [1])
2960 interfaces [nifaces] = valuetype_types [1];
2962 eclass_is_valuetype = TRUE;
2965 int idepth = eclass->idepth;
2966 if (!internal_enumerator)
2968 nifaces = generic_ireadonlylist_class ? 2 : 3;
2970 // FIXME: This doesn't seem to work/required for generic params
2971 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
2972 mono_class_setup_interface_offsets (eclass);
2974 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2975 /* we add object for interfaces and the supertypes for the other
2976 * types. The last of the supertypes is the element class itself which we
2977 * already created the explicit interfaces for (so we include it for IEnumerator
2978 * and exclude it for arrays).
2980 if (MONO_CLASS_IS_INTERFACE (eclass))
2983 interface_count += idepth;
2984 if (eclass->rank && eclass->element_class->valuetype) {
2985 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2986 if (valuetype_types [1])
2989 /* IList, ICollection, IEnumerable, IReadOnlyList */
2990 interface_count *= nifaces;
2991 real_count = interface_count;
2992 if (internal_enumerator) {
2993 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2994 if (valuetype_types [1])
2997 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2998 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2999 interfaces [0] = mono_defaults.object_class;
3003 for (i = 0; i < idepth; i++) {
3004 mono_class_init (eclass->supertypes [i]);
3005 interfaces [j] = eclass->supertypes [i];
3009 if (all_interfaces) {
3010 for (i = 0; i < eclass->interface_offsets_count; i++) {
3011 interfaces [j] = eclass->interfaces_packed [i];
3015 for (i = 0; i < eclass->interface_count; i++) {
3016 interfaces [j] = eclass->interfaces [i];
3020 if (valuetype_types [1]) {
3021 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3026 /* instantiate the generic interfaces */
3027 for (i = 0; i < interface_count; i += nifaces) {
3028 MonoClass *iface = interfaces [i];
3030 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3031 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3033 if (eclass->valuetype) {
3034 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3035 if (generic_ireadonlylist_class) {
3036 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3037 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3040 if (!generic_ireadonlylist_class)
3041 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3044 if (internal_enumerator) {
3046 /* instantiate IEnumerator<iface> */
3047 for (i = 0; i < interface_count; i++) {
3048 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3050 j = interface_count;
3051 if (!eclass_is_valuetype) {
3052 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3053 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3056 for (i = 0; i < eclass->idepth; i++) {
3057 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3061 for (i = 0; i < eclass->interface_offsets_count; i++) {
3062 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3066 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3068 if (valuetype_types [1])
3069 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3073 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3074 for (i = 0; i < real_count; ++i) {
3075 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3076 g_print ("%s implements %s\n", type_name, name);
3087 find_array_interface (MonoClass *klass, const char *name)
3090 for (i = 0; i < klass->interface_count; ++i) {
3091 if (strcmp (klass->interfaces [i]->name, name) == 0)
3098 * Return the number of virtual methods.
3099 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3100 * Return -1 on failure.
3101 * FIXME It would be nice if this information could be cached somewhere.
3104 count_virtual_methods (MonoClass *class)
3108 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3110 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3111 mono_class_setup_methods (class);
3112 if (class->exception_type)
3115 for (i = 0; i < class->method.count; ++i) {
3116 flags = class->methods [i]->flags;
3117 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3121 for (i = 0; i < class->method.count; ++i) {
3122 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3124 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3132 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3140 m = (l + num_ifaces) / 2;
3141 if (interfaces_full [m] == ic)
3143 if (l == num_ifaces)
3145 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3154 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3156 int i = find_interface (num_ifaces, interfaces_full, ic);
3158 return interface_offsets_full [i];
3163 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3165 int i = find_interface (num_ifaces, interfaces_full, ic);
3169 interface_offsets_full [i] = offset;
3172 for (i = 0; i < num_ifaces; ++i) {
3173 if (interfaces_full [i]) {
3175 if (interfaces_full [i]->interface_id < ic->interface_id)
3178 while (end < num_ifaces && interfaces_full [end]) end++;
3179 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3180 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3182 interfaces_full [i] = ic;
3183 interface_offsets_full [i] = offset;
3189 #ifdef COMPRESSED_INTERFACE_BITMAP
3192 * Compressed interface bitmap design.
3194 * Interface bitmaps take a large amount of memory, because their size is
3195 * linear with the maximum interface id assigned in the process (each interface
3196 * is assigned a unique id as it is loaded). The number of interface classes
3197 * is high because of the many implicit interfaces implemented by arrays (we'll
3198 * need to lazy-load them in the future).
3199 * Most classes implement a very small number of interfaces, so the bitmap is
3200 * sparse. This bitmap needs to be checked by interface casts, so access to the
3201 * needed bit must be fast and doable with few jit instructions.
3203 * The current compression format is as follows:
3204 * *) it is a sequence of one or more two-byte elements
3205 * *) the first byte in the element is the count of empty bitmap bytes
3206 * at the current bitmap position
3207 * *) the second byte in the element is an actual bitmap byte at the current
3210 * As an example, the following compressed bitmap bytes:
3211 * 0x07 0x01 0x00 0x7
3212 * correspond to the following bitmap:
3213 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3215 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3216 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3217 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3221 * mono_compress_bitmap:
3222 * @dest: destination buffer
3223 * @bitmap: bitmap buffer
3224 * @size: size of @bitmap in bytes
3226 * This is a mono internal function.
3227 * The @bitmap data is compressed into a format that is small but
3228 * still searchable in few instructions by the JIT and runtime.
3229 * The compressed data is stored in the buffer pointed to by the
3230 * @dest array. Passing a #NULL value for @dest allows to just compute
3231 * the size of the buffer.
3232 * This compression algorithm assumes the bits set in the bitmap are
3233 * few and far between, like in interface bitmaps.
3234 * Returns: the size of the compressed bitmap in bytes.
3237 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3241 const uint8_t *end = bitmap + size;
3242 while (bitmap < end) {
3243 if (*bitmap || numz == 255) {
3267 * mono_class_interface_match:
3268 * @bitmap: a compressed bitmap buffer
3269 * @id: the index to check in the bitmap
3271 * This is a mono internal function.
3272 * Checks if a bit is set in a compressed interface bitmap. @id must
3273 * be already checked for being smaller than the maximum id encoded in the
3276 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3280 mono_class_interface_match (const uint8_t *bitmap, int id)
3283 id -= bitmap [0] * 8;
3287 return bitmap [1] & (1 << id);
3296 * LOCKING: this is supposed to be called with the loader lock held.
3297 * Return -1 on failure and set exception_type
3300 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3304 int i, j, max_iid, num_ifaces;
3305 MonoClass **interfaces_full = NULL;
3306 int *interface_offsets_full = NULL;
3308 GPtrArray **ifaces_array = NULL;
3309 int interface_offsets_count;
3310 MonoClass **array_interfaces = NULL;
3311 int num_array_interfaces;
3312 int is_enumerator = FALSE;
3314 mono_class_setup_supertypes (class);
3316 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3317 * implicit interfaces have the property that they are assigned the same slot in the
3318 * vtables for compatible interfaces
3320 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3322 /* compute maximum number of slots and maximum interface id */
3324 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3325 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3326 for (j = 0; j < class->idepth; j++) {
3327 k = class->supertypes [j];
3328 num_ifaces += k->interface_count;
3329 for (i = 0; i < k->interface_count; i++) {
3330 ic = k->interfaces [i];
3333 mono_class_init (ic);
3335 if (max_iid < ic->interface_id)
3336 max_iid = ic->interface_id;
3338 ifaces = mono_class_get_implemented_interfaces (k, &error);
3339 if (!mono_error_ok (&error)) {
3340 char *name = mono_type_get_full_name (k);
3341 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)));
3343 mono_error_cleanup (&error);
3348 num_ifaces += ifaces->len;
3349 for (i = 0; i < ifaces->len; ++i) {
3350 ic = g_ptr_array_index (ifaces, i);
3351 if (max_iid < ic->interface_id)
3352 max_iid = ic->interface_id;
3354 ifaces_array [j] = ifaces;
3358 for (i = 0; i < num_array_interfaces; ++i) {
3359 ic = array_interfaces [i];
3360 mono_class_init (ic);
3361 if (max_iid < ic->interface_id)
3362 max_iid = ic->interface_id;
3365 if (MONO_CLASS_IS_INTERFACE (class)) {
3367 if (max_iid < class->interface_id)
3368 max_iid = class->interface_id;
3370 class->max_interface_id = max_iid;
3371 /* compute vtable offset for interfaces */
3372 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3373 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3375 for (i = 0; i < num_ifaces; i++) {
3376 interface_offsets_full [i] = -1;
3379 /* skip the current class */
3380 for (j = 0; j < class->idepth - 1; j++) {
3381 k = class->supertypes [j];
3382 ifaces = ifaces_array [j];
3385 for (i = 0; i < ifaces->len; ++i) {
3387 ic = g_ptr_array_index (ifaces, i);
3389 /*Force the sharing of interface offsets between parent and subtypes.*/
3390 io = mono_class_interface_offset (k, ic);
3392 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3397 g_assert (class == class->supertypes [class->idepth - 1]);
3398 ifaces = ifaces_array [class->idepth - 1];
3400 for (i = 0; i < ifaces->len; ++i) {
3402 ic = g_ptr_array_index (ifaces, i);
3403 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3405 count = count_virtual_methods (ic);
3407 char *name = mono_type_get_full_name (ic);
3408 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3417 if (MONO_CLASS_IS_INTERFACE (class))
3418 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3420 if (num_array_interfaces) {
3421 if (is_enumerator) {
3422 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3423 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3424 g_assert (ienumerator_offset >= 0);
3425 for (i = 0; i < num_array_interfaces; ++i) {
3426 ic = array_interfaces [i];
3427 if (strcmp (ic->name, "IEnumerator`1") == 0)
3428 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3430 g_assert_not_reached ();
3431 /*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);*/
3434 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3435 int ilist_iface_idx = find_array_interface (class, "IList`1");
3436 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3437 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3438 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3439 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3440 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3441 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3442 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3443 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3444 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3445 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3446 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3447 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3448 for (i = 0; i < num_array_interfaces; ++i) {
3450 ic = array_interfaces [i];
3451 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3452 offset = ilist_offset;
3453 else if (strcmp (ic->name, "ICollection`1") == 0)
3454 offset = icollection_offset;
3455 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3456 offset = ienumerable_offset;
3457 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3458 offset = ireadonlylist_offset;
3459 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3460 offset = ireadonlycollection_offset;
3462 g_assert_not_reached ();
3463 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3464 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3469 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3470 if (interface_offsets_full [i] != -1) {
3471 interface_offsets_count ++;
3476 * We might get called multiple times:
3477 * - mono_class_init ()
3478 * - mono_class_setup_vtable ().
3479 * - mono_class_setup_interface_offsets ().
3480 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3481 * means we have to overwrite those when called from other places (#4440).
3483 if (class->interfaces_packed && !overwrite) {
3484 g_assert (class->interface_offsets_count == interface_offsets_count);
3488 class->interface_offsets_count = interface_offsets_count;
3489 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3490 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3491 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3492 #ifdef COMPRESSED_INTERFACE_BITMAP
3493 bitmap = g_malloc0 (bsize);
3495 bitmap = mono_class_alloc0 (class, bsize);
3497 for (i = 0; i < interface_offsets_count; i++) {
3498 int id = interfaces_full [i]->interface_id;
3499 bitmap [id >> 3] |= (1 << (id & 7));
3500 class->interfaces_packed [i] = interfaces_full [i];
3501 class->interface_offsets_packed [i] = interface_offsets_full [i];
3502 /*if (num_array_interfaces)
3503 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]);*/
3505 #ifdef COMPRESSED_INTERFACE_BITMAP
3506 i = mono_compress_bitmap (NULL, bitmap, bsize);
3507 class->interface_bitmap = mono_class_alloc0 (class, i);
3508 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3511 class->interface_bitmap = bitmap;
3516 g_free (interfaces_full);
3517 g_free (interface_offsets_full);
3518 g_free (array_interfaces);
3519 for (i = 0; i < class->idepth; i++) {
3520 ifaces = ifaces_array [i];
3522 g_ptr_array_free (ifaces, TRUE);
3524 g_free (ifaces_array);
3526 //printf ("JUST DONE: ");
3527 //print_implemented_interfaces (class);
3533 * Setup interface offsets for interfaces.
3535 * - class->max_interface_id
3536 * - class->interface_offsets_count
3537 * - class->interfaces_packed
3538 * - class->interface_offsets_packed
3539 * - class->interface_bitmap
3541 * This function can fail @class.
3544 mono_class_setup_interface_offsets (MonoClass *class)
3546 mono_loader_lock ();
3548 setup_interface_offsets (class, 0, FALSE);
3550 mono_loader_unlock ();
3553 /*Checks if @klass has @parent as one of it's parents type gtd
3557 * Bar<T> : Foo<Bar<Bar<T>>>
3561 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3563 klass = mono_class_get_generic_type_definition (klass);
3564 parent = mono_class_get_generic_type_definition (parent);
3565 mono_class_setup_supertypes (klass);
3566 mono_class_setup_supertypes (parent);
3568 return klass->idepth >= parent->idepth &&
3569 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3573 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3575 MonoGenericInst *ginst;
3577 if (!class->generic_class) {
3578 mono_class_setup_vtable_full (class, in_setup);
3579 return class->exception_type == 0;
3582 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3583 if (class->generic_class->container_class->exception_type) {
3584 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3588 ginst = class->generic_class->context.class_inst;
3589 for (i = 0; i < ginst->type_argc; ++i) {
3591 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3593 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3594 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3595 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3597 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3598 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3606 * mono_class_setup_vtable:
3608 * Creates the generic vtable of CLASS.
3609 * Initializes the following fields in MonoClass:
3612 * Plus all the fields initialized by setup_interface_offsets ().
3613 * If there is an error during vtable construction, class->exception_type is set.
3615 * LOCKING: Acquires the loader lock.
3618 mono_class_setup_vtable (MonoClass *class)
3620 mono_class_setup_vtable_full (class, NULL);
3624 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3626 MonoMethod **overrides;
3627 MonoGenericContext *context;
3635 if (MONO_CLASS_IS_INTERFACE (class)) {
3636 /* This sets method->slot for all methods if this is an interface */
3637 mono_class_setup_methods (class);
3641 if (class->exception_type)
3644 if (g_list_find (in_setup, class))
3647 mono_loader_lock ();
3649 if (class->vtable) {
3650 mono_loader_unlock ();
3654 mono_stats.generic_vtable_count ++;
3655 in_setup = g_list_prepend (in_setup, class);
3657 if (class->generic_class) {
3658 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3659 mono_loader_unlock ();
3660 g_list_remove (in_setup, class);
3664 context = mono_class_get_context (class);
3665 type_token = class->generic_class->container_class->type_token;
3667 context = (MonoGenericContext *) class->generic_container;
3668 type_token = class->type_token;
3671 if (image_is_dynamic (class->image)) {
3672 /* Generic instances can have zero method overrides without causing any harm.
3673 * This is true since we don't do layout all over again for them, we simply inflate
3674 * the layout of the parent.
3676 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3678 /* The following call fails if there are missing methods in the type */
3679 /* FIXME it's probably a good idea to avoid this for generic instances. */
3680 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3684 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3686 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3690 mono_loader_unlock ();
3691 g_list_remove (in_setup, class);
3696 #define DEBUG_INTERFACE_VTABLE_CODE 0
3697 #define TRACE_INTERFACE_VTABLE_CODE 0
3698 #define VERIFY_INTERFACE_VTABLE_CODE 0
3699 #define VTABLE_SELECTOR (1)
3701 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3702 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3703 if (!(VTABLE_SELECTOR)) break; \
3707 #define DEBUG_INTERFACE_VTABLE(stmt)
3710 #if TRACE_INTERFACE_VTABLE_CODE
3711 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3712 if (!(VTABLE_SELECTOR)) break; \
3716 #define TRACE_INTERFACE_VTABLE(stmt)
3719 #if VERIFY_INTERFACE_VTABLE_CODE
3720 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3721 if (!(VTABLE_SELECTOR)) break; \
3725 #define VERIFY_INTERFACE_VTABLE(stmt)
3729 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3731 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3735 GString *res = g_string_new ("");
3737 g_string_append_c (res, '(');
3738 for (i = 0; i < sig->param_count; ++i) {
3740 g_string_append_c (res, ',');
3741 mono_type_get_desc (res, sig->params [i], include_namespace);
3743 g_string_append (res, ")=>");
3744 if (sig->ret != NULL) {
3745 mono_type_get_desc (res, sig->ret, include_namespace);
3747 g_string_append (res, "NULL");
3750 g_string_free (res, FALSE);
3754 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3755 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3756 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3757 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3765 is_wcf_hack_disabled (void)
3767 static gboolean disabled;
3768 static gboolean inited = FALSE;
3770 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3777 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) {
3778 MonoMethodSignature *cmsig, *imsig;
3779 if (strcmp (im->name, cm->name) == 0) {
3780 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3781 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3784 if (! slot_is_empty) {
3785 if (require_newslot) {
3786 if (! interface_is_explicitly_implemented_by_class) {
3787 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3790 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3791 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3795 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3798 cmsig = mono_method_signature (cm);
3799 imsig = mono_method_signature (im);
3800 if (!cmsig || !imsig) {
3801 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3805 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3806 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3807 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3808 TRACE_INTERFACE_VTABLE (printf ("]"));
3811 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3812 /* CAS - SecurityAction.InheritanceDemand on interface */
3813 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3814 mono_secman_inheritancedemand_method (cm, im);
3817 if (mono_security_core_clr_enabled ())
3818 mono_security_core_clr_check_override (class, cm, im);
3820 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3821 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3822 char *body_name = mono_method_full_name (cm, TRUE);
3823 char *decl_name = mono_method_full_name (im, TRUE);
3824 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));
3832 MonoClass *ic = im->klass;
3833 const char *ic_name_space = ic->name_space;
3834 const char *ic_name = ic->name;
3837 if (! require_newslot) {
3838 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3841 if (cm->klass->rank == 0) {
3842 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3845 cmsig = mono_method_signature (cm);
3846 imsig = mono_method_signature (im);
3847 if (!cmsig || !imsig) {
3848 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3852 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3853 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3854 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3855 TRACE_INTERFACE_VTABLE (printf ("]"));
3858 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3859 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3862 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3863 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3866 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))) {
3867 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3871 subname = strstr (cm->name, ic_name_space);
3872 if (subname != cm->name) {
3873 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3876 subname += strlen (ic_name_space);
3877 if (subname [0] != '.') {
3878 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3882 if (strstr (subname, ic_name) != subname) {
3883 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3886 subname += strlen (ic_name);
3887 if (subname [0] != '.') {
3888 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3892 if (strcmp (subname, im->name) != 0) {
3893 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3897 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3898 /* CAS - SecurityAction.InheritanceDemand on interface */
3899 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3900 mono_secman_inheritancedemand_method (cm, im);
3903 if (mono_security_core_clr_enabled ())
3904 mono_security_core_clr_check_override (class, cm, im);
3906 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3907 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3908 char *body_name = mono_method_full_name (cm, TRUE);
3909 char *decl_name = mono_method_full_name (im, TRUE);
3910 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));
3920 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3922 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3923 MonoMethod *method = key;
3924 MonoMethod *override = value;
3925 MonoClass *method_class = mono_method_get_class (method);
3926 MonoClass *override_class = mono_method_get_class (override);
3928 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3929 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3930 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3933 print_overrides (GHashTable *override_map, const char *message) {
3935 printf ("Override map \"%s\" START:\n", message);
3936 g_hash_table_foreach (override_map, foreach_override, NULL);
3937 printf ("Override map \"%s\" END.\n", message);
3939 printf ("Override map \"%s\" EMPTY.\n", message);
3943 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3944 char *full_name = mono_type_full_name (&class->byval_arg);
3948 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3950 if (print_interfaces) {
3951 print_implemented_interfaces (class);
3952 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3955 if (class->parent) {
3956 parent_size = class->parent->vtable_size;
3960 for (i = 0; i < size; ++i) {
3961 MonoMethod *cm = vtable [i];
3962 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3963 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3965 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3973 #if VERIFY_INTERFACE_VTABLE_CODE
3975 mono_method_try_get_vtable_index (MonoMethod *method)
3977 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3978 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3979 if (imethod->declaring->is_generic)
3980 return imethod->declaring->slot;
3982 return method->slot;
3986 mono_class_verify_vtable (MonoClass *class)
3989 char *full_name = mono_type_full_name (&class->byval_arg);
3991 printf ("*** Verifying VTable of class '%s' \n", full_name);
3995 if (!class->methods)
3998 for (i = 0; i < class->method.count; ++i) {
3999 MonoMethod *cm = class->methods [i];
4002 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4006 full_name = mono_method_full_name (cm, TRUE);
4008 slot = mono_method_try_get_vtable_index (cm);
4010 if (slot >= class->vtable_size) {
4011 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4015 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4016 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4017 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4018 g_free (other_name);
4021 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4028 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4030 char *method_signature;
4033 for (index = 0; index < onum; ++index) {
4034 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4035 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4037 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4038 type_name = mono_type_full_name (&class->byval_arg);
4039 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4040 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4041 g_free (method_signature);
4043 mono_class_setup_methods (class);
4044 if (class->exception_type) {
4045 char *name = mono_type_get_full_name (class);
4046 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4050 for (index = 0; index < class->method.count; ++index) {
4051 MonoMethod *cm = class->methods [index];
4052 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4054 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4055 g_free (method_signature);
4060 mono_method_get_method_definition (MonoMethod *method)
4062 while (method->is_inflated)
4063 method = ((MonoMethodInflated*)method)->declaring;
4068 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4072 for (i = 0; i < onum; ++i) {
4073 MonoMethod *decl = overrides [i * 2];
4074 MonoMethod *body = overrides [i * 2 + 1];
4076 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4077 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4081 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4082 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4083 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4085 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4089 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4090 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4091 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4093 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4097 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4098 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4102 body = mono_method_get_method_definition (body);
4103 decl = mono_method_get_method_definition (decl);
4105 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4106 char *body_name = mono_method_full_name (body, TRUE);
4107 char *decl_name = mono_method_full_name (decl, TRUE);
4108 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));
4118 mono_class_need_stelemref_method (MonoClass *class)
4120 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4124 * LOCKING: this is supposed to be called with the loader lock held.
4127 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4131 MonoMethod **vtable;
4132 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4133 GPtrArray *ifaces = NULL;
4134 GHashTable *override_map = NULL;
4135 gboolean security_enabled = mono_security_enabled ();
4137 gpointer class_iter;
4138 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4139 int first_non_interface_slot;
4141 GSList *virt_methods = NULL, *l;
4142 int stelemref_slot = 0;
4147 if (overrides && !verify_class_overrides (class, overrides, onum))
4150 ifaces = mono_class_get_implemented_interfaces (class, &error);
4151 if (!mono_error_ok (&error)) {
4152 char *name = mono_type_get_full_name (class);
4153 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)));
4155 mono_error_cleanup (&error);
4157 } else if (ifaces) {
4158 for (i = 0; i < ifaces->len; i++) {
4159 MonoClass *ic = g_ptr_array_index (ifaces, i);
4160 max_vtsize += ic->method.count;
4162 g_ptr_array_free (ifaces, TRUE);
4166 if (class->parent) {
4167 mono_class_init (class->parent);
4168 mono_class_setup_vtable_full (class->parent, in_setup);
4170 if (class->parent->exception_type) {
4171 char *name = mono_type_get_full_name (class->parent);
4172 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4177 max_vtsize += class->parent->vtable_size;
4178 cur_slot = class->parent->vtable_size;
4181 max_vtsize += class->method.count;
4183 /*Array have a slot for stelemref*/
4184 if (mono_class_need_stelemref_method (class)) {
4185 stelemref_slot = cur_slot;
4190 vtable = alloca (sizeof (gpointer) * max_vtsize);
4191 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4193 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4195 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4196 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4199 max_iid = class->max_interface_id;
4200 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4202 /* Optimized version for generic instances */
4203 if (class->generic_class) {
4205 MonoClass *gklass = class->generic_class->container_class;
4208 mono_class_setup_vtable_full (gklass, in_setup);
4209 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4210 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4214 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4215 class->vtable_size = gklass->vtable_size;
4216 for (i = 0; i < gklass->vtable_size; ++i)
4217 if (gklass->vtable [i]) {
4218 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4219 if (!mono_error_ok (&error)) {
4220 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4221 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4223 mono_error_cleanup (&error);
4227 tmp [i]->slot = gklass->vtable [i]->slot;
4229 mono_memory_barrier ();
4230 class->vtable = tmp;
4232 /* Have to set method->slot for abstract virtual methods */
4233 if (class->methods && gklass->methods) {
4234 for (i = 0; i < class->method.count; ++i)
4235 if (class->methods [i]->slot == -1)
4236 class->methods [i]->slot = gklass->methods [i]->slot;
4242 if (class->parent && class->parent->vtable_size) {
4243 MonoClass *parent = class->parent;
4246 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4248 // Also inherit parent interface vtables, just as a starting point.
4249 // This is needed otherwise bug-77127.exe fails when the property methods
4250 // have different names in the iterface and the class, because for child
4251 // classes the ".override" information is not used anymore.
4252 for (i = 0; i < parent->interface_offsets_count; i++) {
4253 MonoClass *parent_interface = parent->interfaces_packed [i];
4254 int interface_offset = mono_class_interface_offset (class, parent_interface);
4255 /*FIXME this is now dead code as this condition will never hold true.
4256 Since interface offsets are inherited then the offset of an interface implemented
4257 by a parent will never be the out of it's vtable boundary.
4259 if (interface_offset >= parent->vtable_size) {
4260 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4263 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4264 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4265 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4266 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4267 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4268 parent_interface_offset + j, parent_interface_offset, j,
4269 interface_offset + j, interface_offset, j));
4276 /*Array have a slot for stelemref*/
4277 if (mono_class_need_stelemref_method (class)) {
4278 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4280 method->slot = stelemref_slot;
4282 g_assert (method->slot == stelemref_slot);
4284 vtable [stelemref_slot] = method;
4287 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4288 /* override interface methods */
4289 for (i = 0; i < onum; i++) {
4290 MonoMethod *decl = overrides [i*2];
4291 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4293 dslot = mono_method_get_vtable_slot (decl);
4295 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4299 dslot += mono_class_interface_offset (class, decl->klass);
4300 vtable [dslot] = overrides [i*2 + 1];
4301 vtable [dslot]->slot = dslot;
4303 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4305 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4307 if (mono_security_core_clr_enabled ())
4308 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4311 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4312 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4315 * Create a list of virtual methods to avoid calling
4316 * mono_class_get_virtual_methods () which is slow because of the metadata
4320 gpointer iter = NULL;
4323 virt_methods = NULL;
4324 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4325 virt_methods = g_slist_prepend (virt_methods, cm);
4327 if (class->exception_type)
4331 // Loop on all implemented interfaces...
4332 for (i = 0; i < class->interface_offsets_count; i++) {
4333 MonoClass *parent = class->parent;
4335 gboolean interface_is_explicitly_implemented_by_class;
4338 ic = class->interfaces_packed [i];
4339 ic_offset = mono_class_interface_offset (class, ic);
4341 mono_class_setup_methods (ic);
4342 if (ic->exception_type)
4345 // Check if this interface is explicitly implemented (instead of just inherited)
4346 if (parent != NULL) {
4347 int implemented_interfaces_index;
4348 interface_is_explicitly_implemented_by_class = FALSE;
4349 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4350 if (ic == class->interfaces [implemented_interfaces_index]) {
4351 interface_is_explicitly_implemented_by_class = TRUE;
4356 interface_is_explicitly_implemented_by_class = TRUE;
4359 // Loop on all interface methods...
4360 for (im_index = 0; im_index < ic->method.count; im_index++) {
4361 MonoMethod *im = ic->methods [im_index];
4362 int im_slot = ic_offset + im->slot;
4363 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4365 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4368 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4370 // If there is an explicit implementation, just use it right away,
4371 // otherwise look for a matching method
4372 if (override_im == NULL) {
4377 // First look for a suitable method among the class methods
4379 for (l = virt_methods; l; l = l->next) {
4381 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)));
4382 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4383 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4384 vtable [im_slot] = cm;
4385 /* Why do we need this? */
4390 TRACE_INTERFACE_VTABLE (printf ("\n"));
4391 if (class->exception_type) /*Might be set by check_interface_method_override*/
4395 // If the slot is still empty, look in all the inherited virtual methods...
4396 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4397 MonoClass *parent = class->parent;
4398 // Reverse order, so that last added methods are preferred
4399 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4400 MonoMethod *cm = parent->vtable [cm_index];
4402 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));
4403 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4404 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4405 vtable [im_slot] = cm;
4406 /* Why do we need this? */
4412 if (class->exception_type) /*Might be set by check_interface_method_override*/
4414 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4418 g_assert (vtable [im_slot] == override_im);
4423 // If the class is not abstract, check that all its interface slots are full.
4424 // The check is done here and not directly at the end of the loop above because
4425 // it can happen (for injected generic array interfaces) that the same slot is
4426 // processed multiple times (those interfaces have overlapping slots), and it
4427 // will not always be the first pass the one that fills the slot.
4428 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4429 for (i = 0; i < class->interface_offsets_count; i++) {
4433 ic = class->interfaces_packed [i];
4434 ic_offset = mono_class_interface_offset (class, ic);
4436 for (im_index = 0; im_index < ic->method.count; im_index++) {
4437 MonoMethod *im = ic->methods [im_index];
4438 int im_slot = ic_offset + im->slot;
4440 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4443 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4444 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4445 if (vtable [im_slot] == NULL) {
4446 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4453 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4455 for (l = virt_methods; l; l = l->next) {
4458 * If the method is REUSE_SLOT, we must check in the
4459 * base class for a method to override.
4461 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4463 for (k = class->parent; k ; k = k->parent) {
4468 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4469 MonoMethodSignature *cmsig, *m1sig;
4471 cmsig = mono_method_signature (cm);
4472 m1sig = mono_method_signature (m1);
4474 if (!cmsig || !m1sig) {
4475 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4479 if (!strcmp(cm->name, m1->name) &&
4480 mono_metadata_signature_equal (cmsig, m1sig)) {
4482 /* CAS - SecurityAction.InheritanceDemand */
4483 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4484 mono_secman_inheritancedemand_method (cm, m1);
4487 if (mono_security_core_clr_enabled ())
4488 mono_security_core_clr_check_override (class, cm, m1);
4490 slot = mono_method_get_vtable_slot (m1);
4494 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4495 char *body_name = mono_method_full_name (cm, TRUE);
4496 char *decl_name = mono_method_full_name (m1, TRUE);
4497 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));
4503 g_assert (cm->slot < max_vtsize);
4505 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4506 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4507 mono_method_full_name (m1, 1), m1,
4508 mono_method_full_name (cm, 1), cm));
4509 g_hash_table_insert (override_map, m1, cm);
4513 if (k->exception_type)
4523 /*Non final newslot methods must be given a non-interface vtable slot*/
4524 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4528 cm->slot = cur_slot++;
4530 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4531 vtable [cm->slot] = cm;
4534 /* override non interface methods */
4535 for (i = 0; i < onum; i++) {
4536 MonoMethod *decl = overrides [i*2];
4537 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4538 g_assert (decl->slot != -1);
4539 vtable [decl->slot] = overrides [i*2 + 1];
4540 overrides [i * 2 + 1]->slot = decl->slot;
4542 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4543 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4544 mono_method_full_name (decl, 1), decl,
4545 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4546 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4548 if (mono_security_core_clr_enabled ())
4549 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4554 * If a method occupies more than one place in the vtable, and it is
4555 * overriden, then change the other occurances too.
4560 for (i = 0; i < max_vtsize; ++i)
4562 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4564 cm = g_hash_table_lookup (override_map, vtable [i]);
4569 g_hash_table_destroy (override_map);
4570 override_map = NULL;
4573 g_slist_free (virt_methods);
4574 virt_methods = NULL;
4576 /* Ensure that all vtable slots are filled with concrete instance methods */
4577 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4578 for (i = 0; i < cur_slot; ++i) {
4579 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4580 char *type_name = mono_type_get_full_name (class);
4581 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4582 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));
4584 g_free (method_name);
4590 if (class->generic_class) {
4591 MonoClass *gklass = class->generic_class->container_class;
4593 mono_class_init (gklass);
4595 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4597 /* Check that the vtable_size value computed in mono_class_init () is correct */
4598 if (class->vtable_size)
4599 g_assert (cur_slot == class->vtable_size);
4600 class->vtable_size = cur_slot;
4603 /* Try to share the vtable with our parent. */
4604 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4605 mono_memory_barrier ();
4606 class->vtable = class->parent->vtable;
4608 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4609 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4610 mono_memory_barrier ();
4611 class->vtable = tmp;
4614 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4615 if (mono_print_vtable) {
4618 print_implemented_interfaces (class);
4620 for (i = 0; i <= max_iid; i++)
4621 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4624 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4625 class->vtable_size, icount);
4627 for (i = 0; i < cur_slot; ++i) {
4632 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4633 mono_method_full_name (cm, TRUE));
4639 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4640 class->name, max_iid);
4642 for (i = 0; i < class->interface_count; i++) {
4643 ic = class->interfaces [i];
4644 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4645 mono_class_interface_offset (class, ic),
4646 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4649 for (k = class->parent; k ; k = k->parent) {
4650 for (i = 0; i < k->interface_count; i++) {
4651 ic = k->interfaces [i];
4652 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4653 mono_class_interface_offset (class, ic),
4654 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4660 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4665 char *name = mono_type_get_full_name (class);
4666 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4669 g_hash_table_destroy (override_map);
4671 g_slist_free (virt_methods);
4676 * mono_method_get_vtable_slot:
4678 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4679 * LOCKING: Acquires the loader lock.
4681 * FIXME Use proper MonoError machinery here.
4684 mono_method_get_vtable_slot (MonoMethod *method)
4686 if (method->slot == -1) {
4687 mono_class_setup_vtable (method->klass);
4688 if (method->klass->exception_type)
4690 if (method->slot == -1) {
4694 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4695 g_assert (method->klass->generic_class);
4696 gklass = method->klass->generic_class->container_class;
4697 mono_class_setup_methods (method->klass);
4698 g_assert (method->klass->methods);
4699 for (i = 0; i < method->klass->method.count; ++i) {
4700 if (method->klass->methods [i] == method)
4703 g_assert (i < method->klass->method.count);
4704 g_assert (gklass->methods);
4705 method->slot = gklass->methods [i]->slot;
4707 g_assert (method->slot != -1);
4709 return method->slot;
4713 * mono_method_get_vtable_index:
4716 * Returns the index into the runtime vtable to access the method or,
4717 * in the case of a virtual generic method, the virtual generic method
4718 * thunk. Returns -1 on failure.
4720 * FIXME Use proper MonoError machinery here.
4723 mono_method_get_vtable_index (MonoMethod *method)
4725 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4726 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4727 if (imethod->declaring->is_generic)
4728 return mono_method_get_vtable_slot (imethod->declaring);
4730 return mono_method_get_vtable_slot (method);
4733 static MonoMethod *default_ghc = NULL;
4734 static MonoMethod *default_finalize = NULL;
4735 static int finalize_slot = -1;
4736 static int ghc_slot = -1;
4739 initialize_object_slots (MonoClass *class)
4744 if (class == mono_defaults.object_class) {
4745 mono_class_setup_vtable (class);
4746 for (i = 0; i < class->vtable_size; ++i) {
4747 MonoMethod *cm = class->vtable [i];
4749 if (!strcmp (cm->name, "GetHashCode"))
4751 else if (!strcmp (cm->name, "Finalize"))
4755 g_assert (ghc_slot > 0);
4756 default_ghc = class->vtable [ghc_slot];
4758 g_assert (finalize_slot > 0);
4759 default_finalize = class->vtable [finalize_slot];
4764 MonoMethod *array_method;
4766 } GenericArrayMethodInfo;
4768 static int generic_array_method_num = 0;
4769 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4772 generic_array_methods (MonoClass *class)
4774 int i, count_generic = 0;
4775 GList *list = NULL, *tmp;
4776 if (generic_array_method_num)
4777 return generic_array_method_num;
4778 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4779 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4780 for (i = 0; i < class->parent->method.count; i++) {
4781 MonoMethod *m = class->parent->methods [i];
4782 if (!strncmp (m->name, "InternalArray__", 15)) {
4784 list = g_list_prepend (list, m);
4787 list = g_list_reverse (list);
4788 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4790 for (tmp = list; tmp; tmp = tmp->next) {
4791 const char *mname, *iname;
4793 MonoMethod *m = tmp->data;
4794 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4795 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4797 generic_array_method_info [i].array_method = m;
4798 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4799 iname = "System.Collections.Generic.ICollection`1.";
4800 mname = m->name + 27;
4801 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4802 iname = "System.Collections.Generic.IEnumerable`1.";
4803 mname = m->name + 27;
4804 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4805 iname = "System.Collections.Generic.IReadOnlyList`1.";
4806 mname = m->name + strlen (ireadonlylist_prefix);
4807 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4808 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4809 mname = m->name + strlen (ireadonlycollection_prefix);
4810 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4811 iname = "System.Collections.Generic.IList`1.";
4812 mname = m->name + 15;
4814 g_assert_not_reached ();
4817 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4818 strcpy (name, iname);
4819 strcpy (name + strlen (iname), mname);
4820 generic_array_method_info [i].name = name;
4823 /*g_print ("array generic methods: %d\n", count_generic);*/
4825 generic_array_method_num = count_generic;
4827 return generic_array_method_num;
4831 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4833 MonoGenericContext tmp_context;
4836 tmp_context.class_inst = NULL;
4837 tmp_context.method_inst = iface->generic_class->context.class_inst;
4838 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4840 for (i = 0; i < generic_array_method_num; i++) {
4841 MonoMethod *m = generic_array_method_info [i].array_method;
4842 MonoMethod *inflated;
4844 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4845 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4850 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4852 int null_length = strlen ("(null)");
4853 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4854 char *s = mono_image_alloc (image, len);
4857 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4858 g_assert (result == len - 1);
4864 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4866 gpointer exception_data = NULL;
4868 switch (error->exception_type) {
4869 case MONO_EXCEPTION_TYPE_LOAD:
4870 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4873 case MONO_EXCEPTION_MISSING_METHOD:
4874 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4877 case MONO_EXCEPTION_MISSING_FIELD: {
4878 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4879 const char *class_name;
4882 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4884 class_name = error->klass->name;
4886 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4889 g_free ((void*)class_name);
4893 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4896 if (error->ref_only)
4897 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.";
4899 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4901 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4905 case MONO_EXCEPTION_BAD_IMAGE:
4906 exception_data = error->msg;
4910 g_assert_not_reached ();
4913 mono_class_set_failure (class, error->exception_type, exception_data);
4918 * @class: the class to initialize
4920 * Compute the instance_size, class_size and other infos that cannot be
4921 * computed at mono_class_get() time. Also compute vtable_size if possible.
4922 * Returns TRUE on success or FALSE if there was a problem in loading
4923 * the type (incorrect assemblies, missing assemblies, methods, etc).
4925 * LOCKING: Acquires the loader lock.
4928 mono_class_init (MonoClass *class)
4931 MonoCachedClassInfo cached_info;
4932 gboolean has_cached_info;
4936 /* Double-checking locking pattern */
4937 if (class->inited || class->exception_type)
4938 return class->exception_type == MONO_EXCEPTION_NONE;
4940 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4942 /* We do everything inside the lock to prevent races */
4943 mono_loader_lock ();
4945 if (class->inited || class->exception_type) {
4946 mono_loader_unlock ();
4947 /* Somebody might have gotten in before us */
4948 return class->exception_type == MONO_EXCEPTION_NONE;
4951 if (class->init_pending) {
4952 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4956 class->init_pending = 1;
4958 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4959 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4964 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4965 MonoClass *element_class = class->element_class;
4966 if (!element_class->inited)
4967 mono_class_init (element_class);
4968 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4969 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4974 /* CAS - SecurityAction.InheritanceDemand */
4975 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4976 mono_secman_inheritancedemand_class (class, class->parent);
4979 mono_stats.initialized_class_count++;
4981 if (class->generic_class && !class->generic_class->is_dynamic) {
4982 MonoClass *gklass = class->generic_class->container_class;
4984 mono_stats.generic_class_count++;
4986 class->method = gklass->method;
4987 class->field = gklass->field;
4989 mono_class_init (gklass);
4990 // FIXME: Why is this needed ?
4991 if (!gklass->exception_type)
4992 mono_class_setup_methods (gklass);
4993 if (gklass->exception_type) {
4994 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4998 if (MONO_CLASS_IS_INTERFACE (class))
4999 class->interface_id = mono_get_unique_iid (class);
5002 if (class->parent && !class->parent->inited)
5003 mono_class_init (class->parent);
5005 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5007 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5008 class->nested_classes_inited = TRUE;
5011 * Computes the size used by the fields, and their locations
5013 if (has_cached_info) {
5014 class->instance_size = cached_info.instance_size;
5015 class->sizes.class_size = cached_info.class_size;
5016 class->packing_size = cached_info.packing_size;
5017 class->min_align = cached_info.min_align;
5018 class->blittable = cached_info.blittable;
5019 class->has_references = cached_info.has_references;
5020 class->has_static_refs = cached_info.has_static_refs;
5021 class->no_special_static_fields = cached_info.no_special_static_fields;
5024 if (!class->size_inited){
5025 mono_class_setup_fields (class);
5026 if (class->exception_type || mono_loader_get_last_error ())
5030 /* Initialize arrays */
5032 class->method.count = 3 + (class->rank > 1? 2: 1);
5034 if (class->interface_count) {
5035 int count_generic = generic_array_methods (class);
5036 class->method.count += class->interface_count * count_generic;
5040 mono_class_setup_supertypes (class);
5043 initialize_object_slots (class);
5046 * Initialize the rest of the data without creating a generic vtable if possible.
5047 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5048 * also avoid computing a generic vtable.
5050 if (has_cached_info) {
5052 class->vtable_size = cached_info.vtable_size;
5053 class->has_finalize = cached_info.has_finalize;
5054 class->has_finalize_inited = TRUE;
5055 class->ghcimpl = cached_info.ghcimpl;
5056 class->has_cctor = cached_info.has_cctor;
5057 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5058 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5059 * The first slot if for array with.
5061 static int szarray_vtable_size[2] = { 0 };
5063 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5066 if (!szarray_vtable_size [slot]) {
5067 mono_class_setup_vtable (class);
5068 szarray_vtable_size [slot] = class->vtable_size;
5070 class->vtable_size = szarray_vtable_size[slot];
5072 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5073 MonoClass *gklass = class->generic_class->container_class;
5075 /* Generic instance case */
5076 class->ghcimpl = gklass->ghcimpl;
5077 class->has_cctor = gklass->has_cctor;
5079 mono_class_setup_vtable (gklass);
5080 if (gklass->exception_type) {
5081 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5085 class->vtable_size = gklass->vtable_size;
5089 /* ghcimpl is not currently used
5091 if (class->parent) {
5092 MonoMethod *cmethod = class->vtable [ghc_slot];
5093 if (cmethod->is_inflated)
5094 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5095 if (cmethod == default_ghc) {
5101 /* C# doesn't allow interfaces to have cctors */
5102 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5103 MonoMethod *cmethod = NULL;
5105 if (class->type_token) {
5106 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5107 /* The find_method function ignores the 'flags' argument */
5108 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5109 class->has_cctor = 1;
5111 mono_class_setup_methods (class);
5112 if (class->exception_type)
5115 for (i = 0; i < class->method.count; ++i) {
5116 MonoMethod *method = class->methods [i];
5117 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5118 (strcmp (".cctor", method->name) == 0)) {
5119 class->has_cctor = 1;
5127 if (class->parent) {
5128 int first_iface_slot;
5129 /* This will compute class->parent->vtable_size for some classes */
5130 mono_class_init (class->parent);
5131 if (class->parent->exception_type) {
5132 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5135 if (mono_loader_get_last_error ())
5137 if (!class->parent->vtable_size) {
5138 /* FIXME: Get rid of this somehow */
5139 mono_class_setup_vtable (class->parent);
5140 if (class->parent->exception_type) {
5141 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5144 if (mono_loader_get_last_error ())
5147 first_iface_slot = class->parent->vtable_size;
5148 if (mono_class_need_stelemref_method (class))
5150 setup_interface_offsets (class, first_iface_slot, TRUE);
5152 setup_interface_offsets (class, 0, TRUE);
5155 if (mono_security_core_clr_enabled ())
5156 mono_security_core_clr_check_inheritance (class);
5158 if (mono_loader_get_last_error ()) {
5159 if (class->exception_type == MONO_EXCEPTION_NONE) {
5160 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5162 mono_loader_clear_error ();
5165 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5166 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5171 /* Because of the double-checking locking pattern */
5172 mono_memory_barrier ();
5174 class->init_pending = 0;
5176 mono_loader_unlock ();
5178 if (mono_debugger_class_init_func)
5179 mono_debugger_class_init_func (class);
5181 return class->exception_type == MONO_EXCEPTION_NONE;
5185 * mono_class_has_finalizer:
5187 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5191 mono_class_has_finalizer (MonoClass *klass)
5193 MonoClass *class = klass;
5194 gboolean has_finalize = FALSE;
5196 if (klass->has_finalize_inited)
5197 return klass->has_finalize;
5199 /* Interfaces and valuetypes are not supposed to have finalizers */
5200 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5201 MonoMethod *cmethod = NULL;
5203 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5204 } else if (class->generic_class) {
5205 MonoClass *gklass = class->generic_class->container_class;
5207 has_finalize = mono_class_has_finalizer (gklass);
5208 } else if (class->parent && class->parent->has_finalize) {
5209 has_finalize = TRUE;
5211 if (class->parent) {
5213 * Can't search in metadata for a method named Finalize, because that
5214 * ignores overrides.
5216 mono_class_setup_vtable (class);
5217 if (class->exception_type || mono_loader_get_last_error ())
5220 cmethod = class->vtable [finalize_slot];
5224 g_assert (class->vtable_size > finalize_slot);
5226 if (class->parent) {
5227 if (cmethod->is_inflated)
5228 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5229 if (cmethod != default_finalize)
5230 has_finalize = TRUE;
5236 mono_loader_lock ();
5238 if (!klass->has_finalize_inited) {
5239 klass->has_finalize = has_finalize ? 1 : 0;
5241 mono_memory_barrier ();
5242 klass->has_finalize_inited = TRUE;
5245 mono_loader_unlock ();
5247 return klass->has_finalize;
5251 mono_is_corlib_image (MonoImage *image)
5253 /* FIXME: allow the dynamic case for our compilers and with full trust */
5254 if (image_is_dynamic (image))
5255 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5257 return image == mono_defaults.corlib;
5261 * LOCKING: this assumes the loader lock is held
5264 mono_class_setup_mono_type (MonoClass *class)
5266 const char *name = class->name;
5267 const char *nspace = class->name_space;
5268 gboolean is_corlib = mono_is_corlib_image (class->image);
5270 class->this_arg.byref = 1;
5271 class->this_arg.data.klass = class;
5272 class->this_arg.type = MONO_TYPE_CLASS;
5273 class->byval_arg.data.klass = class;
5274 class->byval_arg.type = MONO_TYPE_CLASS;
5276 if (is_corlib && !strcmp (nspace, "System")) {
5277 if (!strcmp (name, "ValueType")) {
5279 * do not set the valuetype bit for System.ValueType.
5280 * class->valuetype = 1;
5282 class->blittable = TRUE;
5283 } else if (!strcmp (name, "Enum")) {
5285 * do not set the valuetype bit for System.Enum.
5286 * class->valuetype = 1;
5288 class->valuetype = 0;
5289 class->enumtype = 0;
5290 } else if (!strcmp (name, "Object")) {
5291 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5292 } else if (!strcmp (name, "String")) {
5293 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5294 } else if (!strcmp (name, "TypedReference")) {
5295 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5299 if (class->valuetype) {
5300 int t = MONO_TYPE_VALUETYPE;
5302 if (is_corlib && !strcmp (nspace, "System")) {
5305 if (!strcmp (name, "Boolean")) {
5306 t = MONO_TYPE_BOOLEAN;
5307 } else if (!strcmp(name, "Byte")) {
5309 class->blittable = TRUE;
5313 if (!strcmp (name, "Char")) {
5318 if (!strcmp (name, "Double")) {
5320 class->blittable = TRUE;
5324 if (!strcmp (name, "Int32")) {
5326 class->blittable = TRUE;
5327 } else if (!strcmp(name, "Int16")) {
5329 class->blittable = TRUE;
5330 } else if (!strcmp(name, "Int64")) {
5332 class->blittable = TRUE;
5333 } else if (!strcmp(name, "IntPtr")) {
5335 class->blittable = TRUE;
5339 if (!strcmp (name, "Single")) {
5341 class->blittable = TRUE;
5342 } else if (!strcmp(name, "SByte")) {
5344 class->blittable = TRUE;
5348 if (!strcmp (name, "UInt32")) {
5350 class->blittable = TRUE;
5351 } else if (!strcmp(name, "UInt16")) {
5353 class->blittable = TRUE;
5354 } else if (!strcmp(name, "UInt64")) {
5356 class->blittable = TRUE;
5357 } else if (!strcmp(name, "UIntPtr")) {
5359 class->blittable = TRUE;
5363 if (!strcmp (name, "TypedReference")) {
5364 t = MONO_TYPE_TYPEDBYREF;
5365 class->blittable = TRUE;
5369 if (!strcmp (name, "Void")) {
5377 class->this_arg.type = class->byval_arg.type = t;
5380 if (MONO_CLASS_IS_INTERFACE (class))
5381 class->interface_id = mono_get_unique_iid (class);
5387 * COM initialization is delayed until needed.
5388 * However when a [ComImport] attribute is present on a type it will trigger
5389 * the initialization. This is not a problem unless the BCL being executed
5390 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5393 init_com_from_comimport (MonoClass *class)
5395 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5396 if (mono_security_core_clr_enabled ()) {
5397 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5398 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5399 /* but it can not be made available for application (i.e. user code) since all COM calls
5400 * are considered native calls. In this case we fail with a TypeLoadException (just like
5401 * Silverlight 2 does */
5402 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5407 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5409 #endif /*DISABLE_COM*/
5412 * LOCKING: this assumes the loader lock is held
5415 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5417 gboolean system_namespace;
5418 gboolean is_corlib = mono_is_corlib_image (class->image);
5420 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5422 /* if root of the hierarchy */
5423 if (system_namespace && !strcmp (class->name, "Object")) {
5424 class->parent = NULL;
5425 class->instance_size = sizeof (MonoObject);
5428 if (!strcmp (class->name, "<Module>")) {
5429 class->parent = NULL;
5430 class->instance_size = 0;
5434 if (!MONO_CLASS_IS_INTERFACE (class)) {
5435 /* Imported COM Objects always derive from __ComObject. */
5437 if (MONO_CLASS_IS_IMPORT (class)) {
5438 init_com_from_comimport (class);
5439 if (parent == mono_defaults.object_class)
5440 parent = mono_class_get_com_object_class ();
5444 /* set the parent to something useful and safe, but mark the type as broken */
5445 parent = mono_defaults.object_class;
5446 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5449 class->parent = parent;
5451 if (parent->generic_class && !parent->name) {
5453 * If the parent is a generic instance, we may get
5454 * called before it is fully initialized, especially
5455 * before it has its name.
5460 #ifndef DISABLE_REMOTING
5461 class->marshalbyref = parent->marshalbyref;
5462 class->contextbound = parent->contextbound;
5465 class->delegate = parent->delegate;
5467 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5468 mono_class_set_is_com_object (class);
5470 if (system_namespace) {
5471 #ifndef DISABLE_REMOTING
5472 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5473 class->marshalbyref = 1;
5475 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5476 class->contextbound = 1;
5478 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5479 class->delegate = 1;
5482 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5483 (strcmp (class->parent->name_space, "System") == 0)))
5484 class->valuetype = 1;
5485 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5486 class->valuetype = class->enumtype = 1;
5488 /*class->enumtype = class->parent->enumtype; */
5490 /* initialize com types if COM interfaces are present */
5492 if (MONO_CLASS_IS_IMPORT (class))
5493 init_com_from_comimport (class);
5495 class->parent = NULL;
5501 * mono_class_setup_supertypes:
5504 * Build the data structure needed to make fast type checks work.
5505 * This currently sets two fields in @class:
5506 * - idepth: distance between @class and System.Object in the type
5508 * - supertypes: array of classes: each element has a class in the hierarchy
5509 * starting from @class up to System.Object
5511 * LOCKING: This function is atomic, in case of contention we waste memory.
5514 mono_class_setup_supertypes (MonoClass *class)
5517 MonoClass **supertypes;
5519 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5523 if (class->parent && !class->parent->supertypes)
5524 mono_class_setup_supertypes (class->parent);
5526 class->idepth = class->parent->idepth + 1;
5530 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5531 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5533 if (class->parent) {
5534 supertypes [class->idepth - 1] = class;
5535 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5537 supertypes [0] = class;
5540 mono_atomic_store_release (&class->supertypes, supertypes);
5544 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5546 MonoClass *gtd = (MonoClass*)user_data;
5547 /* Only try to fix generic instances of @gtd */
5548 if (gclass->generic_class->container_class != gtd)
5551 /* Check if the generic instance has no parent. */
5552 if (gtd->parent && !gclass->parent)
5553 mono_generic_class_setup_parent (gclass, gtd);
5559 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5561 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5562 mono_error_set_type_load_class (error, class, msg);
5566 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5568 MonoLoaderError *lerror = mono_loader_get_last_error ();
5571 set_failure_from_loader_error (class, lerror);
5572 mono_error_set_from_loader_error (error);
5576 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5577 mono_error_set_type_load_class (error, class, msg);
5582 * mono_class_create_from_typedef:
5583 * @image: image where the token is valid
5584 * @type_token: typedef token
5585 * @error: used to return any error found while creating the type
5587 * Create the MonoClass* representing the specified type token.
5588 * @type_token must be a TypeDef token.
5590 * FIXME: don't return NULL on failure, just the the caller figure it out.
5593 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5595 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5596 MonoClass *class, *parent = NULL;
5597 guint32 cols [MONO_TYPEDEF_SIZE];
5598 guint32 cols_next [MONO_TYPEDEF_SIZE];
5599 guint tidx = mono_metadata_token_index (type_token);
5600 MonoGenericContext *context = NULL;
5601 const char *name, *nspace;
5603 MonoClass **interfaces;
5604 guint32 field_last, method_last;
5605 guint32 nesting_tokeen;
5607 mono_error_init (error);
5609 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5610 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5611 g_assert (!mono_loader_get_last_error ());
5615 mono_loader_lock ();
5617 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5618 mono_loader_unlock ();
5619 g_assert (!mono_loader_get_last_error ());
5623 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5625 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5626 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5628 class = mono_image_alloc0 (image, sizeof (MonoClass));
5631 class->name_space = nspace;
5633 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5635 class->image = image;
5636 class->type_token = type_token;
5637 class->flags = cols [MONO_TYPEDEF_FLAGS];
5639 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5641 classes_size += sizeof (MonoClass);
5644 * Check whether we're a generic type definition.
5646 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5647 if (class->generic_container) {
5648 class->is_generic = 1;
5649 class->generic_container->owner.klass = class;
5650 context = &class->generic_container->context;
5653 if (class->generic_container)
5654 enable_gclass_recording ();
5656 if (cols [MONO_TYPEDEF_EXTENDS]) {
5658 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5660 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5661 /*WARNING: this must satisfy mono_metadata_type_hash*/
5662 class->this_arg.byref = 1;
5663 class->this_arg.data.klass = class;
5664 class->this_arg.type = MONO_TYPE_CLASS;
5665 class->byval_arg.data.klass = class;
5666 class->byval_arg.type = MONO_TYPE_CLASS;
5668 parent = mono_class_get_full (image, parent_token, context);
5670 if (parent == NULL) {
5671 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5672 goto parent_failure;
5675 for (tmp = parent; tmp; tmp = tmp->parent) {
5677 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5678 goto parent_failure;
5680 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5681 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5682 goto parent_failure;
5687 mono_class_setup_parent (class, parent);
5689 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5690 mono_class_setup_mono_type (class);
5692 if (class->generic_container)
5693 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5696 * This might access class->byval_arg for recursion generated by generic constraints,
5697 * so it has to come after setup_mono_type ().
5699 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5700 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5701 if (!mono_error_ok (error)) {
5702 /*FIXME implement a mono_class_set_failure_from_mono_error */
5703 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5704 mono_loader_unlock ();
5705 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5706 g_assert (!mono_loader_get_last_error ());
5711 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5715 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5719 class->cast_class = class->element_class = class;
5721 if (!class->enumtype) {
5722 if (!mono_metadata_interfaces_from_typedef_full (
5723 image, type_token, &interfaces, &icount, FALSE, context)){
5724 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5725 mono_loader_unlock ();
5726 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5730 class->interfaces = interfaces;
5731 class->interface_count = icount;
5732 class->interfaces_inited = 1;
5735 /*g_print ("Load class %s\n", name);*/
5738 * Compute the field and method lists
5740 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5741 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5743 if (tt->rows > tidx){
5744 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5745 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5746 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5748 field_last = image->tables [MONO_TABLE_FIELD].rows;
5749 method_last = image->tables [MONO_TABLE_METHOD].rows;
5752 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5753 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5754 class->field.count = field_last - class->field.first;
5756 class->field.count = 0;
5758 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5759 class->method.count = method_last - class->method.first;
5761 class->method.count = 0;
5763 /* reserve space to store vector pointer in arrays */
5764 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5765 class->instance_size += 2 * sizeof (gpointer);
5766 g_assert (class->field.count == 0);
5769 if (class->enumtype) {
5770 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5771 if (!enum_basetype) {
5772 /*set it to a default value as the whole runtime can't handle this to be null*/
5773 class->cast_class = class->element_class = mono_defaults.int32_class;
5774 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5775 mono_loader_unlock ();
5776 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5777 g_assert (!mono_loader_get_last_error ());
5780 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5784 * If we're a generic type definition, load the constraints.
5785 * We must do this after the class has been constructed to make certain recursive scenarios
5788 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5789 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5790 mono_loader_unlock ();
5791 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5792 g_assert (!mono_loader_get_last_error ());
5796 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5797 if (!strncmp (name, "Vector", 6))
5798 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");
5801 mono_loader_unlock ();
5803 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5804 g_assert (!mono_loader_get_last_error ());
5809 mono_class_setup_mono_type (class);
5810 mono_loader_unlock ();
5811 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5812 g_assert (!mono_loader_get_last_error ());
5816 /** is klass Nullable<T>? */
5818 mono_class_is_nullable (MonoClass *klass)
5820 return klass->generic_class != NULL &&
5821 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5825 /** if klass is T? return T */
5827 mono_class_get_nullable_param (MonoClass *klass)
5829 g_assert (mono_class_is_nullable (klass));
5830 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5834 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5838 MonoGenericClass *gclass = klass->generic_class;
5840 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5841 if (!mono_error_ok (&error)) {
5842 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5843 klass->parent = mono_defaults.object_class;
5844 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5845 mono_error_cleanup (&error);
5849 mono_class_setup_parent (klass, klass->parent);
5851 if (klass->enumtype) {
5852 klass->cast_class = gtd->cast_class;
5853 klass->element_class = gtd->element_class;
5859 * Create the `MonoClass' for an instantiation of a generic type.
5860 * We only do this if we actually need it.
5863 mono_generic_class_get_class (MonoGenericClass *gclass)
5865 MonoClass *klass, *gklass;
5867 if (gclass->cached_class)
5868 return gclass->cached_class;
5870 mono_loader_lock ();
5871 if (gclass->cached_class) {
5872 mono_loader_unlock ();
5873 return gclass->cached_class;
5876 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5878 gklass = gclass->container_class;
5880 if (record_gclass_instantiation > 0)
5881 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5883 if (gklass->nested_in) {
5884 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5885 klass->nested_in = gklass->nested_in;
5888 klass->name = gklass->name;
5889 klass->name_space = gklass->name_space;
5891 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5893 klass->image = gklass->image;
5894 klass->flags = gklass->flags;
5895 klass->type_token = gklass->type_token;
5896 klass->field.count = gklass->field.count;
5898 klass->is_inflated = 1;
5899 klass->generic_class = gclass;
5901 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5902 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5903 klass->this_arg.byref = TRUE;
5904 klass->enumtype = gklass->enumtype;
5905 klass->valuetype = gklass->valuetype;
5907 klass->cast_class = klass->element_class = klass;
5909 if (mono_class_is_nullable (klass))
5910 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5913 * We're not interested in the nested classes of a generic instance.
5914 * We use the generic type definition to look for nested classes.
5917 mono_generic_class_setup_parent (klass, gklass);
5919 if (gclass->is_dynamic) {
5922 mono_class_setup_supertypes (klass);
5924 if (klass->enumtype) {
5926 * For enums, gklass->fields might not been set, but instance_size etc. is
5927 * already set in mono_reflection_create_internal_class (). For non-enums,
5928 * these will be computed normally in mono_class_layout_fields ().
5930 klass->instance_size = gklass->instance_size;
5931 klass->sizes.class_size = gklass->sizes.class_size;
5932 mono_memory_barrier ();
5933 klass->size_inited = 1;
5937 mono_memory_barrier ();
5938 gclass->cached_class = klass;
5940 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5942 inflated_classes ++;
5943 inflated_classes_size += sizeof (MonoClass);
5945 mono_loader_unlock ();
5951 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5953 MonoClass *klass, **ptr;
5955 MonoGenericContainer *container = mono_generic_param_owner (param);
5959 image = mono_defaults.corlib;
5961 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5962 classes_size += sizeof (MonoClass);
5965 klass->name = pinfo->name;
5967 int n = mono_generic_param_num (param);
5968 klass->name = mono_image_alloc0 (image, 16);
5969 sprintf ((char*)klass->name, "%d", n);
5974 MonoMethod *omethod = container->owner.method;
5975 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5977 MonoClass *oklass = container->owner.klass;
5978 klass->name_space = oklass ? oklass->name_space : "";
5981 klass->name_space = "";
5984 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5988 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5992 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5993 klass->parent = pinfo->constraints [0];
5995 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5996 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5998 klass->parent = mono_defaults.object_class;
6001 if (count - pos > 0) {
6002 klass->interface_count = count - pos;
6003 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6004 klass->interfaces_inited = TRUE;
6005 for (i = pos; i < count; i++)
6006 klass->interfaces [i - pos] = pinfo->constraints [i];
6009 klass->image = image;
6011 klass->inited = TRUE;
6012 klass->cast_class = klass->element_class = klass;
6013 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6015 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6016 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6017 klass->this_arg.byref = TRUE;
6019 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6020 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6022 /*Init these fields to sane values*/
6023 klass->min_align = 1;
6024 klass->instance_size = sizeof (gpointer);
6025 mono_memory_barrier ();
6026 klass->size_inited = 1;
6028 mono_class_setup_supertypes (klass);
6030 if (count - pos > 0) {
6031 mono_class_setup_vtable (klass->parent);
6032 if (klass->parent->exception_type)
6033 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6035 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6041 #define FAST_CACHE_SIZE 16
6044 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6046 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6047 MonoImage *image = param->image;
6052 if (n < FAST_CACHE_SIZE) {
6054 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6056 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6058 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6059 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6064 * LOCKING: Acquires the loader lock.
6067 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6069 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6070 MonoImage *image = param->image;
6075 if (n < FAST_CACHE_SIZE) {
6077 /* No locking needed */
6078 if (!image->mvar_cache_fast)
6079 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6080 image->mvar_cache_fast [n] = klass;
6082 if (!image->var_cache_fast)
6083 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6084 image->var_cache_fast [n] = klass;
6088 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6090 mono_loader_lock ();
6091 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6093 ht = g_hash_table_new (NULL, NULL);
6094 mono_memory_barrier ();
6096 image->mvar_cache_slow = ht;
6098 image->var_cache_slow = ht;
6100 mono_loader_unlock ();
6103 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6107 * LOCKING: Acquires the loader lock.
6110 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6112 MonoGenericContainer *container = mono_generic_param_owner (param);
6113 MonoGenericParamInfo *pinfo;
6116 mono_loader_lock ();
6119 pinfo = mono_generic_param_info (param);
6120 if (pinfo->pklass) {
6121 mono_loader_unlock ();
6122 return pinfo->pklass;
6128 klass = get_anon_gparam_class (param, is_mvar);
6130 mono_loader_unlock ();
6135 if (!image && container) {
6137 MonoMethod *method = container->owner.method;
6138 image = (method && method->klass) ? method->klass->image : NULL;
6140 MonoClass *klass = container->owner.klass;
6141 // FIXME: 'klass' should not be null
6142 // But, monodis creates GenericContainers without associating a owner to it
6143 image = klass ? klass->image : NULL;
6147 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6149 mono_memory_barrier ();
6152 pinfo->pklass = klass;
6154 set_anon_gparam_class (param, is_mvar, klass);
6156 mono_loader_unlock ();
6158 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6159 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6165 mono_ptr_class_get (MonoType *type)
6168 MonoClass *el_class;
6172 el_class = mono_class_from_mono_type (type);
6173 image = el_class->image;
6175 mono_loader_lock ();
6177 if (!image->ptr_cache)
6178 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6180 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6181 mono_loader_unlock ();
6184 result = mono_image_alloc0 (image, sizeof (MonoClass));
6186 classes_size += sizeof (MonoClass);
6188 result->parent = NULL; /* no parent for PTR types */
6189 result->name_space = el_class->name_space;
6190 name = g_strdup_printf ("%s*", el_class->name);
6191 result->name = mono_image_strdup (image, name);
6194 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6196 result->image = el_class->image;
6197 result->inited = TRUE;
6198 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6199 /* Can pointers get boxed? */
6200 result->instance_size = sizeof (gpointer);
6201 result->cast_class = result->element_class = el_class;
6202 result->blittable = TRUE;
6204 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6205 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6206 result->this_arg.byref = TRUE;
6208 mono_class_setup_supertypes (result);
6210 g_hash_table_insert (image->ptr_cache, el_class, result);
6212 mono_loader_unlock ();
6214 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6220 mono_fnptr_class_get (MonoMethodSignature *sig)
6223 static GHashTable *ptr_hash = NULL;
6225 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6227 mono_loader_lock ();
6230 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6232 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6233 mono_loader_unlock ();
6236 result = g_new0 (MonoClass, 1);
6238 result->parent = NULL; /* no parent for PTR types */
6239 result->name_space = "System";
6240 result->name = "MonoFNPtrFakeClass";
6242 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6244 result->image = mono_defaults.corlib; /* need to fix... */
6245 result->inited = TRUE;
6246 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6247 /* Can pointers get boxed? */
6248 result->instance_size = sizeof (gpointer);
6249 result->cast_class = result->element_class = result;
6250 result->blittable = TRUE;
6252 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6253 result->this_arg.data.method = result->byval_arg.data.method = sig;
6254 result->this_arg.byref = TRUE;
6255 result->blittable = TRUE;
6257 mono_class_setup_supertypes (result);
6259 g_hash_table_insert (ptr_hash, sig, result);
6261 mono_loader_unlock ();
6263 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6269 mono_class_from_mono_type (MonoType *type)
6271 switch (type->type) {
6272 case MONO_TYPE_OBJECT:
6273 return type->data.klass? type->data.klass: mono_defaults.object_class;
6274 case MONO_TYPE_VOID:
6275 return type->data.klass? type->data.klass: mono_defaults.void_class;
6276 case MONO_TYPE_BOOLEAN:
6277 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6278 case MONO_TYPE_CHAR:
6279 return type->data.klass? type->data.klass: mono_defaults.char_class;
6281 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6283 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6285 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6287 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6289 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6291 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6293 return type->data.klass? type->data.klass: mono_defaults.int_class;
6295 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6297 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6299 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6301 return type->data.klass? type->data.klass: mono_defaults.single_class;
6303 return type->data.klass? type->data.klass: mono_defaults.double_class;
6304 case MONO_TYPE_STRING:
6305 return type->data.klass? type->data.klass: mono_defaults.string_class;
6306 case MONO_TYPE_TYPEDBYREF:
6307 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6308 case MONO_TYPE_ARRAY:
6309 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6311 return mono_ptr_class_get (type->data.type);
6312 case MONO_TYPE_FNPTR:
6313 return mono_fnptr_class_get (type->data.method);
6314 case MONO_TYPE_SZARRAY:
6315 return mono_array_class_get (type->data.klass, 1);
6316 case MONO_TYPE_CLASS:
6317 case MONO_TYPE_VALUETYPE:
6318 return type->data.klass;
6319 case MONO_TYPE_GENERICINST:
6320 return mono_generic_class_get_class (type->data.generic_class);
6322 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6323 case MONO_TYPE_MVAR:
6324 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6326 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6327 g_assert_not_reached ();
6334 * mono_type_retrieve_from_typespec
6335 * @image: context where the image is created
6336 * @type_spec: typespec token
6337 * @context: the generic context used to evaluate generic instantiations in
6340 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6342 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6344 mono_error_init (error);
6345 *did_inflate = FALSE;
6348 char *name = mono_class_name_from_token (image, type_spec);
6349 char *assembly = mono_assembly_name_from_token (image, type_spec);
6350 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6354 if (context && (context->class_inst || context->method_inst)) {
6355 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6357 if (!mono_error_ok (error))
6362 *did_inflate = TRUE;
6369 * mono_class_create_from_typespec
6370 * @image: context where the image is created
6371 * @type_spec: typespec token
6372 * @context: the generic context used to evaluate generic instantiations in
6375 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6378 gboolean inflated = FALSE;
6379 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6380 if (!mono_error_ok (error))
6382 ret = mono_class_from_mono_type (t);
6384 mono_metadata_free_type (t);
6389 * mono_bounded_array_class_get:
6390 * @element_class: element class
6391 * @rank: the dimension of the array class
6392 * @bounded: whenever the array has non-zero bounds
6394 * Returns: a class object describing the array with element type @element_type and
6398 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6402 MonoClass *parent = NULL;
6403 GSList *list, *rootlist = NULL;
6406 gboolean corlib_type = FALSE;
6408 g_assert (rank <= 255);
6411 /* bounded only matters for one-dimensional arrays */
6414 image = eclass->image;
6416 if (rank == 1 && !bounded) {
6418 * This case is very frequent not just during compilation because of calls
6419 * from mono_class_from_mono_type (), mono_array_new (),
6420 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6422 mono_mutex_lock (&image->szarray_cache_lock);
6423 if (!image->szarray_cache)
6424 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6425 class = g_hash_table_lookup (image->szarray_cache, eclass);
6426 mono_mutex_unlock (&image->szarray_cache_lock);
6430 mono_loader_lock ();
6432 mono_loader_lock ();
6434 if (!image->array_cache)
6435 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6437 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6438 for (; list; list = list->next) {
6440 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6441 mono_loader_unlock ();
6448 /* for the building corlib use System.Array from it */
6449 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6450 parent = mono_class_from_name (image, "System", "Array");
6453 parent = mono_defaults.array_class;
6454 if (!parent->inited)
6455 mono_class_init (parent);
6458 class = mono_image_alloc0 (image, sizeof (MonoClass));
6460 class->image = image;
6461 class->name_space = eclass->name_space;
6462 nsize = strlen (eclass->name);
6463 name = g_malloc (nsize + 2 + rank + 1);
6464 memcpy (name, eclass->name, nsize);
6467 memset (name + nsize + 1, ',', rank - 1);
6469 name [nsize + rank] = '*';
6470 name [nsize + rank + bounded] = ']';
6471 name [nsize + rank + bounded + 1] = 0;
6472 class->name = mono_image_strdup (image, name);
6475 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6477 classes_size += sizeof (MonoClass);
6479 class->type_token = 0;
6480 /* all arrays are marked serializable and sealed, bug #42779 */
6481 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6482 class->parent = parent;
6483 class->instance_size = mono_class_instance_size (class->parent);
6485 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6486 /*Arrays of those two types are invalid.*/
6487 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6488 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6489 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6490 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6491 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6493 /* element_size -1 is ok as this is not an instantitable type*/
6494 class->sizes.element_size = -1;
6496 class->sizes.element_size = mono_class_array_element_size (eclass);
6498 mono_class_setup_supertypes (class);
6500 if (eclass->generic_class)
6501 mono_class_init (eclass);
6502 if (!eclass->size_inited)
6503 mono_class_setup_fields (eclass);
6504 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6505 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6507 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6511 if (eclass->enumtype)
6512 class->cast_class = eclass->element_class;
6514 class->cast_class = eclass;
6516 switch (class->cast_class->byval_arg.type) {
6518 class->cast_class = mono_defaults.byte_class;
6521 class->cast_class = mono_defaults.int16_class;
6524 #if SIZEOF_VOID_P == 4
6528 class->cast_class = mono_defaults.int32_class;
6531 #if SIZEOF_VOID_P == 8
6535 class->cast_class = mono_defaults.int64_class;
6539 class->element_class = eclass;
6541 if ((rank > 1) || bounded) {
6542 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6543 class->byval_arg.type = MONO_TYPE_ARRAY;
6544 class->byval_arg.data.array = at;
6545 at->eklass = eclass;
6547 /* FIXME: complete.... */
6549 class->byval_arg.type = MONO_TYPE_SZARRAY;
6550 class->byval_arg.data.klass = eclass;
6552 class->this_arg = class->byval_arg;
6553 class->this_arg.byref = 1;
6558 class->generic_container = eclass->generic_container;
6560 if (rank == 1 && !bounded) {
6561 MonoClass *prev_class;
6563 mono_mutex_lock (&image->szarray_cache_lock);
6564 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6566 /* Someone got in before us */
6569 g_hash_table_insert (image->szarray_cache, eclass, class);
6570 mono_mutex_unlock (&image->szarray_cache_lock);
6572 list = g_slist_append (rootlist, class);
6573 g_hash_table_insert (image->array_cache, eclass, list);
6576 mono_loader_unlock ();
6578 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6584 * mono_array_class_get:
6585 * @element_class: element class
6586 * @rank: the dimension of the array class
6588 * Returns: a class object describing the array with element type @element_type and
6592 mono_array_class_get (MonoClass *eclass, guint32 rank)
6594 return mono_bounded_array_class_get (eclass, rank, FALSE);
6598 * mono_class_instance_size:
6601 * Returns: the size of an object instance
6604 mono_class_instance_size (MonoClass *klass)
6606 if (!klass->size_inited)
6607 mono_class_init (klass);
6609 return klass->instance_size;
6613 * mono_class_min_align:
6616 * Returns: minimm alignment requirements
6619 mono_class_min_align (MonoClass *klass)
6621 if (!klass->size_inited)
6622 mono_class_init (klass);
6624 return klass->min_align;
6628 * mono_class_value_size:
6631 * This function is used for value types, and return the
6632 * space and the alignment to store that kind of value object.
6634 * Returns: the size of a value of kind @klass
6637 mono_class_value_size (MonoClass *klass, guint32 *align)
6641 /* fixme: check disable, because we still have external revereces to
6642 * mscorlib and Dummy Objects
6644 /*g_assert (klass->valuetype);*/
6646 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6649 *align = klass->min_align;
6655 * mono_class_data_size:
6658 * Returns: the size of the static class data
6661 mono_class_data_size (MonoClass *klass)
6664 mono_class_init (klass);
6665 /* This can happen with dynamically created types */
6666 if (!klass->fields_inited)
6667 mono_class_setup_fields_locking (klass);
6669 /* in arrays, sizes.class_size is unioned with element_size
6670 * and arrays have no static fields
6674 return klass->sizes.class_size;
6678 * Auxiliary routine to mono_class_get_field
6680 * Takes a field index instead of a field token.
6682 static MonoClassField *
6683 mono_class_get_field_idx (MonoClass *class, int idx)
6685 mono_class_setup_fields_locking (class);
6686 if (class->exception_type)
6690 if (class->image->uncompressed_metadata) {
6692 * class->field.first points to the FieldPtr table, while idx points into the
6693 * Field table, so we have to do a search.
6695 /*FIXME this is broken for types with multiple fields with the same name.*/
6696 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6699 for (i = 0; i < class->field.count; ++i)
6700 if (mono_field_get_name (&class->fields [i]) == name)
6701 return &class->fields [i];
6702 g_assert_not_reached ();
6704 if (class->field.count) {
6705 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6706 return &class->fields [idx - class->field.first];
6710 class = class->parent;
6716 * mono_class_get_field:
6717 * @class: the class to lookup the field.
6718 * @field_token: the field token
6720 * Returns: A MonoClassField representing the type and offset of
6721 * the field, or a NULL value if the field does not belong to this
6725 mono_class_get_field (MonoClass *class, guint32 field_token)
6727 int idx = mono_metadata_token_index (field_token);
6729 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6731 return mono_class_get_field_idx (class, idx - 1);
6735 * mono_class_get_field_from_name:
6736 * @klass: the class to lookup the field.
6737 * @name: the field name
6739 * Search the class @klass and it's parents for a field with the name @name.
6741 * Returns: the MonoClassField pointer of the named field or NULL
6744 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6746 return mono_class_get_field_from_name_full (klass, name, NULL);
6750 * mono_class_get_field_from_name_full:
6751 * @klass: the class to lookup the field.
6752 * @name: the field name
6753 * @type: the type of the fields. This optional.
6755 * Search the class @klass and it's parents for a field with the name @name and type @type.
6757 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6758 * of its generic type definition.
6760 * Returns: the MonoClassField pointer of the named field or NULL
6763 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6767 mono_class_setup_fields_locking (klass);
6768 if (klass->exception_type)
6772 for (i = 0; i < klass->field.count; ++i) {
6773 MonoClassField *field = &klass->fields [i];
6775 if (strcmp (name, mono_field_get_name (field)) != 0)
6779 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6780 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6785 klass = klass->parent;
6791 * mono_class_get_field_token:
6792 * @field: the field we need the token of
6794 * Get the token of a field. Note that the tokesn is only valid for the image
6795 * the field was loaded from. Don't use this function for fields in dynamic types.
6797 * Returns: the token representing the field in the image it was loaded from.
6800 mono_class_get_field_token (MonoClassField *field)
6802 MonoClass *klass = field->parent;
6805 mono_class_setup_fields_locking (klass);
6810 for (i = 0; i < klass->field.count; ++i) {
6811 if (&klass->fields [i] == field) {
6812 int idx = klass->field.first + i + 1;
6814 if (klass->image->uncompressed_metadata)
6815 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6816 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6819 klass = klass->parent;
6822 g_assert_not_reached ();
6827 mono_field_get_index (MonoClassField *field)
6829 int index = field - field->parent->fields;
6831 g_assert (index >= 0 && index < field->parent->field.count);
6837 * mono_class_get_field_default_value:
6839 * Return the default value of the field as a pointer into the metadata blob.
6842 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6845 guint32 constant_cols [MONO_CONSTANT_SIZE];
6847 MonoClass *klass = field->parent;
6849 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6851 if (!klass->ext || !klass->ext->field_def_values) {
6852 mono_loader_lock ();
6853 mono_class_alloc_ext (klass);
6854 if (!klass->ext->field_def_values)
6855 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6856 mono_loader_unlock ();
6859 field_index = mono_field_get_index (field);
6861 if (!klass->ext->field_def_values [field_index].data) {
6862 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6866 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6868 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6869 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6870 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6873 *def_type = klass->ext->field_def_values [field_index].def_type;
6874 return klass->ext->field_def_values [field_index].data;
6878 mono_property_get_index (MonoProperty *prop)
6880 int index = prop - prop->parent->ext->properties;
6882 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6888 * mono_class_get_property_default_value:
6890 * Return the default value of the field as a pointer into the metadata blob.
6893 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6896 guint32 constant_cols [MONO_CONSTANT_SIZE];
6897 MonoClass *klass = property->parent;
6899 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6901 * We don't cache here because it is not used by C# so it's quite rare, but
6902 * we still do the lookup in klass->ext because that is where the data
6903 * is stored for dynamic assemblies.
6906 if (image_is_dynamic (klass->image)) {
6907 int prop_index = mono_property_get_index (property);
6908 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6909 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6910 return klass->ext->prop_def_values [prop_index].data;
6914 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6918 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6919 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6920 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6924 mono_class_get_event_token (MonoEvent *event)
6926 MonoClass *klass = event->parent;
6931 for (i = 0; i < klass->ext->event.count; ++i) {
6932 if (&klass->ext->events [i] == event)
6933 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6936 klass = klass->parent;
6939 g_assert_not_reached ();
6944 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6948 gpointer iter = NULL;
6949 while ((p = mono_class_get_properties (klass, &iter))) {
6950 if (! strcmp (name, p->name))
6953 klass = klass->parent;
6959 mono_class_get_property_token (MonoProperty *prop)
6961 MonoClass *klass = prop->parent;
6965 gpointer iter = NULL;
6966 while ((p = mono_class_get_properties (klass, &iter))) {
6967 if (&klass->ext->properties [i] == prop)
6968 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6972 klass = klass->parent;
6975 g_assert_not_reached ();
6980 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6982 const char *name, *nspace;
6983 if (image_is_dynamic (image))
6984 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6986 switch (type_token & 0xff000000){
6987 case MONO_TOKEN_TYPE_DEF: {
6988 guint32 cols [MONO_TYPEDEF_SIZE];
6989 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6990 guint tidx = mono_metadata_token_index (type_token);
6992 if (tidx > tt->rows)
6993 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6995 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6996 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6997 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6998 if (strlen (nspace) == 0)
6999 return g_strdup_printf ("%s", name);
7001 return g_strdup_printf ("%s.%s", nspace, name);
7004 case MONO_TOKEN_TYPE_REF: {
7006 guint32 cols [MONO_TYPEREF_SIZE];
7007 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7008 guint tidx = mono_metadata_token_index (type_token);
7011 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7013 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7014 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7015 mono_error_cleanup (&error);
7019 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7020 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7021 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7022 if (strlen (nspace) == 0)
7023 return g_strdup_printf ("%s", name);
7025 return g_strdup_printf ("%s.%s", nspace, name);
7028 case MONO_TOKEN_TYPE_SPEC:
7029 return g_strdup_printf ("Typespec 0x%08x", type_token);
7031 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7036 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7038 if (image_is_dynamic (image))
7039 return g_strdup_printf ("DynamicAssembly %s", image->name);
7041 switch (type_token & 0xff000000){
7042 case MONO_TOKEN_TYPE_DEF:
7043 if (image->assembly)
7044 return mono_stringify_assembly_name (&image->assembly->aname);
7045 else if (image->assembly_name)
7046 return g_strdup (image->assembly_name);
7047 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7048 case MONO_TOKEN_TYPE_REF: {
7050 MonoAssemblyName aname;
7051 guint32 cols [MONO_TYPEREF_SIZE];
7052 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7053 guint32 idx = mono_metadata_token_index (type_token);
7056 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7058 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7059 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7060 mono_error_cleanup (&error);
7063 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7065 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7066 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7067 case MONO_RESOLTION_SCOPE_MODULE:
7069 return g_strdup ("");
7070 case MONO_RESOLTION_SCOPE_MODULEREF:
7072 return g_strdup ("");
7073 case MONO_RESOLTION_SCOPE_TYPEREF:
7075 return g_strdup ("");
7076 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7077 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7078 return mono_stringify_assembly_name (&aname);
7080 g_assert_not_reached ();
7084 case MONO_TOKEN_TYPE_SPEC:
7086 return g_strdup ("");
7088 g_assert_not_reached ();
7095 * mono_class_get_full:
7096 * @image: the image where the class resides
7097 * @type_token: the token for the class
7098 * @context: the generic context used to evaluate generic instantiations in
7100 * Returns: the MonoClass that represents @type_token in @image
7103 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7106 MonoClass *class = NULL;
7108 if (image_is_dynamic (image)) {
7109 int table = mono_metadata_token_table (type_token);
7111 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7112 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7115 return mono_lookup_dynamic_token (image, type_token, context);
7118 switch (type_token & 0xff000000){
7119 case MONO_TOKEN_TYPE_DEF:
7120 class = mono_class_create_from_typedef (image, type_token, &error);
7121 if (!mono_error_ok (&error)) {
7122 mono_loader_set_error_from_mono_error (&error);
7123 /*FIXME don't swallow the error message*/
7124 mono_error_cleanup (&error);
7128 case MONO_TOKEN_TYPE_REF:
7129 class = mono_class_from_typeref (image, type_token);
7131 case MONO_TOKEN_TYPE_SPEC:
7132 class = mono_class_create_from_typespec (image, type_token, context, &error);
7133 if (!mono_error_ok (&error)) {
7134 /*FIXME don't swallow the error message*/
7135 mono_error_cleanup (&error);
7139 g_warning ("unknown token type %x", type_token & 0xff000000);
7140 g_assert_not_reached ();
7144 char *name = mono_class_name_from_token (image, type_token);
7145 char *assembly = mono_assembly_name_from_token (image, type_token);
7146 mono_loader_set_error_type_load (name, assembly);
7156 * mono_type_get_full:
7157 * @image: the image where the type resides
7158 * @type_token: the token for the type
7159 * @context: the generic context used to evaluate generic instantiations in
7161 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7163 * Returns: the MonoType that represents @type_token in @image
7166 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7169 MonoType *type = NULL;
7170 gboolean inflated = FALSE;
7172 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7173 if (image_is_dynamic (image))
7174 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7176 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7177 MonoClass *class = mono_class_get_full (image, type_token, context);
7178 return class ? mono_class_get_type (class) : NULL;
7181 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7183 if (!mono_error_ok (&error)) {
7184 /*FIXME don't swalloc the error message.*/
7185 char *name = mono_class_name_from_token (image, type_token);
7186 char *assembly = mono_assembly_name_from_token (image, type_token);
7188 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7190 mono_error_cleanup (&error);
7191 mono_loader_set_error_type_load (name, assembly);
7196 MonoType *tmp = type;
7197 type = mono_class_get_type (mono_class_from_mono_type (type));
7198 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7199 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7200 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7202 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7204 if (type->type != tmp->type)
7207 mono_metadata_free_type (tmp);
7214 mono_class_get (MonoImage *image, guint32 type_token)
7216 return mono_class_get_full (image, type_token, NULL);
7220 * mono_image_init_name_cache:
7222 * Initializes the class name cache stored in image->name_cache.
7224 * LOCKING: Acquires the corresponding image lock.
7227 mono_image_init_name_cache (MonoImage *image)
7229 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7230 guint32 cols [MONO_TYPEDEF_SIZE];
7233 guint32 i, visib, nspace_index;
7234 GHashTable *name_cache2, *nspace_table;
7236 mono_image_lock (image);
7238 if (image->name_cache) {
7239 mono_image_unlock (image);
7243 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7245 if (image_is_dynamic (image)) {
7246 mono_image_unlock (image);
7250 /* Temporary hash table to avoid lookups in the nspace_table */
7251 name_cache2 = g_hash_table_new (NULL, NULL);
7253 for (i = 1; i <= t->rows; ++i) {
7254 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7255 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7257 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7258 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7260 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7262 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7263 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7265 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7266 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7267 if (!nspace_table) {
7268 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7269 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7270 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7273 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7276 /* Load type names from EXPORTEDTYPES table */
7278 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7279 guint32 cols [MONO_EXP_TYPE_SIZE];
7282 for (i = 0; i < t->rows; ++i) {
7283 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7284 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7285 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7287 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7288 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7289 if (!nspace_table) {
7290 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7291 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7292 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7295 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7299 g_hash_table_destroy (name_cache2);
7300 mono_image_unlock (image);
7303 /*FIXME Only dynamic assemblies should allow this operation.*/
7305 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7306 const char *name, guint32 index)
7308 GHashTable *nspace_table;
7309 GHashTable *name_cache;
7312 mono_image_lock (image);
7314 if (!image->name_cache)
7315 mono_image_init_name_cache (image);
7317 name_cache = image->name_cache;
7318 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7319 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7320 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7323 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7324 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7326 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7328 mono_image_unlock (image);
7337 find_nocase (gpointer key, gpointer value, gpointer user_data)
7339 char *name = (char*)key;
7340 FindUserData *data = (FindUserData*)user_data;
7342 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7343 data->value = value;
7347 * mono_class_from_name_case:
7348 * @image: The MonoImage where the type is looked up in
7349 * @name_space: the type namespace
7350 * @name: the type short name.
7352 * Obtains a MonoClass with a given namespace and a given name which
7353 * is located in the given MonoImage. The namespace and name
7354 * lookups are case insensitive.
7357 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7359 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7360 guint32 cols [MONO_TYPEDEF_SIZE];
7365 if (image_is_dynamic (image)) {
7367 FindUserData user_data;
7369 mono_image_lock (image);
7371 if (!image->name_cache)
7372 mono_image_init_name_cache (image);
7374 user_data.key = name_space;
7375 user_data.value = NULL;
7376 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7378 if (user_data.value) {
7379 GHashTable *nspace_table = (GHashTable*)user_data.value;
7381 user_data.key = name;
7382 user_data.value = NULL;
7384 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7386 if (user_data.value)
7387 token = GPOINTER_TO_UINT (user_data.value);
7390 mono_image_unlock (image);
7393 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7399 /* add a cache if needed */
7400 for (i = 1; i <= t->rows; ++i) {
7401 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7402 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7404 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7405 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7407 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7409 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7410 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7411 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7412 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7418 return_nested_in (MonoClass *class, char *nested)
7421 char *s = strchr (nested, '/');
7422 gpointer iter = NULL;
7429 while ((found = mono_class_get_nested_types (class, &iter))) {
7430 if (strcmp (found->name, nested) == 0) {
7432 return return_nested_in (found, s);
7440 search_modules (MonoImage *image, const char *name_space, const char *name)
7442 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7443 MonoImage *file_image;
7448 * The EXPORTEDTYPES table only contains public types, so have to search the
7450 * Note: image->modules contains the contents of the MODULEREF table, while
7451 * the real module list is in the FILE table.
7453 for (i = 0; i < file_table->rows; i++) {
7454 guint32 cols [MONO_FILE_SIZE];
7455 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7456 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7459 file_image = mono_image_load_file_for_image (image, i + 1);
7461 class = mono_class_from_name (file_image, name_space, name);
7471 * mono_class_from_name:
7472 * @image: The MonoImage where the type is looked up in
7473 * @name_space: the type namespace
7474 * @name: the type short name.
7476 * Obtains a MonoClass with a given namespace and a given name which
7477 * is located in the given MonoImage.
7479 * To reference nested classes, use the "/" character as a separator.
7480 * For example use "Foo/Bar" to reference the class Bar that is nested
7481 * inside Foo, like this: "class Foo { class Bar {} }".
7484 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7486 GHashTable *nspace_table;
7487 MonoImage *loaded_image;
7494 if ((nested = strchr (name, '/'))) {
7495 int pos = nested - name;
7496 int len = strlen (name);
7499 memcpy (buf, name, len + 1);
7501 nested = buf + pos + 1;
7505 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7506 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7507 gboolean res = get_class_from_name (image, name_space, name, &class);
7510 class = search_modules (image, name_space, name);
7512 return class ? return_nested_in (class, nested) : NULL;
7518 mono_image_lock (image);
7520 if (!image->name_cache)
7521 mono_image_init_name_cache (image);
7523 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7526 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7528 mono_image_unlock (image);
7530 if (!token && image_is_dynamic (image) && image->modules) {
7531 /* Search modules as well */
7532 for (i = 0; i < image->module_count; ++i) {
7533 MonoImage *module = image->modules [i];
7535 class = mono_class_from_name (module, name_space, name);
7542 class = search_modules (image, name_space, name);
7550 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7551 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7552 guint32 cols [MONO_EXP_TYPE_SIZE];
7555 idx = mono_metadata_token_index (token);
7557 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7559 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7560 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7561 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7564 class = mono_class_from_name (loaded_image, name_space, name);
7566 return return_nested_in (class, nested);
7568 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7569 guint32 assembly_idx;
7571 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7573 mono_assembly_load_reference (image, assembly_idx - 1);
7574 g_assert (image->references [assembly_idx - 1]);
7575 if (image->references [assembly_idx - 1] == (gpointer)-1)
7578 /* FIXME: Cycle detection */
7579 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7581 g_error ("not yet implemented");
7585 token = MONO_TOKEN_TYPE_DEF | token;
7587 class = mono_class_get (image, token);
7589 return return_nested_in (class, nested);
7594 * mono_class_is_subclass_of:
7595 * @klass: class to probe if it is a subclass of another one
7596 * @klassc: the class we suspect is the base class
7597 * @check_interfaces: whether we should perform interface checks
7599 * This method determines whether @klass is a subclass of @klassc.
7601 * If the @check_interfaces flag is set, then if @klassc is an interface
7602 * this method return true if the @klass implements the interface or
7603 * if @klass is an interface, if one of its base classes is @klass.
7605 * If @check_interfaces is false then, then if @klass is not an interface
7606 * then it returns true if the @klass is a subclass of @klassc.
7608 * if @klass is an interface and @klassc is System.Object, then this function
7613 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7614 gboolean check_interfaces)
7616 /*FIXME test for interfaces with variant generic arguments*/
7618 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7619 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7621 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7624 for (i = 0; i < klass->interface_count; i ++) {
7625 MonoClass *ic = klass->interfaces [i];
7630 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7635 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7638 if (klassc == mono_defaults.object_class)
7645 mono_type_is_generic_argument (MonoType *type)
7647 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7651 mono_class_has_variant_generic_params (MonoClass *klass)
7654 MonoGenericContainer *container;
7656 if (!klass->generic_class)
7659 container = klass->generic_class->container_class->generic_container;
7661 for (i = 0; i < container->type_argc; ++i)
7662 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7669 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7671 if (target == candidate)
7674 if (check_for_reference_conv &&
7675 mono_type_is_generic_argument (&target->byval_arg) &&
7676 mono_type_is_generic_argument (&candidate->byval_arg)) {
7677 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7678 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7680 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7683 if (!mono_class_is_assignable_from (target, candidate))
7689 * @container the generic container from the GTD
7690 * @klass: the class to be assigned to
7691 * @oklass: the source class
7693 * Both klass and oklass must be instances of the same generic interface.
7694 * Return true if @klass can be assigned to a @klass variable
7697 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7700 MonoType **klass_argv, **oklass_argv;
7701 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7702 MonoGenericContainer *container = klass_gtd->generic_container;
7704 if (klass == oklass)
7707 /*Viable candidates are instances of the same generic interface*/
7708 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7711 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7712 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7714 for (j = 0; j < container->type_argc; ++j) {
7715 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7716 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7718 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7722 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7723 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7725 if (param1_class != param2_class) {
7726 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7727 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7729 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7730 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7740 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7742 MonoGenericParam *gparam, *ogparam;
7743 MonoGenericParamInfo *tinfo, *cinfo;
7744 MonoClass **candidate_class;
7745 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7748 if (target == candidate)
7750 if (target->byval_arg.type != candidate->byval_arg.type)
7753 gparam = target->byval_arg.data.generic_param;
7754 ogparam = candidate->byval_arg.data.generic_param;
7755 tinfo = mono_generic_param_info (gparam);
7756 cinfo = mono_generic_param_info (ogparam);
7758 class_constraint_satisfied = FALSE;
7759 valuetype_constraint_satisfied = FALSE;
7761 /*candidate must have a super set of target's special constraints*/
7762 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7763 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7765 if (cinfo->constraints) {
7766 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7767 MonoClass *cc = *candidate_class;
7769 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7770 class_constraint_satisfied = TRUE;
7771 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7772 valuetype_constraint_satisfied = TRUE;
7775 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7776 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7778 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7780 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7782 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7783 valuetype_constraint_satisfied)) {
7788 /*candidate type constraints must be a superset of target's*/
7789 if (tinfo->constraints) {
7790 MonoClass **target_class;
7791 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7792 MonoClass *tc = *target_class;
7795 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7796 * check it's constraints since it satisfy the constraint by itself.
7798 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7801 if (!cinfo->constraints)
7804 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7805 MonoClass *cc = *candidate_class;
7807 if (mono_class_is_assignable_from (tc, cc))
7811 * This happens when we have the following:
7813 * Bar<K> where K : IFace
7814 * Foo<T, U> where T : U where U : IFace
7816 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7819 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7820 if (mono_gparam_is_assignable_from (target, cc))
7824 if (!*candidate_class)
7829 /*candidate itself must have a constraint that satisfy target*/
7830 if (cinfo->constraints) {
7831 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7832 MonoClass *cc = *candidate_class;
7833 if (mono_class_is_assignable_from (target, cc))
7841 * mono_class_is_assignable_from:
7842 * @klass: the class to be assigned to
7843 * @oklass: the source class
7845 * Return: true if an instance of object oklass can be assigned to an
7846 * instance of object @klass
7849 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7851 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7853 mono_class_init (klass);
7855 if (!oklass->inited)
7856 mono_class_init (oklass);
7858 if (klass->exception_type || oklass->exception_type)
7861 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7862 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7864 return mono_gparam_is_assignable_from (klass, oklass);
7867 if (MONO_CLASS_IS_INTERFACE (klass)) {
7868 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7869 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7870 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7874 for (i = 0; constraints [i]; ++i) {
7875 if (mono_class_is_assignable_from (klass, constraints [i]))
7883 /* interface_offsets might not be set for dynamic classes */
7884 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7886 * oklass might be a generic type parameter but they have
7887 * interface_offsets set.
7889 return mono_reflection_call_is_assignable_to (oklass, klass);
7890 if (!oklass->interface_bitmap)
7891 /* Happens with generic instances of not-yet created dynamic types */
7893 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7896 if (mono_class_has_variant_generic_params (klass)) {
7899 mono_class_setup_interfaces (oklass, &error);
7900 if (!mono_error_ok (&error)) {
7901 mono_error_cleanup (&error);
7905 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7906 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7907 MonoClass *iface = oklass->interfaces_packed [i];
7909 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7914 } else if (klass->delegate) {
7915 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7917 }else if (klass->rank) {
7918 MonoClass *eclass, *eoclass;
7920 if (oklass->rank != klass->rank)
7923 /* vectors vs. one dimensional arrays */
7924 if (oklass->byval_arg.type != klass->byval_arg.type)
7927 eclass = klass->cast_class;
7928 eoclass = oklass->cast_class;
7931 * a is b does not imply a[] is b[] when a is a valuetype, and
7932 * b is a reference type.
7935 if (eoclass->valuetype) {
7936 if ((eclass == mono_defaults.enum_class) ||
7937 (eclass == mono_defaults.enum_class->parent) ||
7938 (eclass == mono_defaults.object_class))
7942 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7943 } else if (mono_class_is_nullable (klass)) {
7944 if (mono_class_is_nullable (oklass))
7945 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7947 return mono_class_is_assignable_from (klass->cast_class, oklass);
7948 } else if (klass == mono_defaults.object_class)
7951 return mono_class_has_parent (oklass, klass);
7954 /*Check if @oklass is variant compatible with @klass.*/
7956 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7959 MonoType **klass_argv, **oklass_argv;
7960 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7961 MonoGenericContainer *container = klass_gtd->generic_container;
7963 /*Viable candidates are instances of the same generic interface*/
7964 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7967 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7968 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7970 for (j = 0; j < container->type_argc; ++j) {
7971 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7972 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7974 if (param1_class->valuetype != param2_class->valuetype)
7978 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7979 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7981 if (param1_class != param2_class) {
7982 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7983 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7985 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7986 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7994 /*Check if @candidate implements the interface @target*/
7996 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8000 gboolean is_variant = mono_class_has_variant_generic_params (target);
8002 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8003 if (mono_class_is_variant_compatible_slow (target, candidate))
8008 if (candidate == target)
8011 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8012 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8013 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8015 if (tb && tb->interfaces) {
8016 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8017 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8018 MonoClass *iface_class;
8020 /* we can't realize the type here since it can do pretty much anything. */
8023 iface_class = mono_class_from_mono_type (iface->type);
8024 if (iface_class == target)
8026 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8028 if (mono_class_implement_interface_slow (target, iface_class))
8033 /*setup_interfaces don't mono_class_init anything*/
8034 /*FIXME this doesn't handle primitive type arrays.
8035 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8036 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8038 mono_class_setup_interfaces (candidate, &error);
8039 if (!mono_error_ok (&error)) {
8040 mono_error_cleanup (&error);
8044 for (i = 0; i < candidate->interface_count; ++i) {
8045 if (candidate->interfaces [i] == target)
8048 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8051 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8055 candidate = candidate->parent;
8056 } while (candidate);
8062 * Check if @oklass can be assigned to @klass.
8063 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8066 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8068 if (candidate == target)
8070 if (target == mono_defaults.object_class)
8073 if (mono_class_has_parent (candidate, target))
8076 /*If target is not an interface there is no need to check them.*/
8077 if (MONO_CLASS_IS_INTERFACE (target))
8078 return mono_class_implement_interface_slow (target, candidate);
8080 if (target->delegate && mono_class_has_variant_generic_params (target))
8081 return mono_class_is_variant_compatible (target, candidate, FALSE);
8084 MonoClass *eclass, *eoclass;
8086 if (target->rank != candidate->rank)
8089 /* vectors vs. one dimensional arrays */
8090 if (target->byval_arg.type != candidate->byval_arg.type)
8093 eclass = target->cast_class;
8094 eoclass = candidate->cast_class;
8097 * a is b does not imply a[] is b[] when a is a valuetype, and
8098 * b is a reference type.
8101 if (eoclass->valuetype) {
8102 if ((eclass == mono_defaults.enum_class) ||
8103 (eclass == mono_defaults.enum_class->parent) ||
8104 (eclass == mono_defaults.object_class))
8108 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8110 /*FIXME properly handle nullables */
8111 /*FIXME properly handle (M)VAR */
8116 * mono_class_get_cctor:
8117 * @klass: A MonoClass pointer
8119 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8122 mono_class_get_cctor (MonoClass *klass)
8124 MonoCachedClassInfo cached_info;
8126 if (image_is_dynamic (klass->image)) {
8128 * has_cctor is not set for these classes because mono_class_init () is
8131 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8134 if (!klass->has_cctor)
8137 if (mono_class_get_cached_class_info (klass, &cached_info))
8138 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8140 if (klass->generic_class && !klass->methods)
8141 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8143 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8147 * mono_class_get_finalizer:
8148 * @klass: The MonoClass pointer
8150 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8153 mono_class_get_finalizer (MonoClass *klass)
8155 MonoCachedClassInfo cached_info;
8158 mono_class_init (klass);
8159 if (!mono_class_has_finalizer (klass))
8162 if (mono_class_get_cached_class_info (klass, &cached_info))
8163 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8165 mono_class_setup_vtable (klass);
8166 return klass->vtable [finalize_slot];
8171 * mono_class_needs_cctor_run:
8172 * @klass: the MonoClass pointer
8173 * @caller: a MonoMethod describing the caller
8175 * Determines whenever the class has a static constructor and whenever it
8176 * needs to be called when executing CALLER.
8179 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8183 method = mono_class_get_cctor (klass);
8185 return (method == caller) ? FALSE : TRUE;
8191 * mono_class_array_element_size:
8194 * Returns: the number of bytes an element of type @klass
8195 * uses when stored into an array.
8198 mono_class_array_element_size (MonoClass *klass)
8200 MonoType *type = &klass->byval_arg;
8203 switch (type->type) {
8206 case MONO_TYPE_BOOLEAN:
8210 case MONO_TYPE_CHAR:
8219 case MONO_TYPE_CLASS:
8220 case MONO_TYPE_STRING:
8221 case MONO_TYPE_OBJECT:
8222 case MONO_TYPE_SZARRAY:
8223 case MONO_TYPE_ARRAY:
8225 case MONO_TYPE_MVAR:
8226 return sizeof (gpointer);
8231 case MONO_TYPE_VALUETYPE:
8232 if (type->data.klass->enumtype) {
8233 type = mono_class_enum_basetype (type->data.klass);
8234 klass = klass->element_class;
8237 return mono_class_instance_size (klass) - sizeof (MonoObject);
8238 case MONO_TYPE_GENERICINST:
8239 type = &type->data.generic_class->container_class->byval_arg;
8242 case MONO_TYPE_VOID:
8246 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8252 * mono_array_element_size:
8253 * @ac: pointer to a #MonoArrayClass
8255 * Returns: the size of single array element.
8258 mono_array_element_size (MonoClass *ac)
8260 g_assert (ac->rank);
8261 return ac->sizes.element_size;
8265 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8266 MonoGenericContext *context)
8268 if (image_is_dynamic (image)) {
8269 MonoClass *tmp_handle_class;
8270 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8272 g_assert (tmp_handle_class);
8274 *handle_class = tmp_handle_class;
8276 if (tmp_handle_class == mono_defaults.typehandle_class)
8277 return &((MonoClass*)obj)->byval_arg;
8282 switch (token & 0xff000000) {
8283 case MONO_TOKEN_TYPE_DEF:
8284 case MONO_TOKEN_TYPE_REF:
8285 case MONO_TOKEN_TYPE_SPEC: {
8288 *handle_class = mono_defaults.typehandle_class;
8289 type = mono_type_get_full (image, token, context);
8292 mono_class_init (mono_class_from_mono_type (type));
8293 /* We return a MonoType* as handle */
8296 case MONO_TOKEN_FIELD_DEF: {
8298 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8302 *handle_class = mono_defaults.fieldhandle_class;
8303 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8306 mono_class_init (class);
8307 return mono_class_get_field (class, token);
8309 case MONO_TOKEN_METHOD_DEF:
8310 case MONO_TOKEN_METHOD_SPEC: {
8312 meth = mono_get_method_full (image, token, NULL, context);
8314 *handle_class = mono_defaults.methodhandle_class;
8317 case MONO_TOKEN_MEMBER_REF: {
8318 guint32 cols [MONO_MEMBERREF_SIZE];
8320 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8321 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8322 mono_metadata_decode_blob_size (sig, &sig);
8323 if (*sig == 0x6) { /* it's a field */
8325 MonoClassField *field;
8326 field = mono_field_from_token (image, token, &klass, context);
8328 *handle_class = mono_defaults.fieldhandle_class;
8332 meth = mono_get_method_full (image, token, NULL, context);
8334 *handle_class = mono_defaults.methodhandle_class;
8339 g_warning ("Unknown token 0x%08x in ldtoken", token);
8346 * This function might need to call runtime functions so it can't be part
8347 * of the metadata library.
8349 static MonoLookupDynamicToken lookup_dynamic = NULL;
8352 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8354 lookup_dynamic = func;
8358 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8360 MonoClass *handle_class;
8362 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8366 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8368 return lookup_dynamic (image, token, valid_token, handle_class, context);
8371 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8374 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8376 get_cached_class_info = func;
8380 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8382 if (!get_cached_class_info)
8385 return get_cached_class_info (klass, res);
8389 mono_install_get_class_from_name (MonoGetClassFromName func)
8391 get_class_from_name = func;
8395 mono_class_get_image (MonoClass *klass)
8397 return klass->image;
8401 * mono_class_get_element_class:
8402 * @klass: the MonoClass to act on
8404 * Returns: the element class of an array or an enumeration.
8407 mono_class_get_element_class (MonoClass *klass)
8409 return klass->element_class;
8413 * mono_class_is_valuetype:
8414 * @klass: the MonoClass to act on
8416 * Returns: true if the MonoClass represents a ValueType.
8419 mono_class_is_valuetype (MonoClass *klass)
8421 return klass->valuetype;
8425 * mono_class_is_enum:
8426 * @klass: the MonoClass to act on
8428 * Returns: true if the MonoClass represents an enumeration.
8431 mono_class_is_enum (MonoClass *klass)
8433 return klass->enumtype;
8437 * mono_class_enum_basetype:
8438 * @klass: the MonoClass to act on
8440 * Returns: the underlying type representation for an enumeration.
8443 mono_class_enum_basetype (MonoClass *klass)
8445 if (klass->element_class == klass)
8446 /* SRE or broken types */
8449 return &klass->element_class->byval_arg;
8453 * mono_class_get_parent
8454 * @klass: the MonoClass to act on
8456 * Returns: the parent class for this class.
8459 mono_class_get_parent (MonoClass *klass)
8461 return klass->parent;
8465 * mono_class_get_nesting_type;
8466 * @klass: the MonoClass to act on
8468 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8471 mono_class_get_nesting_type (MonoClass *klass)
8473 return klass->nested_in;
8477 * mono_class_get_rank:
8478 * @klass: the MonoClass to act on
8480 * Returns: the rank for the array (the number of dimensions).
8483 mono_class_get_rank (MonoClass *klass)
8489 * mono_class_get_flags:
8490 * @klass: the MonoClass to act on
8492 * The type flags from the TypeDef table from the metadata.
8493 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8496 * Returns: the flags from the TypeDef table.
8499 mono_class_get_flags (MonoClass *klass)
8501 return klass->flags;
8505 * mono_class_get_name
8506 * @klass: the MonoClass to act on
8508 * Returns: the name of the class.
8511 mono_class_get_name (MonoClass *klass)
8517 * mono_class_get_namespace:
8518 * @klass: the MonoClass to act on
8520 * Returns: the namespace of the class.
8523 mono_class_get_namespace (MonoClass *klass)
8525 return klass->name_space;
8529 * mono_class_get_type:
8530 * @klass: the MonoClass to act on
8532 * This method returns the internal Type representation for the class.
8534 * Returns: the MonoType from the class.
8537 mono_class_get_type (MonoClass *klass)
8539 return &klass->byval_arg;
8543 * mono_class_get_type_token
8544 * @klass: the MonoClass to act on
8546 * This method returns type token for the class.
8548 * Returns: the type token for the class.
8551 mono_class_get_type_token (MonoClass *klass)
8553 return klass->type_token;
8557 * mono_class_get_byref_type:
8558 * @klass: the MonoClass to act on
8563 mono_class_get_byref_type (MonoClass *klass)
8565 return &klass->this_arg;
8569 * mono_class_num_fields:
8570 * @klass: the MonoClass to act on
8572 * Returns: the number of static and instance fields in the class.
8575 mono_class_num_fields (MonoClass *klass)
8577 return klass->field.count;
8581 * mono_class_num_methods:
8582 * @klass: the MonoClass to act on
8584 * Returns: the number of methods in the class.
8587 mono_class_num_methods (MonoClass *klass)
8589 return klass->method.count;
8593 * mono_class_num_properties
8594 * @klass: the MonoClass to act on
8596 * Returns: the number of properties in the class.
8599 mono_class_num_properties (MonoClass *klass)
8601 mono_class_setup_properties (klass);
8603 return klass->ext->property.count;
8607 * mono_class_num_events:
8608 * @klass: the MonoClass to act on
8610 * Returns: the number of events in the class.
8613 mono_class_num_events (MonoClass *klass)
8615 mono_class_setup_events (klass);
8617 return klass->ext->event.count;
8621 * mono_class_get_fields:
8622 * @klass: the MonoClass to act on
8624 * This routine is an iterator routine for retrieving the fields in a class.
8626 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8627 * iterate over all of the elements. When no more values are
8628 * available, the return value is NULL.
8630 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8633 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8635 MonoClassField* field;
8639 mono_class_setup_fields_locking (klass);
8640 if (klass->exception_type)
8642 /* start from the first */
8643 if (klass->field.count) {
8644 return *iter = &klass->fields [0];
8652 if (field < &klass->fields [klass->field.count]) {
8653 return *iter = field;
8659 * mono_class_get_methods
8660 * @klass: the MonoClass to act on
8662 * This routine is an iterator routine for retrieving the fields in a class.
8664 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8665 * iterate over all of the elements. When no more values are
8666 * available, the return value is NULL.
8668 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8671 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8673 MonoMethod** method;
8677 mono_class_setup_methods (klass);
8680 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8681 * FIXME we should better report this error to the caller
8683 if (!klass->methods)
8685 /* start from the first */
8686 if (klass->method.count) {
8687 *iter = &klass->methods [0];
8688 return klass->methods [0];
8696 if (method < &klass->methods [klass->method.count]) {
8704 * mono_class_get_virtual_methods:
8706 * Iterate over the virtual methods of KLASS.
8708 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8711 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8713 MonoMethod** method;
8716 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8718 mono_class_setup_methods (klass);
8720 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8721 * FIXME we should better report this error to the caller
8723 if (!klass->methods)
8725 /* start from the first */
8726 method = &klass->methods [0];
8731 while (method < &klass->methods [klass->method.count]) {
8732 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8736 if (method < &klass->methods [klass->method.count]) {
8743 /* Search directly in metadata to avoid calling setup_methods () */
8744 MonoMethod *res = NULL;
8750 start_index = GPOINTER_TO_UINT (*iter);
8753 for (i = start_index; i < klass->method.count; ++i) {
8756 /* class->method.first points into the methodptr table */
8757 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8759 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8763 if (i < klass->method.count) {
8764 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8765 /* Add 1 here so the if (*iter) check fails */
8766 *iter = GUINT_TO_POINTER (i + 1);
8775 * mono_class_get_properties:
8776 * @klass: the MonoClass to act on
8778 * This routine is an iterator routine for retrieving the properties in a class.
8780 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8781 * iterate over all of the elements. When no more values are
8782 * available, the return value is NULL.
8784 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8787 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8789 MonoProperty* property;
8793 mono_class_setup_properties (klass);
8794 /* start from the first */
8795 if (klass->ext->property.count) {
8796 return *iter = &klass->ext->properties [0];
8804 if (property < &klass->ext->properties [klass->ext->property.count]) {
8805 return *iter = property;
8811 * mono_class_get_events:
8812 * @klass: the MonoClass to act on
8814 * This routine is an iterator routine for retrieving the properties in a class.
8816 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8817 * iterate over all of the elements. When no more values are
8818 * available, the return value is NULL.
8820 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8823 mono_class_get_events (MonoClass* klass, gpointer *iter)
8829 mono_class_setup_events (klass);
8830 /* start from the first */
8831 if (klass->ext->event.count) {
8832 return *iter = &klass->ext->events [0];
8840 if (event < &klass->ext->events [klass->ext->event.count]) {
8841 return *iter = event;
8847 * mono_class_get_interfaces
8848 * @klass: the MonoClass to act on
8850 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8852 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8853 * iterate over all of the elements. When no more values are
8854 * available, the return value is NULL.
8856 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8859 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8867 mono_class_init (klass);
8868 if (!klass->interfaces_inited) {
8869 mono_class_setup_interfaces (klass, &error);
8870 if (!mono_error_ok (&error)) {
8871 mono_error_cleanup (&error);
8875 /* start from the first */
8876 if (klass->interface_count) {
8877 *iter = &klass->interfaces [0];
8878 return klass->interfaces [0];
8886 if (iface < &klass->interfaces [klass->interface_count]) {
8894 * mono_class_get_nested_types
8895 * @klass: the MonoClass to act on
8897 * This routine is an iterator routine for retrieving the nested types of a class.
8898 * This works only if @klass is non-generic, or a generic type definition.
8900 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8901 * iterate over all of the elements. When no more values are
8902 * available, the return value is NULL.
8904 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8907 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8915 if (!klass->nested_classes_inited) {
8916 if (!klass->type_token)
8917 klass->nested_classes_inited = TRUE;
8918 mono_loader_lock ();
8919 if (!klass->nested_classes_inited) {
8920 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8923 guint32 cols [MONO_NESTED_CLASS_SIZE];
8924 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8925 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8926 if (!mono_error_ok (&error)) {
8927 /*FIXME don't swallow the error message*/
8928 mono_error_cleanup (&error);
8930 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8933 mono_class_alloc_ext (klass);
8934 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8936 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8939 mono_memory_barrier ();
8940 klass->nested_classes_inited = TRUE;
8941 mono_loader_unlock ();
8945 /* start from the first */
8946 if (klass->ext && klass->ext->nested_classes) {
8947 *iter = klass->ext->nested_classes;
8948 return klass->ext->nested_classes->data;
8950 /* no nested types */
8965 * mono_class_is_delegate
8966 * @klass: the MonoClass to act on
8968 * Returns: true if the MonoClass represents a System.Delegate.
8971 mono_class_is_delegate (MonoClass *klass)
8973 return klass->delegate;
8977 * mono_class_implements_interface
8978 * @klass: The MonoClass to act on
8979 * @interface: The interface to check if @klass implements.
8981 * Returns: true if @klass implements @interface.
8984 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
8986 return mono_class_is_assignable_from (iface, klass);
8990 * mono_field_get_name:
8991 * @field: the MonoClassField to act on
8993 * Returns: the name of the field.
8996 mono_field_get_name (MonoClassField *field)
9002 * mono_field_get_type:
9003 * @field: the MonoClassField to act on
9005 * Returns: MonoType of the field.
9008 mono_field_get_type (MonoClassField *field)
9011 MonoType *type = mono_field_get_type_checked (field, &error);
9012 if (!mono_error_ok (&error)) {
9013 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9014 mono_error_cleanup (&error);
9021 * mono_field_get_type_checked:
9022 * @field: the MonoClassField to act on
9023 * @error: used to return any erro found while retrieving @field type
9025 * Returns: MonoType of the field.
9028 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9030 mono_error_init (error);
9032 mono_field_resolve_type (field, error);
9037 * mono_field_get_parent:
9038 * @field: the MonoClassField to act on
9040 * Returns: MonoClass where the field was defined.
9043 mono_field_get_parent (MonoClassField *field)
9045 return field->parent;
9049 * mono_field_get_flags;
9050 * @field: the MonoClassField to act on
9052 * The metadata flags for a field are encoded using the
9053 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9055 * Returns: the flags for the field.
9058 mono_field_get_flags (MonoClassField *field)
9061 return mono_field_resolve_flags (field);
9062 return field->type->attrs;
9066 * mono_field_get_offset;
9067 * @field: the MonoClassField to act on
9069 * Returns: the field offset.
9072 mono_field_get_offset (MonoClassField *field)
9074 return field->offset;
9078 mono_field_get_rva (MonoClassField *field)
9082 MonoClass *klass = field->parent;
9084 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9086 if (!klass->ext || !klass->ext->field_def_values) {
9087 mono_loader_lock ();
9088 mono_class_alloc_ext (klass);
9089 if (!klass->ext->field_def_values)
9090 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9091 mono_loader_unlock ();
9094 field_index = mono_field_get_index (field);
9096 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9097 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9099 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9100 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9103 return klass->ext->field_def_values [field_index].data;
9107 * mono_field_get_data;
9108 * @field: the MonoClassField to act on
9110 * Returns: pointer to the metadata constant value or to the field
9111 * data if it has an RVA flag.
9114 mono_field_get_data (MonoClassField *field)
9116 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9117 MonoTypeEnum def_type;
9119 return mono_class_get_field_default_value (field, &def_type);
9120 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9121 return mono_field_get_rva (field);
9128 * mono_property_get_name:
9129 * @prop: the MonoProperty to act on
9131 * Returns: the name of the property
9134 mono_property_get_name (MonoProperty *prop)
9140 * mono_property_get_set_method
9141 * @prop: the MonoProperty to act on.
9143 * Returns: the setter method of the property (A MonoMethod)
9146 mono_property_get_set_method (MonoProperty *prop)
9152 * mono_property_get_get_method
9153 * @prop: the MonoProperty to act on.
9155 * Returns: the setter method of the property (A MonoMethod)
9158 mono_property_get_get_method (MonoProperty *prop)
9164 * mono_property_get_parent:
9165 * @prop: the MonoProperty to act on.
9167 * Returns: the MonoClass where the property was defined.
9170 mono_property_get_parent (MonoProperty *prop)
9172 return prop->parent;
9176 * mono_property_get_flags:
9177 * @prop: the MonoProperty to act on.
9179 * The metadata flags for a property are encoded using the
9180 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9182 * Returns: the flags for the property.
9185 mono_property_get_flags (MonoProperty *prop)
9191 * mono_event_get_name:
9192 * @event: the MonoEvent to act on
9194 * Returns: the name of the event.
9197 mono_event_get_name (MonoEvent *event)
9203 * mono_event_get_add_method:
9204 * @event: The MonoEvent to act on.
9206 * Returns: the @add' method for the event (a MonoMethod).
9209 mono_event_get_add_method (MonoEvent *event)
9215 * mono_event_get_remove_method:
9216 * @event: The MonoEvent to act on.
9218 * Returns: the @remove method for the event (a MonoMethod).
9221 mono_event_get_remove_method (MonoEvent *event)
9223 return event->remove;
9227 * mono_event_get_raise_method:
9228 * @event: The MonoEvent to act on.
9230 * Returns: the @raise method for the event (a MonoMethod).
9233 mono_event_get_raise_method (MonoEvent *event)
9235 return event->raise;
9239 * mono_event_get_parent:
9240 * @event: the MonoEvent to act on.
9242 * Returns: the MonoClass where the event is defined.
9245 mono_event_get_parent (MonoEvent *event)
9247 return event->parent;
9251 * mono_event_get_flags
9252 * @event: the MonoEvent to act on.
9254 * The metadata flags for an event are encoded using the
9255 * EVENT_* constants. See the tabledefs.h file for details.
9257 * Returns: the flags for the event.
9260 mono_event_get_flags (MonoEvent *event)
9262 return event->attrs;
9266 * mono_class_get_method_from_name:
9267 * @klass: where to look for the method
9268 * @name: name of the method
9269 * @param_count: number of parameters. -1 for any number.
9271 * Obtains a MonoMethod with a given name and number of parameters.
9272 * It only works if there are no multiple signatures for any given method name.
9275 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9277 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9281 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9283 MonoMethod *res = NULL;
9286 /* Search directly in the metadata to avoid calling setup_methods () */
9287 for (i = 0; i < klass->method.count; ++i) {
9288 guint32 cols [MONO_METHOD_SIZE];
9290 MonoMethodSignature *sig;
9292 /* class->method.first points into the methodptr table */
9293 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9295 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9296 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9297 if (param_count == -1) {
9301 sig = mono_method_signature (method);
9302 if (sig && sig->param_count == param_count) {
9313 * mono_class_get_method_from_name_flags:
9314 * @klass: where to look for the method
9315 * @name_space: name of the method
9316 * @param_count: number of parameters. -1 for any number.
9317 * @flags: flags which must be set in the method
9319 * Obtains a MonoMethod with a given name and number of parameters.
9320 * It only works if there are no multiple signatures for any given method name.
9323 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9325 MonoMethod *res = NULL;
9328 mono_class_init (klass);
9330 if (klass->generic_class && !klass->methods) {
9331 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9333 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9337 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9338 mono_class_setup_methods (klass);
9340 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9341 See mono/tests/array_load_exception.il
9342 FIXME we should better report this error to the caller
9344 if (!klass->methods)
9346 for (i = 0; i < klass->method.count; ++i) {
9347 MonoMethod *method = klass->methods [i];
9349 if (method->name[0] == name [0] &&
9350 !strcmp (name, method->name) &&
9351 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9352 ((method->flags & flags) == flags)) {
9359 res = find_method_in_metadata (klass, name, param_count, flags);
9366 * mono_class_set_failure:
9367 * @klass: class in which the failure was detected
9368 * @ex_type: the kind of exception/error to be thrown (later)
9369 * @ex_data: exception data (specific to each type of exception/error)
9371 * Keep a detected failure informations in the class for later processing.
9372 * Note that only the first failure is kept.
9374 * LOCKING: Acquires the loader lock.
9377 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9379 if (klass->exception_type)
9382 mono_loader_lock ();
9383 klass->exception_type = ex_type;
9385 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9386 mono_loader_unlock ();
9392 * mono_class_get_exception_data:
9394 * Return the exception_data property of KLASS.
9396 * LOCKING: Acquires the loader lock.
9399 mono_class_get_exception_data (MonoClass *klass)
9401 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9405 * mono_classes_init:
9407 * Initialize the resources used by this module.
9410 mono_classes_init (void)
9412 mono_counters_register ("Inflated methods size",
9413 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9414 mono_counters_register ("Inflated classes",
9415 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9416 mono_counters_register ("Inflated classes size",
9417 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9418 mono_counters_register ("MonoClass size",
9419 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9420 mono_counters_register ("MonoClassExt size",
9421 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9425 * mono_classes_cleanup:
9427 * Free the resources used by this module.
9430 mono_classes_cleanup (void)
9432 if (global_interface_bitset)
9433 mono_bitset_free (global_interface_bitset);
9434 global_interface_bitset = NULL;
9438 * mono_class_get_exception_for_failure:
9439 * @klass: class in which the failure was detected
9441 * Return a constructed MonoException than the caller can then throw
9442 * using mono_raise_exception - or NULL if no failure is present (or
9443 * doesn't result in an exception).
9446 mono_class_get_exception_for_failure (MonoClass *klass)
9448 gpointer exception_data = mono_class_get_exception_data (klass);
9450 switch (klass->exception_type) {
9451 #ifndef DISABLE_SECURITY
9452 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9453 MonoDomain *domain = mono_domain_get ();
9454 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9455 MonoMethod *method = exception_data;
9456 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9457 MonoObject *exc = NULL;
9461 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9462 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9463 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9465 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9466 return (MonoException*) exc;
9469 case MONO_EXCEPTION_TYPE_LOAD: {
9472 char *str = mono_type_get_full_name (klass);
9473 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9474 name = mono_string_new (mono_domain_get (), str);
9476 ex = mono_get_exception_type_load (name, astr);
9480 case MONO_EXCEPTION_MISSING_METHOD: {
9481 char *class_name = exception_data;
9482 char *assembly_name = class_name + strlen (class_name) + 1;
9484 return mono_get_exception_missing_method (class_name, assembly_name);
9486 case MONO_EXCEPTION_MISSING_FIELD: {
9487 char *class_name = exception_data;
9488 char *member_name = class_name + strlen (class_name) + 1;
9490 return mono_get_exception_missing_field (class_name, member_name);
9492 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9493 char *msg_format = exception_data;
9494 char *assembly_name = msg_format + strlen (msg_format) + 1;
9495 char *msg = g_strdup_printf (msg_format, assembly_name);
9498 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9504 case MONO_EXCEPTION_BAD_IMAGE: {
9505 return mono_get_exception_bad_image_format (exception_data);
9508 MonoLoaderError *error;
9511 error = mono_loader_get_last_error ();
9513 ex = mono_loader_error_prepare_exception (error);
9517 /* TODO - handle other class related failures */
9524 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9526 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9527 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9529 if (outer_klass == inner_klass)
9531 inner_klass = inner_klass->nested_in;
9532 } while (inner_klass);
9537 mono_class_get_generic_type_definition (MonoClass *klass)
9539 return klass->generic_class ? klass->generic_class->container_class : klass;
9543 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9545 * Generic instantiations are ignored for all super types of @klass.
9547 * Visibility checks ignoring generic instantiations.
9550 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9553 klass = mono_class_get_generic_type_definition (klass);
9554 parent = mono_class_get_generic_type_definition (parent);
9555 mono_class_setup_supertypes (klass);
9557 for (i = 0; i < klass->idepth; ++i) {
9558 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9564 * Subtype can only access parent members with family protection if the site object
9565 * is subclass of Subtype. For example:
9566 * class A { protected int x; }
9568 * void valid_access () {
9572 * void invalid_access () {
9579 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9581 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9584 if (context_klass == NULL)
9586 /*if access_klass is not member_klass context_klass must be type compat*/
9587 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9593 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9596 if (accessing == accessed)
9598 if (!accessed || !accessing)
9601 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9602 * anywhere so untrusted friends are not safe to access platform's code internals */
9603 if (mono_security_core_clr_enabled ()) {
9604 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9608 mono_assembly_load_friends (accessed);
9609 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9610 MonoAssemblyName *friend = tmp->data;
9611 /* Be conservative with checks */
9614 if (strcmp (accessing->aname.name, friend->name))
9616 if (friend->public_key_token [0]) {
9617 if (!accessing->aname.public_key_token [0])
9619 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9628 * If klass is a generic type or if it is derived from a generic type, return the
9629 * MonoClass of the generic definition
9630 * Returns NULL if not found
9633 get_generic_definition_class (MonoClass *klass)
9636 if (klass->generic_class && klass->generic_class->container_class)
9637 return klass->generic_class->container_class;
9638 klass = klass->parent;
9644 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9647 for (i = 0; i < ginst->type_argc; ++i) {
9648 MonoType *type = ginst->type_argv[i];
9649 switch (type->type) {
9650 case MONO_TYPE_SZARRAY:
9651 if (!can_access_type (access_klass, type->data.klass))
9654 case MONO_TYPE_ARRAY:
9655 if (!can_access_type (access_klass, type->data.array->eklass))
9659 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9662 case MONO_TYPE_CLASS:
9663 case MONO_TYPE_VALUETYPE:
9664 case MONO_TYPE_GENERICINST:
9665 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9673 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9677 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9680 if (access_klass->element_class && !access_klass->enumtype)
9681 access_klass = access_klass->element_class;
9683 if (member_klass->element_class && !member_klass->enumtype)
9684 member_klass = member_klass->element_class;
9686 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9688 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9691 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9694 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9697 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9700 /*Non nested type with nested visibility. We just fail it.*/
9701 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9704 switch (access_level) {
9705 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9706 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9708 case TYPE_ATTRIBUTE_PUBLIC:
9711 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9714 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9715 return is_nesting_type (member_klass, access_klass);
9717 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9718 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9720 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9721 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9723 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9724 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9725 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9727 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9728 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9729 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9734 /* FIXME: check visibility of type, too */
9736 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9738 MonoClass *member_generic_def;
9739 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9742 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9743 access_klass->generic_container) &&
9744 (member_generic_def = get_generic_definition_class (member_klass))) {
9745 MonoClass *access_container;
9747 if (access_klass->generic_container)
9748 access_container = access_klass;
9750 access_container = access_klass->generic_class->container_class;
9752 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9756 /* Partition I 8.5.3.2 */
9757 /* the access level values are the same for fields and methods */
9758 switch (access_level) {
9759 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9760 /* same compilation unit */
9761 return access_klass->image == member_klass->image;
9762 case FIELD_ATTRIBUTE_PRIVATE:
9763 return access_klass == member_klass;
9764 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9765 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9766 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9769 case FIELD_ATTRIBUTE_ASSEMBLY:
9770 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9771 case FIELD_ATTRIBUTE_FAMILY:
9772 if (is_valid_family_access (access_klass, member_klass, context_klass))
9775 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9776 if (is_valid_family_access (access_klass, member_klass, context_klass))
9778 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9779 case FIELD_ATTRIBUTE_PUBLIC:
9786 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9788 /* FIXME: check all overlapping fields */
9789 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9791 MonoClass *nested = method->klass->nested_in;
9793 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9796 nested = nested->nested_in;
9803 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9805 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9807 MonoClass *nested = method->klass->nested_in;
9809 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9812 nested = nested->nested_in;
9817 * with generics calls to explicit interface implementations can be expressed
9818 * directly: the method is private, but we must allow it. This may be opening
9819 * a hole or the generics code should handle this differently.
9820 * Maybe just ensure the interface type is public.
9822 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9828 * mono_method_can_access_method_full:
9829 * @method: The caller method
9830 * @called: The called method
9831 * @context_klass: The static type on stack of the owner @called object used
9833 * This function must be used with instance calls, as they have more strict family accessibility.
9834 * It can be used with static methods, but context_klass should be NULL.
9836 * Returns: TRUE if caller have proper visibility and acessibility to @called
9839 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9841 MonoClass *access_class = method->klass;
9842 MonoClass *member_class = called->klass;
9843 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9845 MonoClass *nested = access_class->nested_in;
9847 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9850 nested = nested->nested_in;
9857 can = can_access_type (access_class, member_class);
9859 MonoClass *nested = access_class->nested_in;
9861 can = can_access_type (nested, member_class);
9864 nested = nested->nested_in;
9871 if (called->is_inflated) {
9872 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9873 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9882 * mono_method_can_access_field_full:
9883 * @method: The caller method
9884 * @field: The accessed field
9885 * @context_klass: The static type on stack of the owner @field object used
9887 * This function must be used with instance fields, as they have more strict family accessibility.
9888 * It can be used with static fields, but context_klass should be NULL.
9890 * Returns: TRUE if caller have proper visibility and acessibility to @field
9893 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9895 MonoClass *access_class = method->klass;
9896 MonoClass *member_class = field->parent;
9897 /* FIXME: check all overlapping fields */
9898 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9900 MonoClass *nested = access_class->nested_in;
9902 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9905 nested = nested->nested_in;
9912 can = can_access_type (access_class, member_class);
9914 MonoClass *nested = access_class->nested_in;
9916 can = can_access_type (nested, member_class);
9919 nested = nested->nested_in;
9929 * mono_class_can_access_class:
9930 * @source_class: The source class
9931 * @target_class: The accessed class
9933 * This function returns is @target_class is visible to @source_class
9935 * Returns: TRUE if source have proper visibility and acessibility to target
9938 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9940 return can_access_type (source_class, target_class);
9944 * mono_type_is_valid_enum_basetype:
9945 * @type: The MonoType to check
9947 * Returns: TRUE if the type can be used as the basetype of an enum
9949 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9950 switch (type->type) {
9953 case MONO_TYPE_BOOLEAN:
9956 case MONO_TYPE_CHAR:
9969 * mono_class_is_valid_enum:
9970 * @klass: An enum class to be validated
9972 * This method verify the required properties an enum should have.
9974 * Returns: TRUE if the informed enum class is valid
9976 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9977 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9978 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9980 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9981 MonoClassField * field;
9982 gpointer iter = NULL;
9983 gboolean found_base_field = FALSE;
9985 g_assert (klass->enumtype);
9986 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9987 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9991 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9994 while ((field = mono_class_get_fields (klass, &iter))) {
9995 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9996 if (found_base_field)
9998 found_base_field = TRUE;
9999 if (!mono_type_is_valid_enum_basetype (field->type))
10004 if (!found_base_field)
10007 if (klass->method.count > 0)
10014 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10016 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10020 * mono_class_setup_interface_id:
10022 * Initializes MonoClass::interface_id if required.
10024 * LOCKING: Acquires the loader lock.
10027 mono_class_setup_interface_id (MonoClass *class)
10029 mono_loader_lock ();
10030 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10031 class->interface_id = mono_get_unique_iid (class);
10032 mono_loader_unlock ();
10036 * mono_class_alloc_ext:
10038 * Allocate klass->ext if not already done.
10039 * LOCKING: Assumes the loader lock is held.
10042 mono_class_alloc_ext (MonoClass *klass)
10045 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10046 class_ext_size += sizeof (MonoClassExt);
10051 * mono_class_setup_interfaces:
10053 * Initialize class->interfaces/interfaces_count.
10054 * LOCKING: Acquires the loader lock.
10055 * This function can fail the type.
10058 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10060 int i, interface_count;
10061 MonoClass **interfaces;
10063 mono_error_init (error);
10065 if (klass->interfaces_inited)
10068 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10069 MonoType *args [1];
10071 /* generic IList, ICollection, IEnumerable */
10072 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10073 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10075 args [0] = &klass->element_class->byval_arg;
10076 interfaces [0] = mono_class_bind_generic_parameters (
10077 mono_defaults.generic_ilist_class, 1, args, FALSE);
10078 if (interface_count > 1)
10079 interfaces [1] = mono_class_bind_generic_parameters (
10080 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10081 } else if (klass->generic_class) {
10082 MonoClass *gklass = klass->generic_class->container_class;
10084 mono_class_setup_interfaces (gklass, error);
10085 if (!mono_error_ok (error)) {
10086 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10090 interface_count = gklass->interface_count;
10091 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10092 for (i = 0; i < interface_count; i++) {
10093 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10094 if (!mono_error_ok (error)) {
10095 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10100 interface_count = 0;
10104 mono_image_lock (klass->image);
10106 if (klass->interfaces_inited) {
10107 mono_image_unlock (klass->image);
10111 klass->interface_count = interface_count;
10112 klass->interfaces = interfaces;
10114 mono_memory_barrier ();
10116 klass->interfaces_inited = TRUE;
10118 mono_image_unlock (klass->image);
10122 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10124 MonoClass *class = field->parent;
10125 MonoImage *image = class->image;
10126 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10127 int field_idx = field - class->fields;
10129 mono_error_init (error);
10132 MonoClassField *gfield = >d->fields [field_idx];
10133 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10134 if (!mono_error_ok (error)) {
10135 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10136 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10140 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10141 if (!mono_error_ok (error)) {
10142 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10143 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10148 guint32 cols [MONO_FIELD_SIZE];
10149 MonoGenericContainer *container = NULL;
10150 int idx = class->field.first + field_idx;
10152 /*FIXME, in theory we do not lazy load SRE fields*/
10153 g_assert (!image_is_dynamic (image));
10155 if (class->generic_container) {
10156 container = class->generic_container;
10158 container = gtd->generic_container;
10159 g_assert (container);
10162 /* class->field.first and idx points into the fieldptr table */
10163 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10165 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10166 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10167 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10171 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10173 mono_metadata_decode_value (sig, &sig);
10174 /* FIELD signature == 0x06 */
10175 g_assert (*sig == 0x06);
10176 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10178 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10183 mono_field_resolve_flags (MonoClassField *field)
10185 MonoClass *class = field->parent;
10186 MonoImage *image = class->image;
10187 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10188 int field_idx = field - class->fields;
10192 MonoClassField *gfield = >d->fields [field_idx];
10193 return mono_field_get_flags (gfield);
10195 int idx = class->field.first + field_idx;
10197 /*FIXME, in theory we do not lazy load SRE fields*/
10198 g_assert (!image_is_dynamic (image));
10200 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10205 * mono_class_setup_basic_field_info:
10206 * @class: The class to initialize
10208 * Initializes the class->fields array of fields.
10209 * Aquires the loader lock.
10212 mono_class_setup_basic_field_info_locking (MonoClass *class)
10214 mono_loader_lock ();
10215 mono_class_setup_basic_field_info (class);
10216 mono_loader_unlock ();
10220 * mono_class_get_fields_lazy:
10221 * @klass: the MonoClass to act on
10223 * This routine is an iterator routine for retrieving the fields in a class.
10224 * Only minimal information about fields are loaded. Accessors must be used
10225 * for all MonoClassField returned.
10227 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10228 * iterate over all of the elements. When no more values are
10229 * available, the return value is NULL.
10231 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10234 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10236 MonoClassField* field;
10240 mono_class_setup_basic_field_info_locking (klass);
10241 if (!klass->fields)
10243 /* start from the first */
10244 if (klass->field.count) {
10245 return *iter = &klass->fields [0];
10253 if (field < &klass->fields [klass->field.count]) {
10254 return *iter = field;
10260 mono_class_full_name (MonoClass *klass)
10262 return mono_type_full_name (&klass->byval_arg);