2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* Function supplied by the runtime to find classes by name using information from the AOT file */
56 static MonoGetClassFromName get_class_from_name = NULL;
58 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
59 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
60 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
61 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
62 static int generic_array_methods (MonoClass *class);
63 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
65 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
66 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
67 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
68 static guint32 mono_field_resolve_flags (MonoClassField *field);
69 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
70 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
73 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
77 We use gclass recording to allow recursive system f types to be referenced by a parent.
79 Given the following type hierarchy:
81 class TextBox : TextBoxBase<TextBox> {}
82 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
83 class TextInput<T> : Input<T> where T: TextInput<T> {}
86 The runtime tries to load TextBoxBase<>.
87 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
88 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
89 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
91 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
92 at this point, iow, both are registered in the type map and both and a NULL parent. This means
93 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
95 To fix that what we do is to record all generic instantes created while resolving the parent of
96 any generic type definition and, after resolved, correct the parent field if needed.
99 static int record_gclass_instantiation;
100 static GSList *gclass_recorded_list;
101 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
104 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
107 enable_gclass_recording (void)
109 ++record_gclass_instantiation;
113 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
116 disable_gclass_recording (gclass_record_func func, void *user_data)
118 GSList **head = &gclass_recorded_list;
120 g_assert (record_gclass_instantiation > 0);
121 --record_gclass_instantiation;
124 GSList *node = *head;
125 if (func ((MonoClass*)node->data, user_data)) {
127 g_slist_free_1 (node);
133 /* We automatically discard all recorded gclasses when disabled. */
134 if (!record_gclass_instantiation && gclass_recorded_list) {
135 g_slist_free (gclass_recorded_list);
136 gclass_recorded_list = NULL;
141 * mono_class_from_typeref:
142 * @image: a MonoImage
143 * @type_token: a TypeRef token
145 * Creates the MonoClass* structure representing the type defined by
146 * the typeref token valid inside @image.
147 * Returns: the MonoClass* representing the typeref token, NULL ifcould
151 mono_class_from_typeref (MonoImage *image, guint32 type_token)
154 guint32 cols [MONO_TYPEREF_SIZE];
155 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
157 const char *name, *nspace;
161 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, &error)) {
162 mono_trace_warning (MONO_TRACE_TYPE, "Failed to resolve typeref from %s due to '%s'", image->name, mono_error_get_message (&error));
166 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
168 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
169 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
171 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
172 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
173 case MONO_RESOLTION_SCOPE_MODULE:
175 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
176 This is not the observed behavior of existing implementations.
177 The defacto behavior is that it's just a typedef in disguise.
179 /* a typedef in disguise */
180 return mono_class_from_name (image, nspace, name);
181 case MONO_RESOLTION_SCOPE_MODULEREF:
182 module = mono_image_load_module (image, idx);
184 return mono_class_from_name (module, nspace, name);
186 char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
189 human_name = mono_stringify_assembly_name (&image->assembly->aname);
190 mono_loader_set_error_type_load (msg, human_name);
196 case MONO_RESOLTION_SCOPE_TYPEREF: {
197 MonoClass *enclosing;
200 if (idx == mono_metadata_token_index (type_token)) {
201 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token));
205 enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
209 if (enclosing->nested_classes_inited && enclosing->ext) {
210 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
211 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
213 if (strcmp (res->name, name) == 0)
217 /* Don't call mono_class_init as we might've been called by it recursively */
218 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
220 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
221 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
222 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
224 if (strcmp (nname, name) == 0) {
225 MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
226 if (!mono_error_ok (&error)) {
227 mono_loader_set_error_from_mono_error (&error);
228 mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
234 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
237 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
240 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
244 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
245 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
249 if (!image->references || !image->references [idx - 1])
250 mono_assembly_load_reference (image, idx - 1);
251 g_assert (image->references [idx - 1]);
253 /* If the assembly did not load, register this as a type load exception */
254 if (image->references [idx - 1] == REFERENCE_MISSING){
255 MonoAssemblyName aname;
258 mono_assembly_get_assemblyref (image, idx - 1, &aname);
259 human_name = mono_stringify_assembly_name (&aname);
260 mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
266 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
271 mono_image_memdup (MonoImage *image, void *data, guint size)
273 void *res = mono_image_alloc (image, size);
274 memcpy (res, data, size);
278 /* Copy everything mono_metadata_free_array free. */
280 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
283 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
285 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
287 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
289 a = g_memdup (a, sizeof (MonoArrayType));
291 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
293 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
298 /* Copy everything mono_metadata_free_method_signature free. */
300 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
304 sig = mono_metadata_signature_dup_full (image, sig);
306 sig->ret = mono_metadata_type_dup (image, sig->ret);
307 for (i = 0; i < sig->param_count; ++i)
308 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
314 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
316 MonoAssembly *ta = klass->image->assembly;
319 name = mono_stringify_assembly_name (&ta->aname);
320 g_string_append_printf (str, ", %s", name);
325 mono_type_name_check_byref (MonoType *type, GString *str)
328 g_string_append_c (str, '&');
332 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
333 MonoTypeNameFormat format)
337 switch (type->type) {
338 case MONO_TYPE_ARRAY: {
339 int i, rank = type->data.array->rank;
340 MonoTypeNameFormat nested_format;
342 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
343 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
345 mono_type_get_name_recurse (
346 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
347 g_string_append_c (str, '[');
349 g_string_append_c (str, '*');
350 for (i = 1; i < rank; i++)
351 g_string_append_c (str, ',');
352 g_string_append_c (str, ']');
354 mono_type_name_check_byref (type, str);
356 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
357 _mono_type_get_assembly_name (type->data.array->eklass, str);
360 case MONO_TYPE_SZARRAY: {
361 MonoTypeNameFormat nested_format;
363 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
364 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
366 mono_type_get_name_recurse (
367 &type->data.klass->byval_arg, str, FALSE, nested_format);
368 g_string_append (str, "[]");
370 mono_type_name_check_byref (type, str);
372 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
373 _mono_type_get_assembly_name (type->data.klass, str);
376 case MONO_TYPE_PTR: {
377 MonoTypeNameFormat nested_format;
379 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
380 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
382 mono_type_get_name_recurse (
383 type->data.type, str, FALSE, nested_format);
384 g_string_append_c (str, '*');
386 mono_type_name_check_byref (type, str);
388 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
389 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
394 if (!mono_generic_param_info (type->data.generic_param))
395 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
397 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
399 mono_type_name_check_byref (type, str);
403 klass = mono_class_from_mono_type (type);
404 if (klass->nested_in) {
405 mono_type_get_name_recurse (
406 &klass->nested_in->byval_arg, str, TRUE, format);
407 if (format == MONO_TYPE_NAME_FORMAT_IL)
408 g_string_append_c (str, '.');
410 g_string_append_c (str, '+');
411 } else if (*klass->name_space) {
412 g_string_append (str, klass->name_space);
413 g_string_append_c (str, '.');
415 if (format == MONO_TYPE_NAME_FORMAT_IL) {
416 char *s = strchr (klass->name, '`');
417 int len = s ? s - klass->name : strlen (klass->name);
419 g_string_append_len (str, klass->name, len);
421 g_string_append (str, klass->name);
424 if (klass->generic_class) {
425 MonoGenericClass *gclass = klass->generic_class;
426 MonoGenericInst *inst = gclass->context.class_inst;
427 MonoTypeNameFormat nested_format;
430 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
431 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
433 if (format == MONO_TYPE_NAME_FORMAT_IL)
434 g_string_append_c (str, '<');
436 g_string_append_c (str, '[');
437 for (i = 0; i < inst->type_argc; i++) {
438 MonoType *t = inst->type_argv [i];
441 g_string_append_c (str, ',');
442 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
443 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
444 g_string_append_c (str, '[');
445 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
446 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
447 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
448 g_string_append_c (str, ']');
450 if (format == MONO_TYPE_NAME_FORMAT_IL)
451 g_string_append_c (str, '>');
453 g_string_append_c (str, ']');
454 } else if (klass->generic_container &&
455 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
456 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
459 if (format == MONO_TYPE_NAME_FORMAT_IL)
460 g_string_append_c (str, '<');
462 g_string_append_c (str, '[');
463 for (i = 0; i < klass->generic_container->type_argc; i++) {
465 g_string_append_c (str, ',');
466 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
468 if (format == MONO_TYPE_NAME_FORMAT_IL)
469 g_string_append_c (str, '>');
471 g_string_append_c (str, ']');
474 mono_type_name_check_byref (type, str);
476 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
477 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
478 _mono_type_get_assembly_name (klass, str);
484 * mono_type_get_name_full:
486 * @format: the format for the return string.
489 * Returns: the string representation in a number of formats:
491 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
492 * returned in the formatrequired by System.Reflection, this is the
493 * inverse of mono_reflection_parse_type ().
495 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
496 * be used by the IL assembler.
498 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
500 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
503 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
507 result = g_string_new ("");
509 mono_type_get_name_recurse (type, result, FALSE, format);
511 return g_string_free (result, FALSE);
515 * mono_type_get_full_name:
518 * Returns: the string representation for type as required by System.Reflection.
519 * The inverse of mono_reflection_parse_type ().
522 mono_type_get_full_name (MonoClass *class)
524 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
528 * mono_type_get_name:
531 * Returns: the string representation for type as it would be represented in IL code.
534 mono_type_get_name (MonoType *type)
536 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
540 * mono_type_get_underlying_type:
543 * Returns: the MonoType for the underlying integer type if @type
544 * is an enum and byref is false, otherwise the type itself.
547 mono_type_get_underlying_type (MonoType *type)
549 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
550 return mono_class_enum_basetype (type->data.klass);
551 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
552 return mono_class_enum_basetype (type->data.generic_class->container_class);
557 * mono_class_is_open_constructed_type:
560 * Returns TRUE if type represents a generics open constructed type.
561 * IOW, not all type parameters required for the instantiation have
562 * been provided or it's a generic type definition.
564 * An open constructed type means it's a non realizable type. Not to
565 * be mixed up with an abstract type - we can't cast or dispatch to
566 * an open type, for example.
569 mono_class_is_open_constructed_type (MonoType *t)
575 case MONO_TYPE_SZARRAY:
576 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
577 case MONO_TYPE_ARRAY:
578 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
580 return mono_class_is_open_constructed_type (t->data.type);
581 case MONO_TYPE_GENERICINST:
582 return t->data.generic_class->context.class_inst->is_open;
583 case MONO_TYPE_CLASS:
584 case MONO_TYPE_VALUETYPE:
585 return t->data.klass->generic_container != NULL;
592 This is a simple function to catch the most common bad instances of generic types.
593 Specially those that might lead to further failures in the runtime.
596 is_valid_generic_argument (MonoType *type)
598 switch (type->type) {
600 //case MONO_TYPE_TYPEDBYREF:
607 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
609 mono_error_init (error);
611 switch (type->type) {
612 case MONO_TYPE_MVAR: {
614 int num = mono_type_get_generic_param_num (type);
615 MonoGenericInst *inst = context->method_inst;
616 if (!inst || !inst->type_argv)
618 if (num >= inst->type_argc) {
619 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
620 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
621 num, info ? info->name : "", inst->type_argc);
625 if (!is_valid_generic_argument (inst->type_argv [num])) {
626 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
627 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
628 num, info ? info->name : "", inst->type_argv [num]->type);
632 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
633 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
634 * ->byref and ->attrs from @type are propagated to the returned type.
636 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
637 nt->byref = type->byref;
638 nt->attrs = type->attrs;
641 case MONO_TYPE_VAR: {
643 int num = mono_type_get_generic_param_num (type);
644 MonoGenericInst *inst = context->class_inst;
647 if (num >= inst->type_argc) {
648 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
649 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
650 num, info ? info->name : "", inst->type_argc);
653 if (!is_valid_generic_argument (inst->type_argv [num])) {
654 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
655 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
656 num, info ? info->name : "", inst->type_argv [num]->type);
659 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
660 nt->byref = type->byref;
661 nt->attrs = type->attrs;
664 case MONO_TYPE_SZARRAY: {
665 MonoClass *eclass = type->data.klass;
666 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
667 if (!inflated || !mono_error_ok (error))
669 nt = mono_metadata_type_dup (image, type);
670 nt->data.klass = mono_class_from_mono_type (inflated);
671 mono_metadata_free_type (inflated);
674 case MONO_TYPE_ARRAY: {
675 MonoClass *eclass = type->data.array->eklass;
676 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
677 if (!inflated || !mono_error_ok (error))
679 nt = mono_metadata_type_dup (image, type);
680 nt->data.array->eklass = mono_class_from_mono_type (inflated);
681 mono_metadata_free_type (inflated);
684 case MONO_TYPE_GENERICINST: {
685 MonoGenericClass *gclass = type->data.generic_class;
686 MonoGenericInst *inst;
688 if (!gclass->context.class_inst->is_open)
691 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
692 if (!mono_error_ok (error))
694 if (inst != gclass->context.class_inst)
695 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
697 if (gclass == type->data.generic_class)
700 nt = mono_metadata_type_dup (image, type);
701 nt->data.generic_class = gclass;
704 case MONO_TYPE_CLASS:
705 case MONO_TYPE_VALUETYPE: {
706 MonoClass *klass = type->data.klass;
707 MonoGenericContainer *container = klass->generic_container;
708 MonoGenericInst *inst;
709 MonoGenericClass *gclass = NULL;
715 /* We can't use context->class_inst directly, since it can have more elements */
716 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
717 if (!mono_error_ok (error))
719 if (inst == container->context.class_inst)
722 gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
724 nt = mono_metadata_type_dup (image, type);
725 nt->type = MONO_TYPE_GENERICINST;
726 nt->data.generic_class = gclass;
736 mono_generic_class_get_context (MonoGenericClass *gclass)
738 return &gclass->context;
742 mono_class_get_context (MonoClass *class)
744 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
748 * mono_class_get_generic_container:
750 * Return the generic container of KLASS which should be a generic type definition.
752 MonoGenericContainer*
753 mono_class_get_generic_container (MonoClass *klass)
755 g_assert (klass->is_generic);
757 return klass->generic_container;
761 * mono_class_get_generic_class:
763 * Return the MonoGenericClass of KLASS, which should be a generic instance.
766 mono_class_get_generic_class (MonoClass *klass)
768 g_assert (klass->is_inflated);
770 return klass->generic_class;
774 * mono_class_inflate_generic_type_with_mempool:
775 * @mempool: a mempool
777 * @context: a generics context
778 * @error: error context
780 * The same as mono_class_inflate_generic_type, but allocates the MonoType
781 * from mempool if it is non-NULL. If it is NULL, the MonoType is
782 * allocated on the heap and is owned by the caller.
783 * The returned type can potentially be the same as TYPE, so it should not be
784 * modified by the caller, and it should be freed using mono_metadata_free_type ().
787 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
789 MonoType *inflated = NULL;
790 mono_error_init (error);
793 inflated = inflate_generic_type (image, type, context, error);
794 if (!mono_error_ok (error))
798 MonoType *shared = mono_metadata_get_shared_type (type);
803 return mono_metadata_type_dup (image, type);
807 mono_stats.inflated_type_count++;
812 * mono_class_inflate_generic_type:
814 * @context: a generics context
816 * If @type is a generic type and @context is not NULL, instantiate it using the
817 * generics context @context.
819 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
820 * on the heap and is owned by the caller. Returns NULL on error.
822 * @deprecated Please use mono_class_inflate_generic_type_checked instead
825 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
829 result = mono_class_inflate_generic_type_checked (type, context, &error);
831 if (!mono_error_ok (&error)) {
832 mono_error_cleanup (&error);
839 * mono_class_inflate_generic_type:
841 * @context: a generics context
842 * @error: error context to use
844 * If @type is a generic type and @context is not NULL, instantiate it using the
845 * generics context @context.
847 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
848 * on the heap and is owned by the caller.
851 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
853 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
857 * mono_class_inflate_generic_type_no_copy:
859 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
863 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
865 MonoType *inflated = NULL;
867 mono_error_init (error);
869 inflated = inflate_generic_type (image, type, context, error);
870 if (!mono_error_ok (error))
877 mono_stats.inflated_type_count++;
882 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
887 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
888 if (!mono_error_ok (error))
891 res = mono_class_from_mono_type (inflated);
892 mono_metadata_free_type (inflated);
897 * mono_class_inflate_generic_class:
899 * Inflate the class GKLASS with CONTEXT.
902 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
907 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
908 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
915 static MonoGenericContext
916 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
918 MonoGenericInst *class_inst = NULL;
919 MonoGenericInst *method_inst = NULL;
920 MonoGenericContext res = { NULL, NULL };
922 mono_error_init (error);
924 if (context->class_inst) {
925 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
926 if (!mono_error_ok (error))
930 if (context->method_inst) {
931 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
932 if (!mono_error_ok (error))
936 res.class_inst = class_inst;
937 res.method_inst = method_inst;
943 * mono_class_inflate_generic_method:
944 * @method: a generic method
945 * @context: a generics context
947 * Instantiate the generic method @method using the generics context @context.
949 * Returns: the new instantiated method
952 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
954 return mono_class_inflate_generic_method_full (method, NULL, context);
958 * mono_class_inflate_generic_method_full:
960 * Instantiate method @method with the generic context @context.
961 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
962 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
965 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
968 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
969 if (!mono_error_ok (&error))
970 /*FIXME do proper error handling - on this case, kill this function. */
971 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
977 * mono_class_inflate_generic_method_full_checked:
978 * Same as mono_class_inflate_generic_method_full but return failure using @error.
981 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
984 MonoMethodInflated *iresult, *cached;
985 MonoMethodSignature *sig;
986 MonoGenericContext tmp_context;
987 gboolean is_mb_open = FALSE;
989 mono_error_init (error);
991 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
992 while (method->is_inflated) {
993 MonoGenericContext *method_context = mono_method_get_context (method);
994 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
996 tmp_context = inflate_generic_context (method_context, context, error);
997 if (!mono_error_ok (error))
999 context = &tmp_context;
1001 if (mono_metadata_generic_context_equal (method_context, context))
1004 method = imethod->declaring;
1008 * A method only needs to be inflated if the context has argument for which it is
1011 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1012 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1015 if (!((method->is_generic && context->method_inst) ||
1016 (method->klass->generic_container && context->class_inst)))
1020 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1021 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1022 * This is opposite to the way non-SRE MethodInfos behave.
1024 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1026 * void Example<T> () {
1030 * In Example, the method token must be encoded as: "void Example<!!0>()"
1032 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1033 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1035 * On the other hand, inflating a non-SRE generic method with its own arguments should
1036 * return itself. For example:
1038 * MethodInfo m = ... //m is a generic method definition
1039 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1042 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1043 * what happens with regular methods.
1045 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1046 * everything should behave like a regular type or method.
1049 is_mb_open = method->is_generic &&
1050 method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1051 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1053 iresult = g_new0 (MonoMethodInflated, 1);
1054 iresult->context = *context;
1055 iresult->declaring = method;
1056 iresult->method.method.is_mb_open = is_mb_open;
1058 if (!context->method_inst && method->is_generic)
1059 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1061 if (!context->class_inst) {
1062 g_assert (!iresult->declaring->klass->generic_class);
1063 if (iresult->declaring->klass->generic_container)
1064 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1065 else if (iresult->declaring->klass->generic_class)
1066 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1069 mono_loader_lock ();
1070 cached = mono_method_inflated_lookup (iresult, FALSE);
1072 mono_loader_unlock ();
1074 return (MonoMethod*)cached;
1077 mono_stats.inflated_method_count++;
1079 inflated_methods_size += sizeof (MonoMethodInflated);
1081 sig = mono_method_signature (method);
1083 char *name = mono_type_get_full_name (method->klass);
1084 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1090 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1092 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1095 result = (MonoMethod *) iresult;
1096 result->is_inflated = TRUE;
1097 result->is_generic = FALSE;
1098 result->sre_method = FALSE;
1099 result->signature = NULL;
1100 result->is_mb_open = is_mb_open;
1102 if (!context->method_inst) {
1103 /* Set the generic_container of the result to the generic_container of method */
1104 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1106 if (generic_container) {
1107 result->is_generic = 1;
1108 mono_method_set_generic_container (result, generic_container);
1112 if (!klass_hint || !klass_hint->generic_class ||
1113 klass_hint->generic_class->container_class != method->klass ||
1114 klass_hint->generic_class->context.class_inst != context->class_inst)
1117 if (method->klass->generic_container)
1118 result->klass = klass_hint;
1120 if (!result->klass) {
1121 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1122 if (!mono_error_ok (error))
1125 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1127 mono_metadata_free_type (inflated);
1131 * FIXME: This should hold, but it doesn't:
1133 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1134 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1135 * g_assert (result->is_generic);
1138 * Fixing this here causes other things to break, hence a very
1139 * ugly hack in mini-trampolines.c - see
1140 * is_generic_method_definition().
1143 mono_method_inflated_lookup (iresult, TRUE);
1144 mono_loader_unlock ();
1148 mono_loader_unlock ();
1154 * mono_get_inflated_method:
1156 * Obsolete. We keep it around since it's mentioned in the public API.
1159 mono_get_inflated_method (MonoMethod *method)
1165 * mono_method_get_context_general:
1167 * @uninflated: handle uninflated methods?
1169 * Returns the generic context of a method or NULL if it doesn't have
1170 * one. For an inflated method that's the context stored in the
1171 * method. Otherwise it's in the method's generic container or in the
1172 * generic container of the method's class.
1175 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1177 if (method->is_inflated) {
1178 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1179 return &imethod->context;
1183 if (method->is_generic)
1184 return &(mono_method_get_generic_container (method)->context);
1185 if (method->klass->generic_container)
1186 return &method->klass->generic_container->context;
1191 * mono_method_get_context:
1194 * Returns the generic context for method if it's inflated, otherwise
1198 mono_method_get_context (MonoMethod *method)
1200 return mono_method_get_context_general (method, FALSE);
1204 * mono_method_get_generic_container:
1206 * Returns the generic container of METHOD, which should be a generic method definition.
1207 * Returns NULL if METHOD is not a generic method definition.
1208 * LOCKING: Acquires the loader lock.
1210 MonoGenericContainer*
1211 mono_method_get_generic_container (MonoMethod *method)
1213 MonoGenericContainer *container;
1215 if (!method->is_generic)
1218 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1219 g_assert (container);
1225 * mono_method_set_generic_container:
1227 * Sets the generic container of METHOD to CONTAINER.
1228 * LOCKING: Acquires the loader lock.
1231 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1233 g_assert (method->is_generic);
1235 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1239 * mono_class_find_enum_basetype:
1240 * @class: The enum class
1242 * Determine the basetype of an enum by iterating through its fields. We do this
1243 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1246 mono_class_find_enum_basetype (MonoClass *class)
1248 MonoGenericContainer *container = NULL;
1249 MonoImage *m = class->image;
1250 const int top = class->field.count;
1253 g_assert (class->enumtype);
1255 if (class->generic_container)
1256 container = class->generic_container;
1257 else if (class->generic_class) {
1258 MonoClass *gklass = class->generic_class->container_class;
1260 container = gklass->generic_container;
1261 g_assert (container);
1265 * Fetch all the field information.
1267 for (i = 0; i < top; i++){
1269 guint32 cols [MONO_FIELD_SIZE];
1270 int idx = class->field.first + i;
1273 /* class->field.first and idx points into the fieldptr table */
1274 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1276 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1279 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1282 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1283 mono_metadata_decode_value (sig, &sig);
1284 /* FIELD signature == 0x06 */
1288 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1291 if (class->generic_class) {
1292 //FIXME do we leak here?
1293 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1294 ftype->attrs = cols [MONO_FIELD_FLAGS];
1304 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1307 mono_type_has_exceptions (MonoType *type)
1309 switch (type->type) {
1310 case MONO_TYPE_CLASS:
1311 case MONO_TYPE_VALUETYPE:
1312 case MONO_TYPE_SZARRAY:
1313 return type->data.klass->exception_type;
1314 case MONO_TYPE_ARRAY:
1315 return type->data.array->eklass->exception_type;
1316 case MONO_TYPE_GENERICINST:
1317 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1325 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1329 mono_class_alloc (MonoClass *class, int size)
1331 if (class->generic_class)
1332 return mono_image_set_alloc (class->generic_class->owner, size);
1334 return mono_image_alloc (class->image, size);
1338 mono_class_alloc0 (MonoClass *class, int size)
1342 res = mono_class_alloc (class, size);
1343 memset (res, 0, size);
1347 #define mono_class_new0(class,struct_type, n_structs) \
1348 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1351 * mono_class_setup_basic_field_info:
1352 * @class: The class to initialize
1354 * Initializes the class->fields.
1355 * LOCKING: Assumes the loader lock is held.
1358 mono_class_setup_basic_field_info (MonoClass *class)
1360 MonoClassField *field;
1368 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1369 image = class->image;
1370 top = class->field.count;
1372 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1374 * This happens when a generic instance of an unfinished generic typebuilder
1375 * is used as an element type for creating an array type. We can't initialize
1376 * the fields of this class using the fields of gklass, since gklass is not
1377 * finished yet, fields could be added to it later.
1383 mono_class_setup_basic_field_info (gtd);
1385 top = gtd->field.count;
1386 class->field.first = gtd->field.first;
1387 class->field.count = gtd->field.count;
1390 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1393 * Fetch all the field information.
1395 for (i = 0; i < top; i++){
1396 field = &class->fields [i];
1397 field->parent = class;
1400 field->name = mono_field_get_name (>d->fields [i]);
1402 int idx = class->field.first + i;
1403 /* class->field.first and idx points into the fieldptr table */
1404 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1405 /* The name is needed for fieldrefs */
1406 field->name = mono_metadata_string_heap (image, name_idx);
1412 * mono_class_setup_fields:
1413 * @class: The class to initialize
1415 * Initializes the class->fields.
1416 * LOCKING: Assumes the loader lock is held.
1419 mono_class_setup_fields (MonoClass *class)
1422 MonoImage *m = class->image;
1424 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1425 int i, blittable = TRUE;
1426 guint32 real_size = 0;
1427 guint32 packing_size = 0;
1428 gboolean explicit_size;
1429 MonoClassField *field;
1430 MonoGenericContainer *container = NULL;
1431 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1434 * FIXME: We have a race condition here. It's possible that this function returns
1435 * to its caller with `instance_size` set to `0` instead of the actual size. This
1436 * is not a problem when the function is called recursively on the same class,
1437 * because the size will be initialized by the outer invocation. What follows is a
1438 * description of how it can occur in other cases, too. There it is a problem,
1439 * because it can lead to the GC being asked to allocate an object of size `0`,
1440 * which SGen chokes on. The race condition is triggered infrequently by
1441 * `tests/sgen-suspend.cs`.
1443 * This function is called for a class whenever one of its subclasses is inited.
1444 * For example, it's called for every subclass of Object. What it does is this:
1446 * if (class->setup_fields_called)
1449 * class->instance_size = 0;
1451 * class->setup_fields_called = 1;
1452 * ... critical point
1453 * class->instance_size = actual_instance_size;
1455 * The last two steps are sometimes reversed, but that only changes the way in which
1456 * the race condition works.
1458 * Assume thread A goes through this function and makes it to the critical point.
1459 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1460 * immediately, but `instance_size` is incorrect.
1462 * The other case looks like this:
1464 * if (class->setup_fields_called)
1466 * ... critical point X
1467 * class->instance_size = 0;
1468 * ... critical point Y
1469 * class->instance_size = actual_instance_size;
1471 * class->setup_fields_called = 1;
1473 * Assume thread A goes through the function and makes it to critical point X. Now
1474 * thread B runs through the whole of the function, returning, assuming
1475 * `instance_size` is set. At that point thread A gets to run and makes it to
1476 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1479 if (class->setup_fields_called)
1482 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1484 * This happens when a generic instance of an unfinished generic typebuilder
1485 * is used as an element type for creating an array type. We can't initialize
1486 * the fields of this class using the fields of gklass, since gklass is not
1487 * finished yet, fields could be added to it later.
1492 mono_class_setup_basic_field_info (class);
1493 top = class->field.count;
1496 mono_class_setup_fields (gtd);
1497 if (gtd->exception_type) {
1498 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1503 class->instance_size = 0;
1505 class->sizes.class_size = 0;
1507 if (class->parent) {
1508 /* For generic instances, class->parent might not have been initialized */
1509 mono_class_init (class->parent);
1510 if (!class->parent->size_inited) {
1511 mono_class_setup_fields (class->parent);
1512 if (class->parent->exception_type) {
1513 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1517 class->instance_size += class->parent->instance_size;
1518 class->min_align = class->parent->min_align;
1519 /* we use |= since it may have been set already */
1520 class->has_references |= class->parent->has_references;
1521 blittable = class->parent->blittable;
1523 class->instance_size = sizeof (MonoObject);
1524 class->min_align = 1;
1527 /* We can't really enable 16 bytes alignment until the GC supports it.
1528 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1529 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1530 Bug #506144 is an example of this issue.
1532 if (class->simd_type)
1533 class->min_align = 16;
1535 /* Get the real size */
1536 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1538 if (explicit_size) {
1539 if ((packing_size & 0xfffffff0) != 0) {
1540 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1541 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1544 class->packing_size = packing_size;
1545 real_size += class->instance_size;
1549 if (explicit_size && real_size) {
1550 class->instance_size = MAX (real_size, class->instance_size);
1552 class->blittable = blittable;
1553 mono_memory_barrier ();
1554 class->size_inited = 1;
1555 class->fields_inited = 1;
1556 class->setup_fields_called = 1;
1560 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1563 /* Prevent infinite loops if the class references itself */
1564 class->setup_fields_called = 1;
1566 if (class->generic_container) {
1567 container = class->generic_container;
1569 container = gtd->generic_container;
1570 g_assert (container);
1574 * Fetch all the field information.
1576 for (i = 0; i < top; i++){
1577 int idx = class->field.first + i;
1578 field = &class->fields [i];
1580 field->parent = class;
1583 mono_field_resolve_type (field, &error);
1584 if (!mono_error_ok (&error)) {
1585 /*mono_field_resolve_type already failed class*/
1586 mono_error_cleanup (&error);
1590 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1591 g_assert (field->type);
1594 if (mono_field_is_deleted (field))
1597 MonoClassField *gfield = >d->fields [i];
1598 field->offset = gfield->offset;
1600 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1602 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1603 field->offset = offset;
1605 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1606 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1609 if (field->offset < -1) { /*-1 is used to encode special static fields */
1610 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1616 /* Only do these checks if we still think this type is blittable */
1617 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1618 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1621 MonoClass *field_class = mono_class_from_mono_type (field->type);
1623 mono_class_setup_fields (field_class);
1624 if (field_class->exception_type) {
1625 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1629 if (!field_class || !field_class->blittable)
1634 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1635 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1636 blittable = class->element_class->blittable;
1639 if (mono_type_has_exceptions (field->type)) {
1640 char *class_name = mono_type_get_full_name (class);
1641 char *type_name = mono_type_full_name (field->type);
1643 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1644 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1645 g_free (class_name);
1649 /* The def_value of fields is compute lazily during vtable creation */
1652 if (class == mono_defaults.string_class)
1655 class->blittable = blittable;
1657 if (class->enumtype && !mono_class_enum_basetype (class)) {
1658 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1661 if (explicit_size && real_size) {
1662 class->instance_size = MAX (real_size, class->instance_size);
1665 if (class->exception_type)
1667 mono_class_layout_fields (class);
1669 /*valuetypes can't be neither bigger than 1Mb or empty. */
1670 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1671 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1673 mono_memory_barrier ();
1674 class->fields_inited = 1;
1678 * mono_class_setup_fields_locking:
1679 * @class: The class to initialize
1681 * Initializes the class->fields array of fields.
1682 * Aquires the loader lock.
1685 mono_class_setup_fields_locking (MonoClass *class)
1687 /* This can be checked without locks */
1688 if (class->fields_inited)
1690 mono_loader_lock ();
1691 mono_class_setup_fields (class);
1692 mono_loader_unlock ();
1696 * mono_class_has_references:
1698 * Returns whenever @klass->has_references is set, initializing it if needed.
1699 * Aquires the loader lock.
1702 mono_class_has_references (MonoClass *klass)
1704 if (klass->init_pending) {
1705 /* Be conservative */
1708 mono_class_init (klass);
1710 return klass->has_references;
1715 * mono_type_get_basic_type_from_generic:
1718 * Returns a closed type corresponding to the possibly open type
1722 mono_type_get_basic_type_from_generic (MonoType *type)
1724 /* When we do generic sharing we let type variables stand for reference types. */
1725 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1726 return &mono_defaults.object_class->byval_arg;
1731 * mono_class_layout_fields:
1734 * Compute the placement of fields inside an object or struct, according to
1735 * the layout rules and set the following fields in @class:
1736 * - has_references (if the class contains instance references firled or structs that contain references)
1737 * - has_static_refs (same, but for static fields)
1738 * - instance_size (size of the object in memory)
1739 * - class_size (size needed for the static fields)
1740 * - size_inited (flag set when the instance_size is set)
1742 * LOCKING: this is supposed to be called with the loader lock held.
1745 mono_class_layout_fields (MonoClass *class)
1748 const int top = class->field.count;
1749 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1750 guint32 pass, passes, real_size;
1751 gboolean gc_aware_layout = FALSE;
1752 MonoClassField *field;
1755 * When we do generic sharing we need to have layout
1756 * information for open generic classes (either with a generic
1757 * context containing type variables or with a generic
1758 * container), so we don't return in that case anymore.
1762 * Enable GC aware auto layout: in this mode, reference
1763 * fields are grouped together inside objects, increasing collector
1765 * Requires that all classes whose layout is known to native code be annotated
1766 * with [StructLayout (LayoutKind.Sequential)]
1767 * Value types have gc_aware_layout disabled by default, as per
1768 * what the default is for other runtimes.
1770 /* corlib is missing [StructLayout] directives in many places */
1771 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1772 if (!class->valuetype)
1773 gc_aware_layout = TRUE;
1776 /* Compute klass->has_references */
1778 * Process non-static fields first, since static fields might recursively
1779 * refer to the class itself.
1781 for (i = 0; i < top; i++) {
1784 field = &class->fields [i];
1786 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1787 ftype = mono_type_get_underlying_type (field->type);
1788 ftype = mono_type_get_basic_type_from_generic (ftype);
1789 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1790 class->has_references = TRUE;
1794 for (i = 0; i < top; i++) {
1797 field = &class->fields [i];
1799 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1800 ftype = mono_type_get_underlying_type (field->type);
1801 ftype = mono_type_get_basic_type_from_generic (ftype);
1802 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1803 class->has_static_refs = TRUE;
1807 for (i = 0; i < top; i++) {
1810 field = &class->fields [i];
1812 ftype = mono_type_get_underlying_type (field->type);
1813 ftype = mono_type_get_basic_type_from_generic (ftype);
1814 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1815 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1816 class->has_static_refs = TRUE;
1818 class->has_references = TRUE;
1823 * Compute field layout and total size (not considering static fields)
1827 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1828 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1830 if (gc_aware_layout)
1835 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1838 if (class->parent) {
1839 mono_class_setup_fields (class->parent);
1840 if (class->parent->exception_type) {
1841 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1844 real_size = class->parent->instance_size;
1846 real_size = sizeof (MonoObject);
1849 for (pass = 0; pass < passes; ++pass) {
1850 for (i = 0; i < top; i++){
1855 field = &class->fields [i];
1857 if (mono_field_is_deleted (field))
1859 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1862 ftype = mono_type_get_underlying_type (field->type);
1863 ftype = mono_type_get_basic_type_from_generic (ftype);
1864 if (gc_aware_layout) {
1865 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1874 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1875 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1876 /* This field is a hack inserted by MCS to empty structures */
1880 size = mono_type_size (field->type, &align);
1882 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1883 align = class->packing_size ? MIN (class->packing_size, align): align;
1884 /* if the field has managed references, we need to force-align it
1887 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1888 align = MAX (align, sizeof (gpointer));
1890 class->min_align = MAX (align, class->min_align);
1891 field->offset = real_size;
1893 field->offset += align - 1;
1894 field->offset &= ~(align - 1);
1896 /*TypeBuilders produce all sort of weird things*/
1897 g_assert (class->image->dynamic || field->offset > 0);
1898 real_size = field->offset + size;
1901 class->instance_size = MAX (real_size, class->instance_size);
1903 if (class->instance_size & (class->min_align - 1)) {
1904 class->instance_size += class->min_align - 1;
1905 class->instance_size &= ~(class->min_align - 1);
1909 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1911 for (i = 0; i < top; i++) {
1916 field = &class->fields [i];
1919 * There must be info about all the fields in a type if it
1920 * uses explicit layout.
1923 if (mono_field_is_deleted (field))
1925 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1928 size = mono_type_size (field->type, &align);
1929 align = class->packing_size ? MIN (class->packing_size, align): align;
1930 class->min_align = MAX (align, class->min_align);
1933 * When we get here, field->offset is already set by the
1934 * loader (for either runtime fields or fields loaded from metadata).
1935 * The offset is from the start of the object: this works for both
1936 * classes and valuetypes.
1938 field->offset += sizeof (MonoObject);
1939 ftype = mono_type_get_underlying_type (field->type);
1940 ftype = mono_type_get_basic_type_from_generic (ftype);
1941 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1942 if (field->offset % sizeof (gpointer)) {
1943 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1950 real_size = MAX (real_size, size + field->offset);
1952 class->instance_size = MAX (real_size, class->instance_size);
1953 if (class->instance_size & (class->min_align - 1)) {
1954 class->instance_size += class->min_align - 1;
1955 class->instance_size &= ~(class->min_align - 1);
1960 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1962 * For small structs, set min_align to at least the struct size to improve
1963 * performance, and since the JIT memset/memcpy code assumes this and generates
1964 * unaligned accesses otherwise. See #78990 for a testcase.
1966 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1967 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1970 mono_memory_barrier ();
1971 class->size_inited = 1;
1974 * Compute static field layout and size
1976 for (i = 0; i < top; i++){
1980 field = &class->fields [i];
1982 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1984 if (mono_field_is_deleted (field))
1987 if (mono_type_has_exceptions (field->type)) {
1988 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1992 size = mono_type_size (field->type, &align);
1993 field->offset = class->sizes.class_size;
1994 /*align is always non-zero here*/
1995 field->offset += align - 1;
1996 field->offset &= ~(align - 1);
1997 class->sizes.class_size = field->offset + size;
2002 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2006 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2007 method->klass = class;
2008 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2009 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2010 method->signature = sig;
2011 method->name = name;
2014 if (name [0] == '.') {
2015 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2017 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2023 * mono_class_setup_methods:
2026 * Initializes the 'methods' array in the klass.
2027 * Calling this method should be avoided if possible since it allocates a lot
2028 * of long-living MonoMethod structures.
2029 * Methods belonging to an interface are assigned a sequential slot starting
2032 * On failure this function sets class->exception_type
2035 mono_class_setup_methods (MonoClass *class)
2038 MonoMethod **methods;
2043 mono_loader_lock ();
2045 if (class->methods) {
2046 mono_loader_unlock ();
2050 if (class->generic_class) {
2052 MonoClass *gklass = class->generic_class->container_class;
2054 mono_class_init (gklass);
2055 if (!gklass->exception_type)
2056 mono_class_setup_methods (gklass);
2057 if (gklass->exception_type) {
2058 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2059 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2060 mono_loader_unlock ();
2064 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2065 class->method.count = gklass->method.count;
2066 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2068 for (i = 0; i < class->method.count; i++) {
2069 methods [i] = mono_class_inflate_generic_method_full_checked (
2070 gklass->methods [i], class, mono_class_get_context (class), &error);
2071 if (!mono_error_ok (&error)) {
2072 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2073 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2076 mono_error_cleanup (&error);
2077 mono_loader_unlock ();
2081 } else if (class->rank) {
2083 MonoMethod *amethod;
2084 MonoMethodSignature *sig;
2085 int count_generic = 0, first_generic = 0;
2087 gboolean jagged_ctor = FALSE;
2089 class->method.count = 3 + (class->rank > 1? 2: 1);
2091 mono_class_setup_interfaces (class, &error);
2092 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2094 if (class->rank == 1 && class->element_class->rank) {
2096 class->method.count ++;
2099 if (class->interface_count) {
2100 count_generic = generic_array_methods (class);
2101 first_generic = class->method.count;
2102 class->method.count += class->interface_count * count_generic;
2105 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2107 sig = mono_metadata_signature_alloc (class->image, class->rank);
2108 sig->ret = &mono_defaults.void_class->byval_arg;
2109 sig->pinvoke = TRUE;
2110 sig->hasthis = TRUE;
2111 for (i = 0; i < class->rank; ++i)
2112 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2114 amethod = create_array_method (class, ".ctor", sig);
2115 methods [method_num++] = amethod;
2116 if (class->rank > 1) {
2117 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2118 sig->ret = &mono_defaults.void_class->byval_arg;
2119 sig->pinvoke = TRUE;
2120 sig->hasthis = TRUE;
2121 for (i = 0; i < class->rank * 2; ++i)
2122 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2124 amethod = create_array_method (class, ".ctor", sig);
2125 methods [method_num++] = amethod;
2129 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2130 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2131 sig->ret = &mono_defaults.void_class->byval_arg;
2132 sig->pinvoke = TRUE;
2133 sig->hasthis = TRUE;
2134 for (i = 0; i < class->rank + 1; ++i)
2135 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2136 amethod = create_array_method (class, ".ctor", sig);
2137 methods [method_num++] = amethod;
2140 /* element Get (idx11, [idx2, ...]) */
2141 sig = mono_metadata_signature_alloc (class->image, class->rank);
2142 sig->ret = &class->element_class->byval_arg;
2143 sig->pinvoke = TRUE;
2144 sig->hasthis = TRUE;
2145 for (i = 0; i < class->rank; ++i)
2146 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2147 amethod = create_array_method (class, "Get", sig);
2148 methods [method_num++] = amethod;
2149 /* element& Address (idx11, [idx2, ...]) */
2150 sig = mono_metadata_signature_alloc (class->image, class->rank);
2151 sig->ret = &class->element_class->this_arg;
2152 sig->pinvoke = TRUE;
2153 sig->hasthis = TRUE;
2154 for (i = 0; i < class->rank; ++i)
2155 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2156 amethod = create_array_method (class, "Address", sig);
2157 methods [method_num++] = amethod;
2158 /* void Set (idx11, [idx2, ...], element) */
2159 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2160 sig->ret = &mono_defaults.void_class->byval_arg;
2161 sig->pinvoke = TRUE;
2162 sig->hasthis = TRUE;
2163 for (i = 0; i < class->rank; ++i)
2164 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2165 sig->params [i] = &class->element_class->byval_arg;
2166 amethod = create_array_method (class, "Set", sig);
2167 methods [method_num++] = amethod;
2169 for (i = 0; i < class->interface_count; i++)
2170 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2172 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2173 for (i = 0; i < class->method.count; ++i) {
2174 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2175 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2179 if (MONO_CLASS_IS_INTERFACE (class)) {
2181 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2182 for (i = 0; i < class->method.count; ++i) {
2183 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2184 methods [i]->slot = slot++;
2188 /* Needed because of the double-checking locking pattern */
2189 mono_memory_barrier ();
2191 class->methods = methods;
2193 mono_loader_unlock ();
2197 * mono_class_get_method_by_index:
2199 * Returns class->methods [index], initializing class->methods if neccesary.
2201 * LOCKING: Acquires the loader lock.
2204 mono_class_get_method_by_index (MonoClass *class, int index)
2206 /* Avoid calling setup_methods () if possible */
2207 if (class->generic_class && !class->methods) {
2208 MonoClass *gklass = class->generic_class->container_class;
2211 m = mono_class_inflate_generic_method_full (
2212 gklass->methods [index], class, mono_class_get_context (class));
2214 * If setup_methods () is called later for this class, no duplicates are created,
2215 * since inflate_generic_method guarantees that only one instance of a method
2216 * is created for each context.
2219 mono_class_setup_methods (class);
2220 g_assert (m == class->methods [index]);
2224 mono_class_setup_methods (class);
2225 if (class->exception_type) /*FIXME do proper error handling*/
2227 g_assert (index >= 0 && index < class->method.count);
2228 return class->methods [index];
2233 * mono_class_get_inflated_method:
2235 * Given an inflated class CLASS and a method METHOD which should be a method of
2236 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2239 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2241 MonoClass *gklass = class->generic_class->container_class;
2244 g_assert (method->klass == gklass);
2246 mono_class_setup_methods (gklass);
2247 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2249 for (i = 0; i < gklass->method.count; ++i) {
2250 if (gklass->methods [i] == method) {
2252 return class->methods [i];
2254 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2262 * mono_class_get_vtable_entry:
2264 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2265 * LOCKING: Acquires the loader lock.
2268 mono_class_get_vtable_entry (MonoClass *class, int offset)
2272 if (class->rank == 1) {
2274 * szarrays do not overwrite any methods of Array, so we can avoid
2275 * initializing their vtables in some cases.
2277 mono_class_setup_vtable (class->parent);
2278 if (offset < class->parent->vtable_size)
2279 return class->parent->vtable [offset];
2282 if (class->generic_class) {
2283 MonoClass *gklass = class->generic_class->container_class;
2284 mono_class_setup_vtable (gklass);
2285 m = gklass->vtable [offset];
2287 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2289 mono_class_setup_vtable (class);
2290 if (class->exception_type)
2292 m = class->vtable [offset];
2299 * mono_class_get_vtable_size:
2301 * Return the vtable size for KLASS.
2304 mono_class_get_vtable_size (MonoClass *klass)
2306 mono_class_setup_vtable (klass);
2308 return klass->vtable_size;
2311 /*This method can fail the class.*/
2313 mono_class_setup_properties (MonoClass *class)
2315 guint startm, endm, i, j;
2316 guint32 cols [MONO_PROPERTY_SIZE];
2317 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2318 MonoProperty *properties;
2321 if (class->ext && class->ext->properties)
2324 mono_loader_lock ();
2326 if (class->ext && class->ext->properties) {
2327 mono_loader_unlock ();
2331 mono_class_alloc_ext (class);
2333 if (class->generic_class) {
2334 MonoClass *gklass = class->generic_class->container_class;
2336 mono_class_init (gklass);
2337 mono_class_setup_properties (gklass);
2338 if (gklass->exception_type) {
2339 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2340 mono_loader_unlock ();
2344 class->ext->property = gklass->ext->property;
2346 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2348 for (i = 0; i < class->ext->property.count; i++) {
2349 MonoProperty *prop = &properties [i];
2351 *prop = gklass->ext->properties [i];
2354 prop->get = mono_class_inflate_generic_method_full (
2355 prop->get, class, mono_class_get_context (class));
2357 prop->set = mono_class_inflate_generic_method_full (
2358 prop->set, class, mono_class_get_context (class));
2360 prop->parent = class;
2363 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2364 int count = last - first;
2367 mono_class_setup_methods (class);
2368 if (class->exception_type) {
2369 mono_loader_unlock ();
2374 class->ext->property.first = first;
2375 class->ext->property.count = count;
2376 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2377 for (i = first; i < last; ++i) {
2378 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2379 properties [i - first].parent = class;
2380 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2381 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2383 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2384 for (j = startm; j < endm; ++j) {
2387 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2389 if (class->image->uncompressed_metadata)
2390 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2391 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2393 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2395 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2396 case METHOD_SEMANTIC_SETTER:
2397 properties [i - first].set = method;
2399 case METHOD_SEMANTIC_GETTER:
2400 properties [i - first].get = method;
2408 /*Flush any pending writes as we do double checked locking on class->properties */
2409 mono_memory_barrier ();
2411 /* Leave this assignment as the last op in the function */
2412 class->ext->properties = properties;
2414 mono_loader_unlock ();
2418 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2420 MonoMethod **om, **retval;
2423 for (om = methods, count = 0; *om; ++om, ++count)
2426 retval = g_new0 (MonoMethod*, count + 1);
2428 for (om = methods, count = 0; *om; ++om, ++count)
2429 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2434 /*This method can fail the class.*/
2436 mono_class_setup_events (MonoClass *class)
2439 guint startm, endm, i, j;
2440 guint32 cols [MONO_EVENT_SIZE];
2441 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2445 if (class->ext && class->ext->events)
2448 mono_loader_lock ();
2450 if (class->ext && class->ext->events) {
2451 mono_loader_unlock ();
2455 mono_class_alloc_ext (class);
2457 if (class->generic_class) {
2458 MonoClass *gklass = class->generic_class->container_class;
2459 MonoGenericContext *context;
2461 mono_class_setup_events (gklass);
2462 if (gklass->exception_type) {
2463 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2464 mono_loader_unlock ();
2468 class->ext->event = gklass->ext->event;
2469 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2471 if (class->ext->event.count)
2472 context = mono_class_get_context (class);
2474 for (i = 0; i < class->ext->event.count; i++) {
2475 MonoEvent *event = &class->ext->events [i];
2476 MonoEvent *gevent = &gklass->ext->events [i];
2478 event->parent = class;
2479 event->name = gevent->name;
2480 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2481 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2482 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2483 #ifndef MONO_SMALL_CONFIG
2484 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2486 event->attrs = gevent->attrs;
2489 mono_loader_unlock ();
2493 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2494 count = last - first;
2497 mono_class_setup_methods (class);
2498 if (class->exception_type) {
2499 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2500 mono_loader_unlock ();
2504 class->ext->event.first = first;
2505 class->ext->event.count = count;
2506 events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2507 for (i = first; i < last; ++i) {
2508 MonoEvent *event = &events [i - first];
2510 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2511 event->parent = class;
2512 event->attrs = cols [MONO_EVENT_FLAGS];
2513 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2515 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2516 for (j = startm; j < endm; ++j) {
2519 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2521 if (class->image->uncompressed_metadata)
2522 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2523 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2525 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2527 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2528 case METHOD_SEMANTIC_ADD_ON:
2529 event->add = method;
2531 case METHOD_SEMANTIC_REMOVE_ON:
2532 event->remove = method;
2534 case METHOD_SEMANTIC_FIRE:
2535 event->raise = method;
2537 case METHOD_SEMANTIC_OTHER: {
2538 #ifndef MONO_SMALL_CONFIG
2541 if (event->other == NULL) {
2542 event->other = g_new0 (MonoMethod*, 2);
2544 while (event->other [n])
2546 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2548 event->other [n] = method;
2549 /* NULL terminated */
2550 event->other [n + 1] = NULL;
2559 /*Flush any pending writes as we do double checked locking on class->properties */
2560 mono_memory_barrier ();
2562 /* Leave this assignment as the last op in the function */
2563 class->ext->events = events;
2565 mono_loader_unlock ();
2569 * Global pool of interface IDs, represented as a bitset.
2570 * LOCKING: this is supposed to be accessed with the loader lock held.
2572 static MonoBitSet *global_interface_bitset = NULL;
2575 * mono_unload_interface_ids:
2576 * @bitset: bit set of interface IDs
2578 * When an image is unloaded, the interface IDs associated with
2579 * the image are put back in the global pool of IDs so the numbers
2583 mono_unload_interface_ids (MonoBitSet *bitset)
2585 mono_loader_lock ();
2586 mono_bitset_sub (global_interface_bitset, bitset);
2587 mono_loader_unlock ();
2591 mono_unload_interface_id (MonoClass *class)
2593 if (global_interface_bitset && class->interface_id) {
2594 mono_loader_lock ();
2595 mono_bitset_clear (global_interface_bitset, class->interface_id);
2596 mono_loader_unlock ();
2601 * mono_get_unique_iid:
2604 * Assign a unique integer ID to the interface represented by @class.
2605 * The ID will positive and as small as possible.
2606 * LOCKING: this is supposed to be called with the loader lock held.
2607 * Returns: the new ID.
2610 mono_get_unique_iid (MonoClass *class)
2614 g_assert (MONO_CLASS_IS_INTERFACE (class));
2616 if (!global_interface_bitset) {
2617 global_interface_bitset = mono_bitset_new (128, 0);
2620 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2622 int old_size = mono_bitset_size (global_interface_bitset);
2623 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2624 mono_bitset_free (global_interface_bitset);
2625 global_interface_bitset = new_set;
2628 mono_bitset_set (global_interface_bitset, iid);
2629 /* set the bit also in the per-image set */
2630 if (!class->generic_class) {
2631 if (class->image->interface_bitset) {
2632 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2633 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2634 mono_bitset_free (class->image->interface_bitset);
2635 class->image->interface_bitset = new_set;
2638 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2640 mono_bitset_set (class->image->interface_bitset, iid);
2643 #ifndef MONO_SMALL_CONFIG
2644 if (mono_print_vtable) {
2646 char *type_name = mono_type_full_name (&class->byval_arg);
2647 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2648 generic_id = class->generic_class->context.class_inst->id;
2649 g_assert (generic_id != 0);
2653 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2658 g_assert (iid <= 65535);
2663 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2668 mono_class_setup_interfaces (klass, error);
2669 if (!mono_error_ok (error))
2672 for (i = 0; i < klass->interface_count; i++) {
2673 ic = klass->interfaces [i];
2676 *res = g_ptr_array_new ();
2677 g_ptr_array_add (*res, ic);
2678 mono_class_init (ic);
2679 if (ic->exception_type) {
2680 mono_error_set_type_load_class (error, ic, "Error Loading class");
2684 collect_implemented_interfaces_aux (ic, res, error);
2685 if (!mono_error_ok (error))
2691 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2693 GPtrArray *res = NULL;
2695 collect_implemented_interfaces_aux (klass, &res, error);
2696 if (!mono_error_ok (error)) {
2698 g_ptr_array_free (res, TRUE);
2705 compare_interface_ids (const void *p_key, const void *p_element) {
2706 const MonoClass *key = p_key;
2707 const MonoClass *element = *(MonoClass**) p_element;
2709 return (key->interface_id - element->interface_id);
2712 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2714 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2715 MonoClass **result = mono_binary_search (
2717 klass->interfaces_packed,
2718 klass->interface_offsets_count,
2719 sizeof (MonoClass *),
2720 compare_interface_ids);
2722 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2729 * mono_class_interface_offset_with_variance:
2731 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2732 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2734 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2736 * FIXME figure out MS disambiguation rules and fix this function.
2739 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2740 int i = mono_class_interface_offset (klass, itf);
2741 *non_exact_match = FALSE;
2745 if (!mono_class_has_variant_generic_params (itf))
2748 for (i = 0; i < klass->interface_offsets_count; i++) {
2749 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2750 *non_exact_match = TRUE;
2751 return klass->interface_offsets_packed [i];
2759 print_implemented_interfaces (MonoClass *klass) {
2762 GPtrArray *ifaces = NULL;
2764 int ancestor_level = 0;
2766 name = mono_type_get_full_name (klass);
2767 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2770 for (i = 0; i < klass->interface_offsets_count; i++)
2771 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2772 klass->interfaces_packed [i]->interface_id,
2773 klass->interface_offsets_packed [i],
2774 klass->interfaces_packed [i]->method.count,
2775 klass->interfaces_packed [i]->name_space,
2776 klass->interfaces_packed [i]->name );
2777 printf ("Interface flags: ");
2778 for (i = 0; i <= klass->max_interface_id; i++)
2779 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2780 printf ("(%d,T)", i);
2782 printf ("(%d,F)", i);
2784 printf ("Dump interface flags:");
2785 #ifdef COMPRESSED_INTERFACE_BITMAP
2787 const uint8_t* p = klass->interface_bitmap;
2788 i = klass->max_interface_id;
2790 printf (" %d x 00 %02X", p [0], p [1]);
2796 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2797 printf (" %02X", klass->interface_bitmap [i]);
2800 while (klass != NULL) {
2801 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2802 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2803 if (!mono_error_ok (&error)) {
2804 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2805 mono_error_cleanup (&error);
2806 } else if (ifaces) {
2807 for (i = 0; i < ifaces->len; i++) {
2808 MonoClass *ic = g_ptr_array_index (ifaces, i);
2809 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2810 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2812 mono_class_interface_offset (klass, ic),
2817 g_ptr_array_free (ifaces, TRUE);
2820 klass = klass->parent;
2825 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2828 args [0] = &arg0->byval_arg;
2830 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2834 array_class_get_if_rank (MonoClass *class, guint rank)
2836 return rank ? mono_array_class_get (class, rank) : class;
2840 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2842 valuetype_types [0] = eclass;
2843 if (eclass == mono_defaults.int16_class)
2844 valuetype_types [1] = mono_defaults.uint16_class;
2845 else if (eclass == mono_defaults.uint16_class)
2846 valuetype_types [1] = mono_defaults.int16_class;
2847 else if (eclass == mono_defaults.int32_class)
2848 valuetype_types [1] = mono_defaults.uint32_class;
2849 else if (eclass == mono_defaults.uint32_class)
2850 valuetype_types [1] = mono_defaults.int32_class;
2851 else if (eclass == mono_defaults.int64_class)
2852 valuetype_types [1] = mono_defaults.uint64_class;
2853 else if (eclass == mono_defaults.uint64_class)
2854 valuetype_types [1] = mono_defaults.int64_class;
2855 else if (eclass == mono_defaults.byte_class)
2856 valuetype_types [1] = mono_defaults.sbyte_class;
2857 else if (eclass == mono_defaults.sbyte_class)
2858 valuetype_types [1] = mono_defaults.byte_class;
2859 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2860 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2863 /* this won't be needed once bug #325495 is completely fixed
2864 * though we'll need something similar to know which interfaces to allow
2865 * in arrays when they'll be lazyly created
2867 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2868 * MS returns diferrent types based on which instance is called. For example:
2869 * object obj = new byte[10][];
2870 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2871 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2874 * Fixing this should kill quite some code, save some bits and improve compatibility.
2877 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2879 MonoClass *eclass = class->element_class;
2880 static MonoClass* generic_icollection_class = NULL;
2881 static MonoClass* generic_ienumerable_class = NULL;
2882 static MonoClass* generic_ienumerator_class = NULL;
2883 static MonoClass* generic_ireadonlylist_class = NULL;
2884 static MonoClass* generic_ireadonlycollection_class = NULL;
2885 MonoClass *valuetype_types[2] = { NULL, NULL };
2886 MonoClass **interfaces = NULL;
2887 int i, nifaces, interface_count, real_count, original_rank;
2889 gboolean internal_enumerator;
2890 gboolean eclass_is_valuetype;
2892 if (!mono_defaults.generic_ilist_class) {
2896 internal_enumerator = FALSE;
2897 eclass_is_valuetype = FALSE;
2898 original_rank = eclass->rank;
2899 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2900 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2902 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2904 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2905 original_rank = eclass->rank;
2907 eclass = eclass->element_class;
2908 internal_enumerator = TRUE;
2909 *is_enumerator = TRUE;
2917 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2918 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2920 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2922 if (!generic_icollection_class) {
2923 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2924 "System.Collections.Generic", "ICollection`1");
2925 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2926 "System.Collections.Generic", "IEnumerable`1");
2927 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2928 "System.Collections.Generic", "IEnumerator`1");
2929 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2930 "System.Collections.Generic", "IReadOnlyList`1");
2931 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2932 "System.Collections.Generic", "IReadOnlyCollection`1");
2935 mono_class_init (eclass);
2938 * Arrays in 2.0 need to implement a number of generic interfaces
2939 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2940 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2941 * We collect the types needed to build the
2942 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2943 * the generic interfaces needed to implement.
2945 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2946 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2948 if (eclass->valuetype) {
2949 nifaces = generic_ireadonlylist_class ? 5 : 3;
2950 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2952 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2953 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2954 if (internal_enumerator) {
2956 if (valuetype_types [1])
2960 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2961 interfaces [0] = valuetype_types [0];
2962 if (valuetype_types [1])
2963 interfaces [nifaces] = valuetype_types [1];
2965 eclass_is_valuetype = TRUE;
2968 int idepth = eclass->idepth;
2969 if (!internal_enumerator)
2971 nifaces = generic_ireadonlylist_class ? 2 : 3;
2973 // FIXME: This doesn't seem to work/required for generic params
2974 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
2975 mono_class_setup_interface_offsets (eclass);
2977 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2978 /* we add object for interfaces and the supertypes for the other
2979 * types. The last of the supertypes is the element class itself which we
2980 * already created the explicit interfaces for (so we include it for IEnumerator
2981 * and exclude it for arrays).
2983 if (MONO_CLASS_IS_INTERFACE (eclass))
2986 interface_count += idepth;
2987 if (eclass->rank && eclass->element_class->valuetype) {
2988 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2989 if (valuetype_types [1])
2992 /* IList, ICollection, IEnumerable, IReadOnlyList */
2993 interface_count *= nifaces;
2994 real_count = interface_count;
2995 if (internal_enumerator) {
2996 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2997 if (valuetype_types [1])
3000 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3001 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3002 interfaces [0] = mono_defaults.object_class;
3006 for (i = 0; i < idepth; i++) {
3007 mono_class_init (eclass->supertypes [i]);
3008 interfaces [j] = eclass->supertypes [i];
3012 if (all_interfaces) {
3013 for (i = 0; i < eclass->interface_offsets_count; i++) {
3014 interfaces [j] = eclass->interfaces_packed [i];
3018 for (i = 0; i < eclass->interface_count; i++) {
3019 interfaces [j] = eclass->interfaces [i];
3023 if (valuetype_types [1]) {
3024 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3029 /* instantiate the generic interfaces */
3030 for (i = 0; i < interface_count; i += nifaces) {
3031 MonoClass *iface = interfaces [i];
3033 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3034 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3036 if (eclass->valuetype) {
3037 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3038 if (generic_ireadonlylist_class) {
3039 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3040 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3043 if (!generic_ireadonlylist_class)
3044 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3047 if (internal_enumerator) {
3049 /* instantiate IEnumerator<iface> */
3050 for (i = 0; i < interface_count; i++) {
3051 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3053 j = interface_count;
3054 if (!eclass_is_valuetype) {
3055 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3056 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3059 for (i = 0; i < eclass->idepth; i++) {
3060 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3064 for (i = 0; i < eclass->interface_offsets_count; i++) {
3065 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3069 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3071 if (valuetype_types [1])
3072 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3076 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3077 for (i = 0; i < real_count; ++i) {
3078 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3079 g_print ("%s implements %s\n", type_name, name);
3090 find_array_interface (MonoClass *klass, const char *name)
3093 for (i = 0; i < klass->interface_count; ++i) {
3094 if (strcmp (klass->interfaces [i]->name, name) == 0)
3101 * Return the number of virtual methods.
3102 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3103 * Return -1 on failure.
3104 * FIXME It would be nice if this information could be cached somewhere.
3107 count_virtual_methods (MonoClass *class)
3111 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3113 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3114 mono_class_setup_methods (class);
3115 if (class->exception_type)
3118 for (i = 0; i < class->method.count; ++i) {
3119 flags = class->methods [i]->flags;
3120 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3124 for (i = 0; i < class->method.count; ++i) {
3125 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3127 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3135 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3143 m = (l + num_ifaces) / 2;
3144 if (interfaces_full [m] == ic)
3146 if (l == num_ifaces)
3148 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3157 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3159 int i = find_interface (num_ifaces, interfaces_full, ic);
3161 return interface_offsets_full [i];
3166 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3168 int i = find_interface (num_ifaces, interfaces_full, ic);
3172 interface_offsets_full [i] = offset;
3175 for (i = 0; i < num_ifaces; ++i) {
3176 if (interfaces_full [i]) {
3178 if (interfaces_full [i]->interface_id < ic->interface_id)
3181 while (end < num_ifaces && interfaces_full [end]) end++;
3182 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3183 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3185 interfaces_full [i] = ic;
3186 interface_offsets_full [i] = offset;
3192 #ifdef COMPRESSED_INTERFACE_BITMAP
3195 * Compressed interface bitmap design.
3197 * Interface bitmaps take a large amount of memory, because their size is
3198 * linear with the maximum interface id assigned in the process (each interface
3199 * is assigned a unique id as it is loaded). The number of interface classes
3200 * is high because of the many implicit interfaces implemented by arrays (we'll
3201 * need to lazy-load them in the future).
3202 * Most classes implement a very small number of interfaces, so the bitmap is
3203 * sparse. This bitmap needs to be checked by interface casts, so access to the
3204 * needed bit must be fast and doable with few jit instructions.
3206 * The current compression format is as follows:
3207 * *) it is a sequence of one or more two-byte elements
3208 * *) the first byte in the element is the count of empty bitmap bytes
3209 * at the current bitmap position
3210 * *) the second byte in the element is an actual bitmap byte at the current
3213 * As an example, the following compressed bitmap bytes:
3214 * 0x07 0x01 0x00 0x7
3215 * correspond to the following bitmap:
3216 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3218 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3219 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3220 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3224 * mono_compress_bitmap:
3225 * @dest: destination buffer
3226 * @bitmap: bitmap buffer
3227 * @size: size of @bitmap in bytes
3229 * This is a mono internal function.
3230 * The @bitmap data is compressed into a format that is small but
3231 * still searchable in few instructions by the JIT and runtime.
3232 * The compressed data is stored in the buffer pointed to by the
3233 * @dest array. Passing a #NULL value for @dest allows to just compute
3234 * the size of the buffer.
3235 * This compression algorithm assumes the bits set in the bitmap are
3236 * few and far between, like in interface bitmaps.
3237 * Returns: the size of the compressed bitmap in bytes.
3240 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3244 const uint8_t *end = bitmap + size;
3245 while (bitmap < end) {
3246 if (*bitmap || numz == 255) {
3270 * mono_class_interface_match:
3271 * @bitmap: a compressed bitmap buffer
3272 * @id: the index to check in the bitmap
3274 * This is a mono internal function.
3275 * Checks if a bit is set in a compressed interface bitmap. @id must
3276 * be already checked for being smaller than the maximum id encoded in the
3279 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3283 mono_class_interface_match (const uint8_t *bitmap, int id)
3286 id -= bitmap [0] * 8;
3290 return bitmap [1] & (1 << id);
3299 * LOCKING: this is supposed to be called with the loader lock held.
3300 * Return -1 on failure and set exception_type
3303 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3307 int i, j, max_iid, num_ifaces;
3308 MonoClass **interfaces_full = NULL;
3309 int *interface_offsets_full = NULL;
3311 GPtrArray **ifaces_array = NULL;
3312 int interface_offsets_count;
3313 MonoClass **array_interfaces = NULL;
3314 int num_array_interfaces;
3315 int is_enumerator = FALSE;
3317 mono_class_setup_supertypes (class);
3319 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3320 * implicit interfaces have the property that they are assigned the same slot in the
3321 * vtables for compatible interfaces
3323 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3325 /* compute maximum number of slots and maximum interface id */
3327 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3328 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3329 for (j = 0; j < class->idepth; j++) {
3330 k = class->supertypes [j];
3331 num_ifaces += k->interface_count;
3332 for (i = 0; i < k->interface_count; i++) {
3333 ic = k->interfaces [i];
3336 mono_class_init (ic);
3338 if (max_iid < ic->interface_id)
3339 max_iid = ic->interface_id;
3341 ifaces = mono_class_get_implemented_interfaces (k, &error);
3342 if (!mono_error_ok (&error)) {
3343 char *name = mono_type_get_full_name (k);
3344 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)));
3346 mono_error_cleanup (&error);
3351 num_ifaces += ifaces->len;
3352 for (i = 0; i < ifaces->len; ++i) {
3353 ic = g_ptr_array_index (ifaces, i);
3354 if (max_iid < ic->interface_id)
3355 max_iid = ic->interface_id;
3357 ifaces_array [j] = ifaces;
3361 for (i = 0; i < num_array_interfaces; ++i) {
3362 ic = array_interfaces [i];
3363 mono_class_init (ic);
3364 if (max_iid < ic->interface_id)
3365 max_iid = ic->interface_id;
3368 if (MONO_CLASS_IS_INTERFACE (class)) {
3370 if (max_iid < class->interface_id)
3371 max_iid = class->interface_id;
3373 class->max_interface_id = max_iid;
3374 /* compute vtable offset for interfaces */
3375 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3376 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3378 for (i = 0; i < num_ifaces; i++) {
3379 interface_offsets_full [i] = -1;
3382 /* skip the current class */
3383 for (j = 0; j < class->idepth - 1; j++) {
3384 k = class->supertypes [j];
3385 ifaces = ifaces_array [j];
3388 for (i = 0; i < ifaces->len; ++i) {
3390 ic = g_ptr_array_index (ifaces, i);
3392 /*Force the sharing of interface offsets between parent and subtypes.*/
3393 io = mono_class_interface_offset (k, ic);
3395 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3400 g_assert (class == class->supertypes [class->idepth - 1]);
3401 ifaces = ifaces_array [class->idepth - 1];
3403 for (i = 0; i < ifaces->len; ++i) {
3405 ic = g_ptr_array_index (ifaces, i);
3406 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3408 count = count_virtual_methods (ic);
3410 char *name = mono_type_get_full_name (ic);
3411 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3420 if (MONO_CLASS_IS_INTERFACE (class))
3421 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3423 if (num_array_interfaces) {
3424 if (is_enumerator) {
3425 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3426 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3427 g_assert (ienumerator_offset >= 0);
3428 for (i = 0; i < num_array_interfaces; ++i) {
3429 ic = array_interfaces [i];
3430 if (strcmp (ic->name, "IEnumerator`1") == 0)
3431 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3433 g_assert_not_reached ();
3434 /*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);*/
3437 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3438 int ilist_iface_idx = find_array_interface (class, "IList`1");
3439 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3440 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3441 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3442 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3443 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3444 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3445 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3446 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3447 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3448 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3449 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3450 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3451 for (i = 0; i < num_array_interfaces; ++i) {
3453 ic = array_interfaces [i];
3454 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3455 offset = ilist_offset;
3456 else if (strcmp (ic->name, "ICollection`1") == 0)
3457 offset = icollection_offset;
3458 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3459 offset = ienumerable_offset;
3460 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3461 offset = ireadonlylist_offset;
3462 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3463 offset = ireadonlycollection_offset;
3465 g_assert_not_reached ();
3466 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3467 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3472 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3473 if (interface_offsets_full [i] != -1) {
3474 interface_offsets_count ++;
3479 * We might get called multiple times:
3480 * - mono_class_init ()
3481 * - mono_class_setup_vtable ().
3482 * - mono_class_setup_interface_offsets ().
3483 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3484 * means we have to overwrite those when called from other places (#4440).
3486 if (class->interfaces_packed && !overwrite) {
3487 g_assert (class->interface_offsets_count == interface_offsets_count);
3491 class->interface_offsets_count = interface_offsets_count;
3492 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3493 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3494 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3495 #ifdef COMPRESSED_INTERFACE_BITMAP
3496 bitmap = g_malloc0 (bsize);
3498 bitmap = mono_class_alloc0 (class, bsize);
3500 for (i = 0; i < interface_offsets_count; i++) {
3501 int id = interfaces_full [i]->interface_id;
3502 bitmap [id >> 3] |= (1 << (id & 7));
3503 class->interfaces_packed [i] = interfaces_full [i];
3504 class->interface_offsets_packed [i] = interface_offsets_full [i];
3505 /*if (num_array_interfaces)
3506 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]);*/
3508 #ifdef COMPRESSED_INTERFACE_BITMAP
3509 i = mono_compress_bitmap (NULL, bitmap, bsize);
3510 class->interface_bitmap = mono_class_alloc0 (class, i);
3511 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3514 class->interface_bitmap = bitmap;
3519 g_free (interfaces_full);
3520 g_free (interface_offsets_full);
3521 g_free (array_interfaces);
3522 for (i = 0; i < class->idepth; i++) {
3523 ifaces = ifaces_array [i];
3525 g_ptr_array_free (ifaces, TRUE);
3527 g_free (ifaces_array);
3529 //printf ("JUST DONE: ");
3530 //print_implemented_interfaces (class);
3536 * Setup interface offsets for interfaces.
3538 * - class->max_interface_id
3539 * - class->interface_offsets_count
3540 * - class->interfaces_packed
3541 * - class->interface_offsets_packed
3542 * - class->interface_bitmap
3544 * This function can fail @class.
3547 mono_class_setup_interface_offsets (MonoClass *class)
3549 mono_loader_lock ();
3551 setup_interface_offsets (class, 0, FALSE);
3553 mono_loader_unlock ();
3556 /*Checks if @klass has @parent as one of it's parents type gtd
3560 * Bar<T> : Foo<Bar<Bar<T>>>
3564 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3566 klass = mono_class_get_generic_type_definition (klass);
3567 parent = mono_class_get_generic_type_definition (parent);
3568 mono_class_setup_supertypes (klass);
3569 mono_class_setup_supertypes (parent);
3571 return klass->idepth >= parent->idepth &&
3572 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3576 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3578 MonoGenericInst *ginst;
3580 if (!class->generic_class) {
3581 mono_class_setup_vtable_full (class, in_setup);
3582 return class->exception_type == 0;
3585 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3586 if (class->generic_class->container_class->exception_type) {
3587 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3591 ginst = class->generic_class->context.class_inst;
3592 for (i = 0; i < ginst->type_argc; ++i) {
3594 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3596 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3597 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3598 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3600 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3601 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3609 * mono_class_setup_vtable:
3611 * Creates the generic vtable of CLASS.
3612 * Initializes the following fields in MonoClass:
3615 * Plus all the fields initialized by setup_interface_offsets ().
3616 * If there is an error during vtable construction, class->exception_type is set.
3618 * LOCKING: Acquires the loader lock.
3621 mono_class_setup_vtable (MonoClass *class)
3623 mono_class_setup_vtable_full (class, NULL);
3627 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3629 MonoMethod **overrides;
3630 MonoGenericContext *context;
3638 if (MONO_CLASS_IS_INTERFACE (class)) {
3639 /* This sets method->slot for all methods if this is an interface */
3640 mono_class_setup_methods (class);
3644 if (class->exception_type)
3647 if (g_list_find (in_setup, class))
3650 mono_loader_lock ();
3652 if (class->vtable) {
3653 mono_loader_unlock ();
3657 mono_stats.generic_vtable_count ++;
3658 in_setup = g_list_prepend (in_setup, class);
3660 if (class->generic_class) {
3661 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3662 mono_loader_unlock ();
3663 g_list_remove (in_setup, class);
3667 context = mono_class_get_context (class);
3668 type_token = class->generic_class->container_class->type_token;
3670 context = (MonoGenericContext *) class->generic_container;
3671 type_token = class->type_token;
3674 if (class->image->dynamic) {
3675 /* Generic instances can have zero method overrides without causing any harm.
3676 * This is true since we don't do layout all over again for them, we simply inflate
3677 * the layout of the parent.
3679 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3681 /* The following call fails if there are missing methods in the type */
3682 /* FIXME it's probably a good idea to avoid this for generic instances. */
3683 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3687 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3689 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3693 mono_loader_unlock ();
3694 g_list_remove (in_setup, class);
3699 #define DEBUG_INTERFACE_VTABLE_CODE 0
3700 #define TRACE_INTERFACE_VTABLE_CODE 0
3701 #define VERIFY_INTERFACE_VTABLE_CODE 0
3702 #define VTABLE_SELECTOR (1)
3704 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3705 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3706 if (!(VTABLE_SELECTOR)) break; \
3710 #define DEBUG_INTERFACE_VTABLE(stmt)
3713 #if TRACE_INTERFACE_VTABLE_CODE
3714 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3715 if (!(VTABLE_SELECTOR)) break; \
3719 #define TRACE_INTERFACE_VTABLE(stmt)
3722 #if VERIFY_INTERFACE_VTABLE_CODE
3723 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3724 if (!(VTABLE_SELECTOR)) break; \
3728 #define VERIFY_INTERFACE_VTABLE(stmt)
3732 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3734 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3738 GString *res = g_string_new ("");
3740 g_string_append_c (res, '(');
3741 for (i = 0; i < sig->param_count; ++i) {
3743 g_string_append_c (res, ',');
3744 mono_type_get_desc (res, sig->params [i], include_namespace);
3746 g_string_append (res, ")=>");
3747 if (sig->ret != NULL) {
3748 mono_type_get_desc (res, sig->ret, include_namespace);
3750 g_string_append (res, "NULL");
3753 g_string_free (res, FALSE);
3757 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3758 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3759 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3760 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3768 is_wcf_hack_disabled (void)
3770 static gboolean disabled;
3771 static gboolean inited = FALSE;
3773 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3780 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) {
3781 MonoMethodSignature *cmsig, *imsig;
3782 if (strcmp (im->name, cm->name) == 0) {
3783 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3784 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3787 if (! slot_is_empty) {
3788 if (require_newslot) {
3789 if (! interface_is_explicitly_implemented_by_class) {
3790 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3793 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3794 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3798 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3801 cmsig = mono_method_signature (cm);
3802 imsig = mono_method_signature (im);
3803 if (!cmsig || !imsig) {
3804 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3808 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3809 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3810 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3811 TRACE_INTERFACE_VTABLE (printf ("]"));
3814 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3815 /* CAS - SecurityAction.InheritanceDemand on interface */
3816 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3817 mono_secman_inheritancedemand_method (cm, im);
3820 if (mono_security_core_clr_enabled ())
3821 mono_security_core_clr_check_override (class, cm, im);
3823 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3824 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3825 char *body_name = mono_method_full_name (cm, TRUE);
3826 char *decl_name = mono_method_full_name (im, TRUE);
3827 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));
3835 MonoClass *ic = im->klass;
3836 const char *ic_name_space = ic->name_space;
3837 const char *ic_name = ic->name;
3840 if (! require_newslot) {
3841 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3844 if (cm->klass->rank == 0) {
3845 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3848 cmsig = mono_method_signature (cm);
3849 imsig = mono_method_signature (im);
3850 if (!cmsig || !imsig) {
3851 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3855 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3856 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3857 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3858 TRACE_INTERFACE_VTABLE (printf ("]"));
3861 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3862 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3865 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3866 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3869 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))) {
3870 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3874 subname = strstr (cm->name, ic_name_space);
3875 if (subname != cm->name) {
3876 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3879 subname += strlen (ic_name_space);
3880 if (subname [0] != '.') {
3881 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3885 if (strstr (subname, ic_name) != subname) {
3886 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3889 subname += strlen (ic_name);
3890 if (subname [0] != '.') {
3891 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3895 if (strcmp (subname, im->name) != 0) {
3896 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3900 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3901 /* CAS - SecurityAction.InheritanceDemand on interface */
3902 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3903 mono_secman_inheritancedemand_method (cm, im);
3906 if (mono_security_core_clr_enabled ())
3907 mono_security_core_clr_check_override (class, cm, im);
3909 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3910 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3911 char *body_name = mono_method_full_name (cm, TRUE);
3912 char *decl_name = mono_method_full_name (im, TRUE);
3913 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));
3923 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3925 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3926 MonoMethod *method = key;
3927 MonoMethod *override = value;
3928 MonoClass *method_class = mono_method_get_class (method);
3929 MonoClass *override_class = mono_method_get_class (override);
3931 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3932 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3933 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3936 print_overrides (GHashTable *override_map, const char *message) {
3938 printf ("Override map \"%s\" START:\n", message);
3939 g_hash_table_foreach (override_map, foreach_override, NULL);
3940 printf ("Override map \"%s\" END.\n", message);
3942 printf ("Override map \"%s\" EMPTY.\n", message);
3946 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3947 char *full_name = mono_type_full_name (&class->byval_arg);
3951 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3953 if (print_interfaces) {
3954 print_implemented_interfaces (class);
3955 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3958 if (class->parent) {
3959 parent_size = class->parent->vtable_size;
3963 for (i = 0; i < size; ++i) {
3964 MonoMethod *cm = vtable [i];
3965 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3966 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3968 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3976 #if VERIFY_INTERFACE_VTABLE_CODE
3978 mono_method_try_get_vtable_index (MonoMethod *method)
3980 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3981 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3982 if (imethod->declaring->is_generic)
3983 return imethod->declaring->slot;
3985 return method->slot;
3989 mono_class_verify_vtable (MonoClass *class)
3992 char *full_name = mono_type_full_name (&class->byval_arg);
3994 printf ("*** Verifying VTable of class '%s' \n", full_name);
3998 if (!class->methods)
4001 for (i = 0; i < class->method.count; ++i) {
4002 MonoMethod *cm = class->methods [i];
4005 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4009 full_name = mono_method_full_name (cm, TRUE);
4011 slot = mono_method_try_get_vtable_index (cm);
4013 if (slot >= class->vtable_size) {
4014 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4018 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4019 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4020 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4021 g_free (other_name);
4024 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4031 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4033 char *method_signature;
4036 for (index = 0; index < onum; ++index) {
4037 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4038 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4040 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4041 type_name = mono_type_full_name (&class->byval_arg);
4042 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4043 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4044 g_free (method_signature);
4046 mono_class_setup_methods (class);
4047 if (class->exception_type) {
4048 char *name = mono_type_get_full_name (class);
4049 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4053 for (index = 0; index < class->method.count; ++index) {
4054 MonoMethod *cm = class->methods [index];
4055 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4057 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4058 g_free (method_signature);
4063 mono_method_get_method_definition (MonoMethod *method)
4065 while (method->is_inflated)
4066 method = ((MonoMethodInflated*)method)->declaring;
4071 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4075 for (i = 0; i < onum; ++i) {
4076 MonoMethod *decl = overrides [i * 2];
4077 MonoMethod *body = overrides [i * 2 + 1];
4079 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4080 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4084 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4085 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4086 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4088 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4092 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4093 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4094 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4096 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4100 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4101 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4105 body = mono_method_get_method_definition (body);
4106 decl = mono_method_get_method_definition (decl);
4108 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4109 char *body_name = mono_method_full_name (body, TRUE);
4110 char *decl_name = mono_method_full_name (decl, TRUE);
4111 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));
4121 mono_class_need_stelemref_method (MonoClass *class)
4123 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4127 * LOCKING: this is supposed to be called with the loader lock held.
4130 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4134 MonoMethod **vtable;
4135 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4136 GPtrArray *ifaces = NULL;
4137 GHashTable *override_map = NULL;
4138 gboolean security_enabled = mono_security_enabled ();
4140 gpointer class_iter;
4141 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4142 int first_non_interface_slot;
4144 GSList *virt_methods = NULL, *l;
4145 int stelemref_slot = 0;
4150 if (overrides && !verify_class_overrides (class, overrides, onum))
4153 ifaces = mono_class_get_implemented_interfaces (class, &error);
4154 if (!mono_error_ok (&error)) {
4155 char *name = mono_type_get_full_name (class);
4156 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)));
4158 mono_error_cleanup (&error);
4160 } else if (ifaces) {
4161 for (i = 0; i < ifaces->len; i++) {
4162 MonoClass *ic = g_ptr_array_index (ifaces, i);
4163 max_vtsize += ic->method.count;
4165 g_ptr_array_free (ifaces, TRUE);
4169 if (class->parent) {
4170 mono_class_init (class->parent);
4171 mono_class_setup_vtable_full (class->parent, in_setup);
4173 if (class->parent->exception_type) {
4174 char *name = mono_type_get_full_name (class->parent);
4175 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4180 max_vtsize += class->parent->vtable_size;
4181 cur_slot = class->parent->vtable_size;
4184 max_vtsize += class->method.count;
4186 /*Array have a slot for stelemref*/
4187 if (mono_class_need_stelemref_method (class)) {
4188 stelemref_slot = cur_slot;
4193 vtable = alloca (sizeof (gpointer) * max_vtsize);
4194 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4196 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4198 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4199 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4202 max_iid = class->max_interface_id;
4203 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4205 /* Optimized version for generic instances */
4206 if (class->generic_class) {
4208 MonoClass *gklass = class->generic_class->container_class;
4211 mono_class_setup_vtable_full (gklass, in_setup);
4212 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4213 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4217 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4218 class->vtable_size = gklass->vtable_size;
4219 for (i = 0; i < gklass->vtable_size; ++i)
4220 if (gklass->vtable [i]) {
4221 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4222 if (!mono_error_ok (&error)) {
4223 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4224 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4226 mono_error_cleanup (&error);
4230 tmp [i]->slot = gklass->vtable [i]->slot;
4232 mono_memory_barrier ();
4233 class->vtable = tmp;
4235 /* Have to set method->slot for abstract virtual methods */
4236 if (class->methods && gklass->methods) {
4237 for (i = 0; i < class->method.count; ++i)
4238 if (class->methods [i]->slot == -1)
4239 class->methods [i]->slot = gklass->methods [i]->slot;
4245 if (class->parent && class->parent->vtable_size) {
4246 MonoClass *parent = class->parent;
4249 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4251 // Also inherit parent interface vtables, just as a starting point.
4252 // This is needed otherwise bug-77127.exe fails when the property methods
4253 // have different names in the iterface and the class, because for child
4254 // classes the ".override" information is not used anymore.
4255 for (i = 0; i < parent->interface_offsets_count; i++) {
4256 MonoClass *parent_interface = parent->interfaces_packed [i];
4257 int interface_offset = mono_class_interface_offset (class, parent_interface);
4258 /*FIXME this is now dead code as this condition will never hold true.
4259 Since interface offsets are inherited then the offset of an interface implemented
4260 by a parent will never be the out of it's vtable boundary.
4262 if (interface_offset >= parent->vtable_size) {
4263 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4266 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4267 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4268 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4269 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4270 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4271 parent_interface_offset + j, parent_interface_offset, j,
4272 interface_offset + j, interface_offset, j));
4279 /*Array have a slot for stelemref*/
4280 if (mono_class_need_stelemref_method (class)) {
4281 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4283 method->slot = stelemref_slot;
4285 g_assert (method->slot == stelemref_slot);
4287 vtable [stelemref_slot] = method;
4290 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4291 /* override interface methods */
4292 for (i = 0; i < onum; i++) {
4293 MonoMethod *decl = overrides [i*2];
4294 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4296 dslot = mono_method_get_vtable_slot (decl);
4298 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4302 dslot += mono_class_interface_offset (class, decl->klass);
4303 vtable [dslot] = overrides [i*2 + 1];
4304 vtable [dslot]->slot = dslot;
4306 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4308 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4310 if (mono_security_core_clr_enabled ())
4311 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4314 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4315 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4318 * Create a list of virtual methods to avoid calling
4319 * mono_class_get_virtual_methods () which is slow because of the metadata
4323 gpointer iter = NULL;
4326 virt_methods = NULL;
4327 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4328 virt_methods = g_slist_prepend (virt_methods, cm);
4330 if (class->exception_type)
4334 // Loop on all implemented interfaces...
4335 for (i = 0; i < class->interface_offsets_count; i++) {
4336 MonoClass *parent = class->parent;
4338 gboolean interface_is_explicitly_implemented_by_class;
4341 ic = class->interfaces_packed [i];
4342 ic_offset = mono_class_interface_offset (class, ic);
4344 mono_class_setup_methods (ic);
4345 if (ic->exception_type)
4348 // Check if this interface is explicitly implemented (instead of just inherited)
4349 if (parent != NULL) {
4350 int implemented_interfaces_index;
4351 interface_is_explicitly_implemented_by_class = FALSE;
4352 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4353 if (ic == class->interfaces [implemented_interfaces_index]) {
4354 interface_is_explicitly_implemented_by_class = TRUE;
4359 interface_is_explicitly_implemented_by_class = TRUE;
4362 // Loop on all interface methods...
4363 for (im_index = 0; im_index < ic->method.count; im_index++) {
4364 MonoMethod *im = ic->methods [im_index];
4365 int im_slot = ic_offset + im->slot;
4366 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4368 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4371 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4373 // If there is an explicit implementation, just use it right away,
4374 // otherwise look for a matching method
4375 if (override_im == NULL) {
4380 // First look for a suitable method among the class methods
4382 for (l = virt_methods; l; l = l->next) {
4384 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)));
4385 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4386 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4387 vtable [im_slot] = cm;
4388 /* Why do we need this? */
4393 TRACE_INTERFACE_VTABLE (printf ("\n"));
4394 if (class->exception_type) /*Might be set by check_interface_method_override*/
4398 // If the slot is still empty, look in all the inherited virtual methods...
4399 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4400 MonoClass *parent = class->parent;
4401 // Reverse order, so that last added methods are preferred
4402 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4403 MonoMethod *cm = parent->vtable [cm_index];
4405 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));
4406 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4407 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4408 vtable [im_slot] = cm;
4409 /* Why do we need this? */
4415 if (class->exception_type) /*Might be set by check_interface_method_override*/
4417 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4421 g_assert (vtable [im_slot] == override_im);
4426 // If the class is not abstract, check that all its interface slots are full.
4427 // The check is done here and not directly at the end of the loop above because
4428 // it can happen (for injected generic array interfaces) that the same slot is
4429 // processed multiple times (those interfaces have overlapping slots), and it
4430 // will not always be the first pass the one that fills the slot.
4431 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4432 for (i = 0; i < class->interface_offsets_count; i++) {
4436 ic = class->interfaces_packed [i];
4437 ic_offset = mono_class_interface_offset (class, ic);
4439 for (im_index = 0; im_index < ic->method.count; im_index++) {
4440 MonoMethod *im = ic->methods [im_index];
4441 int im_slot = ic_offset + im->slot;
4443 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4446 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4447 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4448 if (vtable [im_slot] == NULL) {
4449 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4456 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4458 for (l = virt_methods; l; l = l->next) {
4461 * If the method is REUSE_SLOT, we must check in the
4462 * base class for a method to override.
4464 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4466 for (k = class->parent; k ; k = k->parent) {
4471 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4472 MonoMethodSignature *cmsig, *m1sig;
4474 cmsig = mono_method_signature (cm);
4475 m1sig = mono_method_signature (m1);
4477 if (!cmsig || !m1sig) {
4478 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4482 if (!strcmp(cm->name, m1->name) &&
4483 mono_metadata_signature_equal (cmsig, m1sig)) {
4485 /* CAS - SecurityAction.InheritanceDemand */
4486 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4487 mono_secman_inheritancedemand_method (cm, m1);
4490 if (mono_security_core_clr_enabled ())
4491 mono_security_core_clr_check_override (class, cm, m1);
4493 slot = mono_method_get_vtable_slot (m1);
4497 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4498 char *body_name = mono_method_full_name (cm, TRUE);
4499 char *decl_name = mono_method_full_name (m1, TRUE);
4500 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));
4506 g_assert (cm->slot < max_vtsize);
4508 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4509 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4510 mono_method_full_name (m1, 1), m1,
4511 mono_method_full_name (cm, 1), cm));
4512 g_hash_table_insert (override_map, m1, cm);
4516 if (k->exception_type)
4526 /*Non final newslot methods must be given a non-interface vtable slot*/
4527 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4531 cm->slot = cur_slot++;
4533 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4534 vtable [cm->slot] = cm;
4537 /* override non interface methods */
4538 for (i = 0; i < onum; i++) {
4539 MonoMethod *decl = overrides [i*2];
4540 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4541 g_assert (decl->slot != -1);
4542 vtable [decl->slot] = overrides [i*2 + 1];
4543 overrides [i * 2 + 1]->slot = decl->slot;
4545 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4546 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4547 mono_method_full_name (decl, 1), decl,
4548 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4549 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4551 if (mono_security_core_clr_enabled ())
4552 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4557 * If a method occupies more than one place in the vtable, and it is
4558 * overriden, then change the other occurances too.
4563 for (i = 0; i < max_vtsize; ++i)
4565 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4567 cm = g_hash_table_lookup (override_map, vtable [i]);
4572 g_hash_table_destroy (override_map);
4573 override_map = NULL;
4576 g_slist_free (virt_methods);
4577 virt_methods = NULL;
4579 /* Ensure that all vtable slots are filled with concrete instance methods */
4580 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4581 for (i = 0; i < cur_slot; ++i) {
4582 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4583 char *type_name = mono_type_get_full_name (class);
4584 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4585 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));
4587 g_free (method_name);
4593 if (class->generic_class) {
4594 MonoClass *gklass = class->generic_class->container_class;
4596 mono_class_init (gklass);
4598 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4600 /* Check that the vtable_size value computed in mono_class_init () is correct */
4601 if (class->vtable_size)
4602 g_assert (cur_slot == class->vtable_size);
4603 class->vtable_size = cur_slot;
4606 /* Try to share the vtable with our parent. */
4607 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4608 mono_memory_barrier ();
4609 class->vtable = class->parent->vtable;
4611 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4612 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4613 mono_memory_barrier ();
4614 class->vtable = tmp;
4617 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4618 if (mono_print_vtable) {
4621 print_implemented_interfaces (class);
4623 for (i = 0; i <= max_iid; i++)
4624 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4627 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4628 class->vtable_size, icount);
4630 for (i = 0; i < cur_slot; ++i) {
4635 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4636 mono_method_full_name (cm, TRUE));
4642 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4643 class->name, max_iid);
4645 for (i = 0; i < class->interface_count; i++) {
4646 ic = class->interfaces [i];
4647 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4648 mono_class_interface_offset (class, ic),
4649 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4652 for (k = class->parent; k ; k = k->parent) {
4653 for (i = 0; i < k->interface_count; i++) {
4654 ic = k->interfaces [i];
4655 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4656 mono_class_interface_offset (class, ic),
4657 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4663 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4668 char *name = mono_type_get_full_name (class);
4669 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4672 g_hash_table_destroy (override_map);
4674 g_slist_free (virt_methods);
4679 * mono_method_get_vtable_slot:
4681 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4682 * LOCKING: Acquires the loader lock.
4684 * FIXME Use proper MonoError machinery here.
4687 mono_method_get_vtable_slot (MonoMethod *method)
4689 if (method->slot == -1) {
4690 mono_class_setup_vtable (method->klass);
4691 if (method->klass->exception_type)
4693 if (method->slot == -1) {
4697 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4698 g_assert (method->klass->generic_class);
4699 gklass = method->klass->generic_class->container_class;
4700 mono_class_setup_methods (method->klass);
4701 g_assert (method->klass->methods);
4702 for (i = 0; i < method->klass->method.count; ++i) {
4703 if (method->klass->methods [i] == method)
4706 g_assert (i < method->klass->method.count);
4707 g_assert (gklass->methods);
4708 method->slot = gklass->methods [i]->slot;
4710 g_assert (method->slot != -1);
4712 return method->slot;
4716 * mono_method_get_vtable_index:
4719 * Returns the index into the runtime vtable to access the method or,
4720 * in the case of a virtual generic method, the virtual generic method
4721 * thunk. Returns -1 on failure.
4723 * FIXME Use proper MonoError machinery here.
4726 mono_method_get_vtable_index (MonoMethod *method)
4728 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4729 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4730 if (imethod->declaring->is_generic)
4731 return mono_method_get_vtable_slot (imethod->declaring);
4733 return mono_method_get_vtable_slot (method);
4736 static MonoMethod *default_ghc = NULL;
4737 static MonoMethod *default_finalize = NULL;
4738 static int finalize_slot = -1;
4739 static int ghc_slot = -1;
4742 initialize_object_slots (MonoClass *class)
4747 if (class == mono_defaults.object_class) {
4748 mono_class_setup_vtable (class);
4749 for (i = 0; i < class->vtable_size; ++i) {
4750 MonoMethod *cm = class->vtable [i];
4752 if (!strcmp (cm->name, "GetHashCode"))
4754 else if (!strcmp (cm->name, "Finalize"))
4758 g_assert (ghc_slot > 0);
4759 default_ghc = class->vtable [ghc_slot];
4761 g_assert (finalize_slot > 0);
4762 default_finalize = class->vtable [finalize_slot];
4767 MonoMethod *array_method;
4769 } GenericArrayMethodInfo;
4771 static int generic_array_method_num = 0;
4772 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4775 generic_array_methods (MonoClass *class)
4777 int i, count_generic = 0;
4778 GList *list = NULL, *tmp;
4779 if (generic_array_method_num)
4780 return generic_array_method_num;
4781 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4782 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4783 for (i = 0; i < class->parent->method.count; i++) {
4784 MonoMethod *m = class->parent->methods [i];
4785 if (!strncmp (m->name, "InternalArray__", 15)) {
4787 list = g_list_prepend (list, m);
4790 list = g_list_reverse (list);
4791 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4793 for (tmp = list; tmp; tmp = tmp->next) {
4794 const char *mname, *iname;
4796 MonoMethod *m = tmp->data;
4797 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4798 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4800 generic_array_method_info [i].array_method = m;
4801 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4802 iname = "System.Collections.Generic.ICollection`1.";
4803 mname = m->name + 27;
4804 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4805 iname = "System.Collections.Generic.IEnumerable`1.";
4806 mname = m->name + 27;
4807 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4808 iname = "System.Collections.Generic.IReadOnlyList`1.";
4809 mname = m->name + strlen (ireadonlylist_prefix);
4810 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4811 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4812 mname = m->name + strlen (ireadonlycollection_prefix);
4813 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4814 iname = "System.Collections.Generic.IList`1.";
4815 mname = m->name + 15;
4817 g_assert_not_reached ();
4820 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4821 strcpy (name, iname);
4822 strcpy (name + strlen (iname), mname);
4823 generic_array_method_info [i].name = name;
4826 /*g_print ("array generic methods: %d\n", count_generic);*/
4828 generic_array_method_num = count_generic;
4830 return generic_array_method_num;
4834 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4836 MonoGenericContext tmp_context;
4839 tmp_context.class_inst = NULL;
4840 tmp_context.method_inst = iface->generic_class->context.class_inst;
4841 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4843 for (i = 0; i < generic_array_method_num; i++) {
4844 MonoMethod *m = generic_array_method_info [i].array_method;
4845 MonoMethod *inflated;
4847 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4848 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4853 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4855 int null_length = strlen ("(null)");
4856 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4857 char *s = mono_image_alloc (image, len);
4860 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4861 g_assert (result == len - 1);
4867 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4869 gpointer exception_data = NULL;
4871 switch (error->exception_type) {
4872 case MONO_EXCEPTION_TYPE_LOAD:
4873 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4876 case MONO_EXCEPTION_MISSING_METHOD:
4877 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4880 case MONO_EXCEPTION_MISSING_FIELD: {
4881 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4882 const char *class_name;
4885 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4887 class_name = error->klass->name;
4889 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4892 g_free ((void*)class_name);
4896 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4899 if (error->ref_only)
4900 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.";
4902 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4904 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4908 case MONO_EXCEPTION_BAD_IMAGE:
4909 exception_data = error->msg;
4913 g_assert_not_reached ();
4916 mono_class_set_failure (class, error->exception_type, exception_data);
4921 * @class: the class to initialize
4923 * Compute the instance_size, class_size and other infos that cannot be
4924 * computed at mono_class_get() time. Also compute vtable_size if possible.
4925 * Returns TRUE on success or FALSE if there was a problem in loading
4926 * the type (incorrect assemblies, missing assemblies, methods, etc).
4928 * LOCKING: Acquires the loader lock.
4931 mono_class_init (MonoClass *class)
4934 MonoCachedClassInfo cached_info;
4935 gboolean has_cached_info;
4939 /* Double-checking locking pattern */
4940 if (class->inited || class->exception_type)
4941 return class->exception_type == MONO_EXCEPTION_NONE;
4943 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4945 /* We do everything inside the lock to prevent races */
4946 mono_loader_lock ();
4948 if (class->inited || class->exception_type) {
4949 mono_loader_unlock ();
4950 /* Somebody might have gotten in before us */
4951 return class->exception_type == MONO_EXCEPTION_NONE;
4954 if (class->init_pending) {
4955 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4959 class->init_pending = 1;
4961 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4962 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4967 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4968 MonoClass *element_class = class->element_class;
4969 if (!element_class->inited)
4970 mono_class_init (element_class);
4971 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4972 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4977 /* CAS - SecurityAction.InheritanceDemand */
4978 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4979 mono_secman_inheritancedemand_class (class, class->parent);
4982 mono_stats.initialized_class_count++;
4984 if (class->generic_class && !class->generic_class->is_dynamic) {
4985 MonoClass *gklass = class->generic_class->container_class;
4987 mono_stats.generic_class_count++;
4989 class->method = gklass->method;
4990 class->field = gklass->field;
4992 mono_class_init (gklass);
4993 // FIXME: Why is this needed ?
4994 if (!gklass->exception_type)
4995 mono_class_setup_methods (gklass);
4996 if (gklass->exception_type) {
4997 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5001 if (MONO_CLASS_IS_INTERFACE (class))
5002 class->interface_id = mono_get_unique_iid (class);
5005 if (class->parent && !class->parent->inited)
5006 mono_class_init (class->parent);
5008 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5010 if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5011 class->nested_classes_inited = TRUE;
5014 * Computes the size used by the fields, and their locations
5016 if (has_cached_info) {
5017 class->instance_size = cached_info.instance_size;
5018 class->sizes.class_size = cached_info.class_size;
5019 class->packing_size = cached_info.packing_size;
5020 class->min_align = cached_info.min_align;
5021 class->blittable = cached_info.blittable;
5022 class->has_references = cached_info.has_references;
5023 class->has_static_refs = cached_info.has_static_refs;
5024 class->no_special_static_fields = cached_info.no_special_static_fields;
5027 if (!class->size_inited){
5028 mono_class_setup_fields (class);
5029 if (class->exception_type || mono_loader_get_last_error ())
5033 /* Initialize arrays */
5035 class->method.count = 3 + (class->rank > 1? 2: 1);
5037 if (class->interface_count) {
5038 int count_generic = generic_array_methods (class);
5039 class->method.count += class->interface_count * count_generic;
5043 mono_class_setup_supertypes (class);
5046 initialize_object_slots (class);
5049 * Initialize the rest of the data without creating a generic vtable if possible.
5050 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5051 * also avoid computing a generic vtable.
5053 if (has_cached_info) {
5055 class->vtable_size = cached_info.vtable_size;
5056 class->has_finalize = cached_info.has_finalize;
5057 class->has_finalize_inited = TRUE;
5058 class->ghcimpl = cached_info.ghcimpl;
5059 class->has_cctor = cached_info.has_cctor;
5060 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5061 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5062 * The first slot if for array with.
5064 static int szarray_vtable_size[2] = { 0 };
5066 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5069 if (!szarray_vtable_size [slot]) {
5070 mono_class_setup_vtable (class);
5071 szarray_vtable_size [slot] = class->vtable_size;
5073 class->vtable_size = szarray_vtable_size[slot];
5075 class->has_finalize_inited = TRUE;
5076 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5077 MonoClass *gklass = class->generic_class->container_class;
5079 /* Generic instance case */
5080 class->ghcimpl = gklass->ghcimpl;
5081 class->has_finalize = mono_class_has_finalizer (gklass);
5082 class->has_finalize_inited = TRUE;
5083 class->has_cctor = gklass->has_cctor;
5085 mono_class_setup_vtable (gklass);
5086 if (gklass->exception_type) {
5087 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5091 class->vtable_size = gklass->vtable_size;
5095 /* ghcimpl is not currently used
5097 if (class->parent) {
5098 MonoMethod *cmethod = class->vtable [ghc_slot];
5099 if (cmethod->is_inflated)
5100 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5101 if (cmethod == default_ghc) {
5107 /* C# doesn't allow interfaces to have cctors */
5108 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5109 MonoMethod *cmethod = NULL;
5111 if (class->type_token) {
5112 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5113 /* The find_method function ignores the 'flags' argument */
5114 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5115 class->has_cctor = 1;
5117 mono_class_setup_methods (class);
5118 if (class->exception_type)
5121 for (i = 0; i < class->method.count; ++i) {
5122 MonoMethod *method = class->methods [i];
5123 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5124 (strcmp (".cctor", method->name) == 0)) {
5125 class->has_cctor = 1;
5133 if (class->parent) {
5134 int first_iface_slot;
5135 /* This will compute class->parent->vtable_size for some classes */
5136 mono_class_init (class->parent);
5137 if (class->parent->exception_type) {
5138 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5141 if (mono_loader_get_last_error ())
5143 if (!class->parent->vtable_size) {
5144 /* FIXME: Get rid of this somehow */
5145 mono_class_setup_vtable (class->parent);
5146 if (class->parent->exception_type) {
5147 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5150 if (mono_loader_get_last_error ())
5153 first_iface_slot = class->parent->vtable_size;
5154 if (mono_class_need_stelemref_method (class))
5156 setup_interface_offsets (class, first_iface_slot, TRUE);
5158 setup_interface_offsets (class, 0, TRUE);
5161 if (mono_security_core_clr_enabled ())
5162 mono_security_core_clr_check_inheritance (class);
5164 if (mono_loader_get_last_error ()) {
5165 if (class->exception_type == MONO_EXCEPTION_NONE) {
5166 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5168 mono_loader_clear_error ();
5171 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5172 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5177 /* Because of the double-checking locking pattern */
5178 mono_memory_barrier ();
5180 class->init_pending = 0;
5182 mono_loader_unlock ();
5184 if (mono_debugger_class_init_func)
5185 mono_debugger_class_init_func (class);
5187 return class->exception_type == MONO_EXCEPTION_NONE;
5191 * mono_class_has_finalizer:
5193 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5197 mono_class_has_finalizer (MonoClass *klass)
5199 if (!klass->has_finalize_inited) {
5200 MonoClass *class = klass;
5202 mono_loader_lock ();
5204 /* Interfaces and valuetypes are not supposed to have finalizers */
5205 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5206 MonoMethod *cmethod = NULL;
5208 if (class->parent && class->parent->has_finalize) {
5209 class->has_finalize = 1;
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 ())
5219 cmethod = class->vtable [finalize_slot];
5223 g_assert (class->vtable_size > finalize_slot);
5225 class->has_finalize = 0;
5226 if (class->parent) {
5227 if (cmethod->is_inflated)
5228 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5229 if (cmethod != default_finalize) {
5230 class->has_finalize = 1;
5237 mono_memory_barrier ();
5238 klass->has_finalize_inited = TRUE;
5240 mono_loader_unlock ();
5243 return klass->has_finalize;
5246 mono_loader_unlock ();
5251 mono_is_corlib_image (MonoImage *image)
5253 /* FIXME: allow the dynamic case for our compilers and with full trust */
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 EnterCriticalSection (&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 LeaveCriticalSection (&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 && image->assembly->dynamic && 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 EnterCriticalSection (&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 LeaveCriticalSection (&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 (klass->image->dynamic) {
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;
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)
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->dynamic) {
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?
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->dynamic) {
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->dynamic) {
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->dynamic && 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 (candidate->image->dynamic && !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 (klass->image->dynamic) {
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->dynamic) {
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 && !klass->image->dynamic) {
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_space: 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)
10062 mono_error_init (error);
10064 if (klass->interfaces_inited)
10067 mono_loader_lock ();
10069 if (klass->interfaces_inited) {
10070 mono_loader_unlock ();
10074 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10075 MonoType *args [1];
10077 /* generic IList, ICollection, IEnumerable */
10078 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10079 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
10081 args [0] = &klass->element_class->byval_arg;
10082 klass->interfaces [0] = mono_class_bind_generic_parameters (
10083 mono_defaults.generic_ilist_class, 1, args, FALSE);
10084 if (klass->interface_count > 1)
10085 klass->interfaces [1] = mono_class_bind_generic_parameters (
10086 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10087 } else if (klass->generic_class) {
10088 MonoClass *gklass = klass->generic_class->container_class;
10090 klass->interface_count = gklass->interface_count;
10091 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
10092 for (i = 0; i < klass->interface_count; i++) {
10093 klass->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"));
10096 klass->interfaces = NULL;
10102 mono_memory_barrier ();
10104 klass->interfaces_inited = TRUE;
10106 mono_loader_unlock ();
10110 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10112 MonoClass *class = field->parent;
10113 MonoImage *image = class->image;
10114 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10115 int field_idx = field - class->fields;
10117 mono_error_init (error);
10120 MonoClassField *gfield = >d->fields [field_idx];
10121 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10122 if (!mono_error_ok (error)) {
10123 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10124 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10128 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10129 if (!mono_error_ok (error)) {
10130 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10131 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10136 guint32 cols [MONO_FIELD_SIZE];
10137 MonoGenericContainer *container = NULL;
10138 int idx = class->field.first + field_idx;
10140 /*FIXME, in theory we do not lazy load SRE fields*/
10141 g_assert (!image->dynamic);
10143 if (class->generic_container) {
10144 container = class->generic_container;
10146 container = gtd->generic_container;
10147 g_assert (container);
10150 /* class->field.first and idx points into the fieldptr table */
10151 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10153 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10154 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10155 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10159 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10161 mono_metadata_decode_value (sig, &sig);
10162 /* FIELD signature == 0x06 */
10163 g_assert (*sig == 0x06);
10164 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10166 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10171 mono_field_resolve_flags (MonoClassField *field)
10173 MonoClass *class = field->parent;
10174 MonoImage *image = class->image;
10175 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10176 int field_idx = field - class->fields;
10180 MonoClassField *gfield = >d->fields [field_idx];
10181 return mono_field_get_flags (gfield);
10183 int idx = class->field.first + field_idx;
10185 /*FIXME, in theory we do not lazy load SRE fields*/
10186 g_assert (!image->dynamic);
10188 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10193 * mono_class_setup_basic_field_info:
10194 * @class: The class to initialize
10196 * Initializes the class->fields array of fields.
10197 * Aquires the loader lock.
10200 mono_class_setup_basic_field_info_locking (MonoClass *class)
10202 mono_loader_lock ();
10203 mono_class_setup_basic_field_info (class);
10204 mono_loader_unlock ();
10208 * mono_class_get_fields_lazy:
10209 * @klass: the MonoClass to act on
10211 * This routine is an iterator routine for retrieving the fields in a class.
10212 * Only minimal information about fields are loaded. Accessors must be used
10213 * for all MonoClassField returned.
10215 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10216 * iterate over all of the elements. When no more values are
10217 * available, the return value is NULL.
10219 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10222 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10224 MonoClassField* field;
10228 mono_class_setup_basic_field_info_locking (klass);
10229 if (!klass->fields)
10231 /* start from the first */
10232 if (klass->field.count) {
10233 return *iter = &klass->fields [0];
10241 if (field < &klass->fields [klass->field.count]) {
10242 return *iter = field;
10248 mono_class_full_name (MonoClass *klass)
10250 return mono_type_full_name (&klass->byval_arg);