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>
47 gboolean mono_print_vtable = FALSE;
50 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
51 guint32 classes_size, class_ext_size;
53 /* Function supplied by the runtime to find classes by name using information from the AOT file */
54 static MonoGetClassFromName get_class_from_name = NULL;
56 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
57 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
58 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
59 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
60 static int generic_array_methods (MonoClass *class);
61 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
63 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
64 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
65 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
66 static guint32 mono_field_resolve_flags (MonoClassField *field);
67 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
68 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
71 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
72 void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass) = NULL;
76 We use gclass recording to allow recursive system f types to be referenced by a parent.
78 Given the following type hierarchy:
80 class TextBox : TextBoxBase<TextBox> {}
81 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
82 class TextInput<T> : Input<T> where T: TextInput<T> {}
85 The runtime tries to load TextBoxBase<>.
86 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
87 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
88 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
90 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
91 at this point, iow, both are registered in the type map and both and a NULL parent. This means
92 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
94 To fix that what we do is to record all generic instantes created while resolving the parent of
95 any generic type definition and, after resolved, correct the parent field if needed.
98 static int record_gclass_instantiation;
99 static GSList *gclass_recorded_list;
100 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
103 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
106 enable_gclass_recording (void)
108 ++record_gclass_instantiation;
112 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
115 disable_gclass_recording (gclass_record_func func, void *user_data)
117 GSList **head = &gclass_recorded_list;
119 g_assert (record_gclass_instantiation > 0);
120 --record_gclass_instantiation;
123 GSList *node = *head;
124 if (func ((MonoClass*)node->data, user_data)) {
126 g_slist_free_1 (node);
132 /* We automatically discard all recorded gclasses when disabled. */
133 if (!record_gclass_instantiation && gclass_recorded_list) {
134 g_slist_free (gclass_recorded_list);
135 gclass_recorded_list = NULL;
140 * mono_class_from_typeref:
141 * @image: a MonoImage
142 * @type_token: a TypeRef token
144 * Creates the MonoClass* structure representing the type defined by
145 * the typeref token valid inside @image.
146 * Returns: the MonoClass* representing the typeref token, NULL ifcould
150 mono_class_from_typeref (MonoImage *image, guint32 type_token)
153 guint32 cols [MONO_TYPEREF_SIZE];
154 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
156 const char *name, *nspace;
160 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, &error)) {
161 mono_trace_warning (MONO_TRACE_TYPE, "Failed to resolve typeref from %s due to '%s'", image->name, mono_error_get_message (&error));
165 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
167 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
168 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
170 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
171 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
172 case MONO_RESOLTION_SCOPE_MODULE:
174 g_error ("null ResolutionScope not yet handled");
175 /* a typedef in disguise */
176 return mono_class_from_name (image, nspace, name);
177 case MONO_RESOLTION_SCOPE_MODULEREF:
178 module = mono_image_load_module (image, idx);
180 return mono_class_from_name (module, nspace, name);
182 char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
185 human_name = mono_stringify_assembly_name (&image->assembly->aname);
186 mono_loader_set_error_type_load (msg, human_name);
192 case MONO_RESOLTION_SCOPE_TYPEREF: {
193 MonoClass *enclosing;
196 if (idx == mono_metadata_token_index (type_token)) {
197 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token));
201 enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
205 if (enclosing->nested_classes_inited && enclosing->ext) {
206 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
207 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
209 if (strcmp (res->name, name) == 0)
213 /* Don't call mono_class_init as we might've been called by it recursively */
214 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
216 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
217 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
218 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
220 if (strcmp (nname, name) == 0) {
221 MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
222 if (!mono_error_ok (&error)) {
223 mono_loader_set_error_from_mono_error (&error);
224 mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
230 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
233 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
236 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
240 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
241 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
245 if (!image->references || !image->references [idx - 1])
246 mono_assembly_load_reference (image, idx - 1);
247 g_assert (image->references [idx - 1]);
249 /* If the assembly did not load, register this as a type load exception */
250 if (image->references [idx - 1] == REFERENCE_MISSING){
251 MonoAssemblyName aname;
254 mono_assembly_get_assemblyref (image, idx - 1, &aname);
255 human_name = mono_stringify_assembly_name (&aname);
256 mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
262 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
267 mono_image_memdup (MonoImage *image, void *data, guint size)
269 void *res = mono_image_alloc (image, size);
270 memcpy (res, data, size);
274 /* Copy everything mono_metadata_free_array free. */
276 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
279 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
281 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
283 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
285 a = g_memdup (a, sizeof (MonoArrayType));
287 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
289 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
294 /* Copy everything mono_metadata_free_method_signature free. */
296 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
300 sig = mono_metadata_signature_dup_full (image, sig);
302 sig->ret = mono_metadata_type_dup (image, sig->ret);
303 for (i = 0; i < sig->param_count; ++i)
304 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
310 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
312 MonoAssembly *ta = klass->image->assembly;
315 name = mono_stringify_assembly_name (&ta->aname);
316 g_string_append_printf (str, ", %s", name);
321 mono_type_name_check_byref (MonoType *type, GString *str)
324 g_string_append_c (str, '&');
328 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
329 MonoTypeNameFormat format)
333 switch (type->type) {
334 case MONO_TYPE_ARRAY: {
335 int i, rank = type->data.array->rank;
336 MonoTypeNameFormat nested_format;
338 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
339 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
341 mono_type_get_name_recurse (
342 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
343 g_string_append_c (str, '[');
345 g_string_append_c (str, '*');
346 for (i = 1; i < rank; i++)
347 g_string_append_c (str, ',');
348 g_string_append_c (str, ']');
350 mono_type_name_check_byref (type, str);
352 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
353 _mono_type_get_assembly_name (type->data.array->eklass, str);
356 case MONO_TYPE_SZARRAY: {
357 MonoTypeNameFormat nested_format;
359 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
360 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
362 mono_type_get_name_recurse (
363 &type->data.klass->byval_arg, str, FALSE, nested_format);
364 g_string_append (str, "[]");
366 mono_type_name_check_byref (type, str);
368 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
369 _mono_type_get_assembly_name (type->data.klass, str);
372 case MONO_TYPE_PTR: {
373 MonoTypeNameFormat nested_format;
375 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
376 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
378 mono_type_get_name_recurse (
379 type->data.type, str, FALSE, nested_format);
380 g_string_append_c (str, '*');
382 mono_type_name_check_byref (type, str);
384 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
385 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
390 if (!mono_generic_param_info (type->data.generic_param))
391 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
393 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
395 mono_type_name_check_byref (type, str);
399 klass = mono_class_from_mono_type (type);
400 if (klass->nested_in) {
401 mono_type_get_name_recurse (
402 &klass->nested_in->byval_arg, str, TRUE, format);
403 if (format == MONO_TYPE_NAME_FORMAT_IL)
404 g_string_append_c (str, '.');
406 g_string_append_c (str, '+');
407 } else if (*klass->name_space) {
408 g_string_append (str, klass->name_space);
409 g_string_append_c (str, '.');
411 if (format == MONO_TYPE_NAME_FORMAT_IL) {
412 char *s = strchr (klass->name, '`');
413 int len = s ? s - klass->name : strlen (klass->name);
415 g_string_append_len (str, klass->name, len);
417 g_string_append (str, klass->name);
420 if (klass->generic_class) {
421 MonoGenericClass *gclass = klass->generic_class;
422 MonoGenericInst *inst = gclass->context.class_inst;
423 MonoTypeNameFormat nested_format;
426 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
427 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
429 if (format == MONO_TYPE_NAME_FORMAT_IL)
430 g_string_append_c (str, '<');
432 g_string_append_c (str, '[');
433 for (i = 0; i < inst->type_argc; i++) {
434 MonoType *t = inst->type_argv [i];
437 g_string_append_c (str, ',');
438 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
439 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
440 g_string_append_c (str, '[');
441 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
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, ']');
446 if (format == MONO_TYPE_NAME_FORMAT_IL)
447 g_string_append_c (str, '>');
449 g_string_append_c (str, ']');
450 } else if (klass->generic_container &&
451 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
452 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
455 if (format == MONO_TYPE_NAME_FORMAT_IL)
456 g_string_append_c (str, '<');
458 g_string_append_c (str, '[');
459 for (i = 0; i < klass->generic_container->type_argc; i++) {
461 g_string_append_c (str, ',');
462 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
464 if (format == MONO_TYPE_NAME_FORMAT_IL)
465 g_string_append_c (str, '>');
467 g_string_append_c (str, ']');
470 mono_type_name_check_byref (type, str);
472 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
473 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
474 _mono_type_get_assembly_name (klass, str);
480 * mono_type_get_name_full:
482 * @format: the format for the return string.
485 * Returns: the string representation in a number of formats:
487 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
488 * returned in the formatrequired by System.Reflection, this is the
489 * inverse of mono_reflection_parse_type ().
491 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
492 * be used by the IL assembler.
494 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
496 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
499 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
503 result = g_string_new ("");
505 mono_type_get_name_recurse (type, result, FALSE, format);
507 return g_string_free (result, FALSE);
511 * mono_type_get_full_name:
514 * Returns: the string representation for type as required by System.Reflection.
515 * The inverse of mono_reflection_parse_type ().
518 mono_type_get_full_name (MonoClass *class)
520 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
524 * mono_type_get_name:
527 * Returns: the string representation for type as it would be represented in IL code.
530 mono_type_get_name (MonoType *type)
532 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
536 * mono_type_get_underlying_type:
539 * Returns: the MonoType for the underlying integer type if @type
540 * is an enum and byref is false, otherwise the type itself.
543 mono_type_get_underlying_type (MonoType *type)
545 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
546 return mono_class_enum_basetype (type->data.klass);
547 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
548 return mono_class_enum_basetype (type->data.generic_class->container_class);
553 * mono_class_is_open_constructed_type:
556 * Returns TRUE if type represents a generics open constructed type.
557 * IOW, not all type parameters required for the instantiation have
558 * been provided or it's a generic type definition.
560 * An open constructed type means it's a non realizable type. Not to
561 * be mixed up with an abstract type - we can't cast or dispatch to
562 * an open type, for example.
565 mono_class_is_open_constructed_type (MonoType *t)
571 case MONO_TYPE_SZARRAY:
572 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
573 case MONO_TYPE_ARRAY:
574 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
576 return mono_class_is_open_constructed_type (t->data.type);
577 case MONO_TYPE_GENERICINST:
578 return t->data.generic_class->context.class_inst->is_open;
579 case MONO_TYPE_CLASS:
580 case MONO_TYPE_VALUETYPE:
581 return t->data.klass->generic_container != NULL;
588 This is a simple function to catch the most common bad instances of generic types.
589 Specially those that might lead to further failures in the runtime.
592 is_valid_generic_argument (MonoType *type)
594 switch (type->type) {
596 //case MONO_TYPE_TYPEDBYREF:
603 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
605 mono_error_init (error);
607 switch (type->type) {
608 case MONO_TYPE_MVAR: {
610 int num = mono_type_get_generic_param_num (type);
611 MonoGenericInst *inst = context->method_inst;
612 if (!inst || !inst->type_argv)
614 if (num >= inst->type_argc) {
615 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
616 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
617 num, info ? info->name : "", inst->type_argc);
621 if (!is_valid_generic_argument (inst->type_argv [num])) {
622 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
623 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
624 num, info ? info->name : "", inst->type_argv [num]->type);
628 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
629 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
630 * ->byref and ->attrs from @type are propagated to the returned type.
632 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
633 nt->byref = type->byref;
634 nt->attrs = type->attrs;
637 case MONO_TYPE_VAR: {
639 int num = mono_type_get_generic_param_num (type);
640 MonoGenericInst *inst = context->class_inst;
643 if (num >= inst->type_argc) {
644 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
645 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
646 num, info ? info->name : "", inst->type_argc);
649 if (!is_valid_generic_argument (inst->type_argv [num])) {
650 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
651 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
652 num, info ? info->name : "", inst->type_argv [num]->type);
655 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
656 nt->byref = type->byref;
657 nt->attrs = type->attrs;
660 case MONO_TYPE_SZARRAY: {
661 MonoClass *eclass = type->data.klass;
662 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
663 if (!inflated || !mono_error_ok (error))
665 nt = mono_metadata_type_dup (image, type);
666 nt->data.klass = mono_class_from_mono_type (inflated);
667 mono_metadata_free_type (inflated);
670 case MONO_TYPE_ARRAY: {
671 MonoClass *eclass = type->data.array->eklass;
672 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
673 if (!inflated || !mono_error_ok (error))
675 nt = mono_metadata_type_dup (image, type);
676 nt->data.array->eklass = mono_class_from_mono_type (inflated);
677 mono_metadata_free_type (inflated);
680 case MONO_TYPE_GENERICINST: {
681 MonoGenericClass *gclass = type->data.generic_class;
682 MonoGenericInst *inst;
684 if (!gclass->context.class_inst->is_open)
687 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
688 if (!mono_error_ok (error))
690 if (inst != gclass->context.class_inst)
691 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
693 if (gclass == type->data.generic_class)
696 nt = mono_metadata_type_dup (image, type);
697 nt->data.generic_class = gclass;
700 case MONO_TYPE_CLASS:
701 case MONO_TYPE_VALUETYPE: {
702 MonoClass *klass = type->data.klass;
703 MonoGenericContainer *container = klass->generic_container;
704 MonoGenericInst *inst;
705 MonoGenericClass *gclass = NULL;
711 /* We can't use context->class_inst directly, since it can have more elements */
712 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
713 if (!mono_error_ok (error))
715 if (inst == container->context.class_inst)
718 gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
720 nt = mono_metadata_type_dup (image, type);
721 nt->type = MONO_TYPE_GENERICINST;
722 nt->data.generic_class = gclass;
732 mono_generic_class_get_context (MonoGenericClass *gclass)
734 return &gclass->context;
738 mono_class_get_context (MonoClass *class)
740 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
744 * mono_class_get_generic_container:
746 * Return the generic container of KLASS which should be a generic type definition.
748 MonoGenericContainer*
749 mono_class_get_generic_container (MonoClass *klass)
751 g_assert (klass->is_generic);
753 return klass->generic_container;
757 * mono_class_get_generic_class:
759 * Return the MonoGenericClass of KLASS, which should be a generic instance.
762 mono_class_get_generic_class (MonoClass *klass)
764 g_assert (klass->is_inflated);
766 return klass->generic_class;
770 * mono_class_inflate_generic_type_with_mempool:
771 * @mempool: a mempool
773 * @context: a generics context
774 * @error: error context
776 * The same as mono_class_inflate_generic_type, but allocates the MonoType
777 * from mempool if it is non-NULL. If it is NULL, the MonoType is
778 * allocated on the heap and is owned by the caller.
779 * The returned type can potentially be the same as TYPE, so it should not be
780 * modified by the caller, and it should be freed using mono_metadata_free_type ().
783 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
785 MonoType *inflated = NULL;
786 mono_error_init (error);
789 inflated = inflate_generic_type (image, type, context, error);
790 if (!mono_error_ok (error))
794 MonoType *shared = mono_metadata_get_shared_type (type);
799 return mono_metadata_type_dup (image, type);
803 mono_stats.inflated_type_count++;
808 * mono_class_inflate_generic_type:
810 * @context: a generics context
812 * If @type is a generic type and @context is not NULL, instantiate it using the
813 * generics context @context.
815 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
816 * on the heap and is owned by the caller. Returns NULL on error.
818 * @deprecated Please use mono_class_inflate_generic_type_checked instead
821 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
825 result = mono_class_inflate_generic_type_checked (type, context, &error);
827 if (!mono_error_ok (&error)) {
828 mono_error_cleanup (&error);
835 * mono_class_inflate_generic_type:
837 * @context: a generics context
838 * @error: error context to use
840 * If @type is a generic type and @context is not NULL, instantiate it using the
841 * generics context @context.
843 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
844 * on the heap and is owned by the caller.
847 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
849 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
853 * mono_class_inflate_generic_type_no_copy:
855 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
859 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
861 MonoType *inflated = NULL;
863 mono_error_init (error);
865 inflated = inflate_generic_type (image, type, context, error);
866 if (!mono_error_ok (error))
873 mono_stats.inflated_type_count++;
878 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
883 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
884 if (!mono_error_ok (error))
887 res = mono_class_from_mono_type (inflated);
888 mono_metadata_free_type (inflated);
893 * mono_class_inflate_generic_class:
895 * Inflate the class GKLASS with CONTEXT.
898 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
903 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
904 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
911 static MonoGenericContext
912 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
914 MonoGenericInst *class_inst = NULL;
915 MonoGenericInst *method_inst = NULL;
916 MonoGenericContext res = { NULL, NULL };
918 mono_error_init (error);
920 if (context->class_inst) {
921 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
922 if (!mono_error_ok (error))
926 if (context->method_inst) {
927 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
928 if (!mono_error_ok (error))
932 res.class_inst = class_inst;
933 res.method_inst = method_inst;
939 * mono_class_inflate_generic_method:
940 * @method: a generic method
941 * @context: a generics context
943 * Instantiate the generic method @method using the generics context @context.
945 * Returns: the new instantiated method
948 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
950 return mono_class_inflate_generic_method_full (method, NULL, context);
954 * mono_class_inflate_generic_method_full:
956 * Instantiate method @method with the generic context @context.
957 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
958 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
961 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
964 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
965 if (!mono_error_ok (&error))
966 /*FIXME do proper error handling - on this case, kill this function. */
967 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
973 * mono_class_inflate_generic_method_full_checked:
974 * Same as mono_class_inflate_generic_method_full but return failure using @error.
977 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
980 MonoMethodInflated *iresult, *cached;
981 MonoMethodSignature *sig;
982 MonoGenericContext tmp_context;
983 gboolean is_mb_open = FALSE;
985 mono_error_init (error);
987 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
988 while (method->is_inflated) {
989 MonoGenericContext *method_context = mono_method_get_context (method);
990 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
992 tmp_context = inflate_generic_context (method_context, context, error);
993 if (!mono_error_ok (error))
995 context = &tmp_context;
997 if (mono_metadata_generic_context_equal (method_context, context))
1000 method = imethod->declaring;
1004 * A method only needs to be inflated if the context has argument for which it is
1007 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1008 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1011 if (!((method->is_generic && context->method_inst) ||
1012 (method->klass->generic_container && context->class_inst)))
1016 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1017 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1018 * This is opposite to the way non-SRE MethodInfos behave.
1020 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1022 * void Example<T> () {
1026 * In Example, the method token must be encoded as: "void Example<!!0>()"
1028 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1029 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1031 * On the other hand, inflating a non-SRE generic method with its own arguments should
1032 * return itself. For example:
1034 * MethodInfo m = ... //m is a generic method definition
1035 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1038 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1039 * what happens with regular methods.
1041 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1042 * everything should behave like a regular type or method.
1045 is_mb_open = method->is_generic &&
1046 method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1047 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1049 iresult = g_new0 (MonoMethodInflated, 1);
1050 iresult->context = *context;
1051 iresult->declaring = method;
1052 iresult->method.method.is_mb_open = is_mb_open;
1054 if (!context->method_inst && method->is_generic)
1055 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1057 if (!context->class_inst) {
1058 g_assert (!iresult->declaring->klass->generic_class);
1059 if (iresult->declaring->klass->generic_container)
1060 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1061 else if (iresult->declaring->klass->generic_class)
1062 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1065 mono_loader_lock ();
1066 cached = mono_method_inflated_lookup (iresult, FALSE);
1068 mono_loader_unlock ();
1070 return (MonoMethod*)cached;
1073 mono_stats.inflated_method_count++;
1075 inflated_methods_size += sizeof (MonoMethodInflated);
1077 sig = mono_method_signature (method);
1079 char *name = mono_type_get_full_name (method->klass);
1080 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1086 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1088 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1091 result = (MonoMethod *) iresult;
1092 result->is_inflated = TRUE;
1093 result->is_generic = FALSE;
1094 result->sre_method = FALSE;
1095 result->signature = NULL;
1096 result->is_mb_open = is_mb_open;
1098 if (!context->method_inst) {
1099 /* Set the generic_container of the result to the generic_container of method */
1100 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1102 if (generic_container) {
1103 result->is_generic = 1;
1104 mono_method_set_generic_container (result, generic_container);
1108 if (!klass_hint || !klass_hint->generic_class ||
1109 klass_hint->generic_class->container_class != method->klass ||
1110 klass_hint->generic_class->context.class_inst != context->class_inst)
1113 if (method->klass->generic_container)
1114 result->klass = klass_hint;
1116 if (!result->klass) {
1117 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1118 if (!mono_error_ok (error))
1121 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1123 mono_metadata_free_type (inflated);
1127 * FIXME: This should hold, but it doesn't:
1129 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1130 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1131 * g_assert (result->is_generic);
1134 * Fixing this here causes other things to break, hence a very
1135 * ugly hack in mini-trampolines.c - see
1136 * is_generic_method_definition().
1139 mono_method_inflated_lookup (iresult, TRUE);
1140 mono_loader_unlock ();
1144 mono_loader_unlock ();
1150 * mono_get_inflated_method:
1152 * Obsolete. We keep it around since it's mentioned in the public API.
1155 mono_get_inflated_method (MonoMethod *method)
1161 * mono_method_get_context_general:
1163 * @uninflated: handle uninflated methods?
1165 * Returns the generic context of a method or NULL if it doesn't have
1166 * one. For an inflated method that's the context stored in the
1167 * method. Otherwise it's in the method's generic container or in the
1168 * generic container of the method's class.
1171 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1173 if (method->is_inflated) {
1174 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1175 return &imethod->context;
1179 if (method->is_generic)
1180 return &(mono_method_get_generic_container (method)->context);
1181 if (method->klass->generic_container)
1182 return &method->klass->generic_container->context;
1187 * mono_method_get_context:
1190 * Returns the generic context for method if it's inflated, otherwise
1194 mono_method_get_context (MonoMethod *method)
1196 return mono_method_get_context_general (method, FALSE);
1200 * mono_method_get_generic_container:
1202 * Returns the generic container of METHOD, which should be a generic method definition.
1203 * Returns NULL if METHOD is not a generic method definition.
1204 * LOCKING: Acquires the loader lock.
1206 MonoGenericContainer*
1207 mono_method_get_generic_container (MonoMethod *method)
1209 MonoGenericContainer *container;
1211 if (!method->is_generic)
1214 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1215 g_assert (container);
1221 * mono_method_set_generic_container:
1223 * Sets the generic container of METHOD to CONTAINER.
1224 * LOCKING: Acquires the loader lock.
1227 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1229 g_assert (method->is_generic);
1231 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1235 * mono_class_find_enum_basetype:
1236 * @class: The enum class
1238 * Determine the basetype of an enum by iterating through its fields. We do this
1239 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1242 mono_class_find_enum_basetype (MonoClass *class)
1244 MonoGenericContainer *container = NULL;
1245 MonoImage *m = class->image;
1246 const int top = class->field.count;
1249 g_assert (class->enumtype);
1251 if (class->generic_container)
1252 container = class->generic_container;
1253 else if (class->generic_class) {
1254 MonoClass *gklass = class->generic_class->container_class;
1256 container = gklass->generic_container;
1257 g_assert (container);
1261 * Fetch all the field information.
1263 for (i = 0; i < top; i++){
1265 guint32 cols [MONO_FIELD_SIZE];
1266 int idx = class->field.first + i;
1269 /* class->field.first and idx points into the fieldptr table */
1270 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1272 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1275 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1278 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1279 mono_metadata_decode_value (sig, &sig);
1280 /* FIELD signature == 0x06 */
1284 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1287 if (class->generic_class) {
1288 //FIXME do we leak here?
1289 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1290 ftype->attrs = cols [MONO_FIELD_FLAGS];
1300 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1303 mono_type_has_exceptions (MonoType *type)
1305 switch (type->type) {
1306 case MONO_TYPE_CLASS:
1307 case MONO_TYPE_VALUETYPE:
1308 case MONO_TYPE_SZARRAY:
1309 return type->data.klass->exception_type;
1310 case MONO_TYPE_ARRAY:
1311 return type->data.array->eklass->exception_type;
1312 case MONO_TYPE_GENERICINST:
1313 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1321 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1325 mono_class_alloc (MonoClass *class, int size)
1327 if (class->generic_class)
1328 return mono_image_set_alloc (class->generic_class->owner, size);
1330 return mono_image_alloc (class->image, size);
1334 mono_class_alloc0 (MonoClass *class, int size)
1338 res = mono_class_alloc (class, size);
1339 memset (res, 0, size);
1343 #define mono_class_new0(class,struct_type, n_structs) \
1344 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1347 * mono_class_setup_basic_field_info:
1348 * @class: The class to initialize
1350 * Initializes the class->fields.
1351 * LOCKING: Assumes the loader lock is held.
1354 mono_class_setup_basic_field_info (MonoClass *class)
1356 MonoClassField *field;
1364 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1365 image = class->image;
1366 top = class->field.count;
1368 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1370 * This happens when a generic instance of an unfinished generic typebuilder
1371 * is used as an element type for creating an array type. We can't initialize
1372 * the fields of this class using the fields of gklass, since gklass is not
1373 * finished yet, fields could be added to it later.
1379 mono_class_setup_basic_field_info (gtd);
1381 top = gtd->field.count;
1382 class->field.first = gtd->field.first;
1383 class->field.count = gtd->field.count;
1386 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1389 * Fetch all the field information.
1391 for (i = 0; i < top; i++){
1392 field = &class->fields [i];
1393 field->parent = class;
1396 field->name = mono_field_get_name (>d->fields [i]);
1398 int idx = class->field.first + i;
1399 /* class->field.first and idx points into the fieldptr table */
1400 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1401 /* The name is needed for fieldrefs */
1402 field->name = mono_metadata_string_heap (image, name_idx);
1408 * mono_class_setup_fields:
1409 * @class: The class to initialize
1411 * Initializes the class->fields.
1412 * LOCKING: Assumes the loader lock is held.
1415 mono_class_setup_fields (MonoClass *class)
1418 MonoImage *m = class->image;
1420 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1421 int i, blittable = TRUE;
1422 guint32 real_size = 0;
1423 guint32 packing_size = 0;
1424 gboolean explicit_size;
1425 MonoClassField *field;
1426 MonoGenericContainer *container = NULL;
1427 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1430 * FIXME: We have a race condition here. It's possible that this function returns
1431 * to its caller with `instance_size` set to `0` instead of the actual size. This
1432 * is not a problem when the function is called recursively on the same class,
1433 * because the size will be initialized by the outer invocation. What follows is a
1434 * description of how it can occur in other cases, too. There it is a problem,
1435 * because it can lead to the GC being asked to allocate an object of size `0`,
1436 * which SGen chokes on. The race condition is triggered infrequently by
1437 * `tests/sgen-suspend.cs`.
1439 * This function is called for a class whenever one of its subclasses is inited.
1440 * For example, it's called for every subclass of Object. What it does is this:
1442 * if (class->setup_fields_called)
1445 * class->instance_size = 0;
1447 * class->setup_fields_called = 1;
1448 * ... critical point
1449 * class->instance_size = actual_instance_size;
1451 * The last two steps are sometimes reversed, but that only changes the way in which
1452 * the race condition works.
1454 * Assume thread A goes through this function and makes it to the critical point.
1455 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1456 * immediately, but `instance_size` is incorrect.
1458 * The other case looks like this:
1460 * if (class->setup_fields_called)
1462 * ... critical point X
1463 * class->instance_size = 0;
1464 * ... critical point Y
1465 * class->instance_size = actual_instance_size;
1467 * class->setup_fields_called = 1;
1469 * Assume thread A goes through the function and makes it to critical point X. Now
1470 * thread B runs through the whole of the function, returning, assuming
1471 * `instance_size` is set. At that point thread A gets to run and makes it to
1472 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1475 if (class->setup_fields_called)
1478 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1480 * This happens when a generic instance of an unfinished generic typebuilder
1481 * is used as an element type for creating an array type. We can't initialize
1482 * the fields of this class using the fields of gklass, since gklass is not
1483 * finished yet, fields could be added to it later.
1488 mono_class_setup_basic_field_info (class);
1489 top = class->field.count;
1492 mono_class_setup_fields (gtd);
1493 if (gtd->exception_type) {
1494 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1499 class->instance_size = 0;
1501 class->sizes.class_size = 0;
1503 if (class->parent) {
1504 /* For generic instances, class->parent might not have been initialized */
1505 mono_class_init (class->parent);
1506 if (!class->parent->size_inited) {
1507 mono_class_setup_fields (class->parent);
1508 if (class->parent->exception_type) {
1509 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1513 class->instance_size += class->parent->instance_size;
1514 class->min_align = class->parent->min_align;
1515 /* we use |= since it may have been set already */
1516 class->has_references |= class->parent->has_references;
1517 blittable = class->parent->blittable;
1519 class->instance_size = sizeof (MonoObject);
1520 class->min_align = 1;
1523 /* We can't really enable 16 bytes alignment until the GC supports it.
1524 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1525 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1526 Bug #506144 is an example of this issue.
1528 if (class->simd_type)
1529 class->min_align = 16;
1531 /* Get the real size */
1532 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1534 if (explicit_size) {
1535 if ((packing_size & 0xfffffff0) != 0) {
1536 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1537 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1540 class->packing_size = packing_size;
1541 real_size += class->instance_size;
1545 if (explicit_size && real_size) {
1546 class->instance_size = MAX (real_size, class->instance_size);
1548 class->blittable = blittable;
1549 mono_memory_barrier ();
1550 class->size_inited = 1;
1551 class->fields_inited = 1;
1552 class->setup_fields_called = 1;
1556 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1559 /* Prevent infinite loops if the class references itself */
1560 class->setup_fields_called = 1;
1562 if (class->generic_container) {
1563 container = class->generic_container;
1565 container = gtd->generic_container;
1566 g_assert (container);
1570 * Fetch all the field information.
1572 for (i = 0; i < top; i++){
1573 int idx = class->field.first + i;
1574 field = &class->fields [i];
1576 field->parent = class;
1579 mono_field_resolve_type (field, &error);
1580 if (!mono_error_ok (&error)) {
1581 /*mono_field_resolve_type already failed class*/
1582 mono_error_cleanup (&error);
1586 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1587 g_assert (field->type);
1590 if (mono_field_is_deleted (field))
1593 MonoClassField *gfield = >d->fields [i];
1594 field->offset = gfield->offset;
1596 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1598 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1599 field->offset = offset;
1601 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1602 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1605 if (field->offset < -1) { /*-1 is used to encode special static fields */
1606 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1612 /* Only do these checks if we still think this type is blittable */
1613 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1614 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1617 MonoClass *field_class = mono_class_from_mono_type (field->type);
1619 mono_class_setup_fields (field_class);
1620 if (field_class->exception_type) {
1621 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1625 if (!field_class || !field_class->blittable)
1630 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1631 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1632 blittable = class->element_class->blittable;
1635 if (mono_type_has_exceptions (field->type)) {
1636 char *class_name = mono_type_get_full_name (class);
1637 char *type_name = mono_type_full_name (field->type);
1639 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1640 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1641 g_free (class_name);
1645 /* The def_value of fields is compute lazily during vtable creation */
1648 if (class == mono_defaults.string_class)
1651 class->blittable = blittable;
1653 if (class->enumtype && !mono_class_enum_basetype (class)) {
1654 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1657 if (explicit_size && real_size) {
1658 class->instance_size = MAX (real_size, class->instance_size);
1661 if (class->exception_type)
1663 mono_class_layout_fields (class);
1665 /*valuetypes can't be neither bigger than 1Mb or empty. */
1666 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1667 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1669 mono_memory_barrier ();
1670 class->fields_inited = 1;
1674 * mono_class_setup_fields_locking:
1675 * @class: The class to initialize
1677 * Initializes the class->fields array of fields.
1678 * Aquires the loader lock.
1681 mono_class_setup_fields_locking (MonoClass *class)
1683 /* This can be checked without locks */
1684 if (class->fields_inited)
1686 mono_loader_lock ();
1687 mono_class_setup_fields (class);
1688 mono_loader_unlock ();
1692 * mono_class_has_references:
1694 * Returns whenever @klass->has_references is set, initializing it if needed.
1695 * Aquires the loader lock.
1698 mono_class_has_references (MonoClass *klass)
1700 if (klass->init_pending) {
1701 /* Be conservative */
1704 mono_class_init (klass);
1706 return klass->has_references;
1711 * mono_type_get_basic_type_from_generic:
1714 * Returns a closed type corresponding to the possibly open type
1718 mono_type_get_basic_type_from_generic (MonoType *type)
1720 /* When we do generic sharing we let type variables stand for reference types. */
1721 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1722 return &mono_defaults.object_class->byval_arg;
1727 * mono_class_layout_fields:
1730 * Compute the placement of fields inside an object or struct, according to
1731 * the layout rules and set the following fields in @class:
1732 * - has_references (if the class contains instance references firled or structs that contain references)
1733 * - has_static_refs (same, but for static fields)
1734 * - instance_size (size of the object in memory)
1735 * - class_size (size needed for the static fields)
1736 * - size_inited (flag set when the instance_size is set)
1738 * LOCKING: this is supposed to be called with the loader lock held.
1741 mono_class_layout_fields (MonoClass *class)
1744 const int top = class->field.count;
1745 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1746 guint32 pass, passes, real_size;
1747 gboolean gc_aware_layout = FALSE;
1748 MonoClassField *field;
1751 * When we do generic sharing we need to have layout
1752 * information for open generic classes (either with a generic
1753 * context containing type variables or with a generic
1754 * container), so we don't return in that case anymore.
1758 * Enable GC aware auto layout: in this mode, reference
1759 * fields are grouped together inside objects, increasing collector
1761 * Requires that all classes whose layout is known to native code be annotated
1762 * with [StructLayout (LayoutKind.Sequential)]
1763 * Value types have gc_aware_layout disabled by default, as per
1764 * what the default is for other runtimes.
1766 /* corlib is missing [StructLayout] directives in many places */
1767 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1768 if (!class->valuetype)
1769 gc_aware_layout = TRUE;
1772 /* Compute klass->has_references */
1774 * Process non-static fields first, since static fields might recursively
1775 * refer to the class itself.
1777 for (i = 0; i < top; i++) {
1780 field = &class->fields [i];
1782 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1783 ftype = mono_type_get_underlying_type (field->type);
1784 ftype = mono_type_get_basic_type_from_generic (ftype);
1785 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1786 class->has_references = TRUE;
1790 for (i = 0; i < top; i++) {
1793 field = &class->fields [i];
1795 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1796 ftype = mono_type_get_underlying_type (field->type);
1797 ftype = mono_type_get_basic_type_from_generic (ftype);
1798 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1799 class->has_static_refs = TRUE;
1803 for (i = 0; i < top; i++) {
1806 field = &class->fields [i];
1808 ftype = mono_type_get_underlying_type (field->type);
1809 ftype = mono_type_get_basic_type_from_generic (ftype);
1810 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1811 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1812 class->has_static_refs = TRUE;
1814 class->has_references = TRUE;
1819 * Compute field layout and total size (not considering static fields)
1823 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1824 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1826 if (gc_aware_layout)
1831 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1834 if (class->parent) {
1835 mono_class_setup_fields (class->parent);
1836 if (class->parent->exception_type) {
1837 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1840 real_size = class->parent->instance_size;
1842 real_size = sizeof (MonoObject);
1845 for (pass = 0; pass < passes; ++pass) {
1846 for (i = 0; i < top; i++){
1851 field = &class->fields [i];
1853 if (mono_field_is_deleted (field))
1855 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1858 ftype = mono_type_get_underlying_type (field->type);
1859 ftype = mono_type_get_basic_type_from_generic (ftype);
1860 if (gc_aware_layout) {
1861 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1870 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1871 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1872 /* This field is a hack inserted by MCS to empty structures */
1876 size = mono_type_size (field->type, &align);
1878 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1879 align = class->packing_size ? MIN (class->packing_size, align): align;
1880 /* if the field has managed references, we need to force-align it
1883 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1884 align = MAX (align, sizeof (gpointer));
1886 class->min_align = MAX (align, class->min_align);
1887 field->offset = real_size;
1889 field->offset += align - 1;
1890 field->offset &= ~(align - 1);
1892 /*TypeBuilders produce all sort of weird things*/
1893 g_assert (class->image->dynamic || field->offset > 0);
1894 real_size = field->offset + size;
1897 class->instance_size = MAX (real_size, class->instance_size);
1899 if (class->instance_size & (class->min_align - 1)) {
1900 class->instance_size += class->min_align - 1;
1901 class->instance_size &= ~(class->min_align - 1);
1905 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1907 for (i = 0; i < top; i++) {
1912 field = &class->fields [i];
1915 * There must be info about all the fields in a type if it
1916 * uses explicit layout.
1919 if (mono_field_is_deleted (field))
1921 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1924 size = mono_type_size (field->type, &align);
1925 align = class->packing_size ? MIN (class->packing_size, align): align;
1926 class->min_align = MAX (align, class->min_align);
1929 * When we get here, field->offset is already set by the
1930 * loader (for either runtime fields or fields loaded from metadata).
1931 * The offset is from the start of the object: this works for both
1932 * classes and valuetypes.
1934 field->offset += sizeof (MonoObject);
1935 ftype = mono_type_get_underlying_type (field->type);
1936 ftype = mono_type_get_basic_type_from_generic (ftype);
1937 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1938 if (field->offset % sizeof (gpointer)) {
1939 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1946 real_size = MAX (real_size, size + field->offset);
1948 class->instance_size = MAX (real_size, class->instance_size);
1949 if (class->instance_size & (class->min_align - 1)) {
1950 class->instance_size += class->min_align - 1;
1951 class->instance_size &= ~(class->min_align - 1);
1956 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1958 * For small structs, set min_align to at least the struct size to improve
1959 * performance, and since the JIT memset/memcpy code assumes this and generates
1960 * unaligned accesses otherwise. See #78990 for a testcase.
1962 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1963 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1966 mono_memory_barrier ();
1967 class->size_inited = 1;
1970 * Compute static field layout and size
1972 for (i = 0; i < top; i++){
1976 field = &class->fields [i];
1978 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1980 if (mono_field_is_deleted (field))
1983 if (mono_type_has_exceptions (field->type)) {
1984 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1988 size = mono_type_size (field->type, &align);
1989 field->offset = class->sizes.class_size;
1990 /*align is always non-zero here*/
1991 field->offset += align - 1;
1992 field->offset &= ~(align - 1);
1993 class->sizes.class_size = field->offset + size;
1998 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2002 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2003 method->klass = class;
2004 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2005 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2006 method->signature = sig;
2007 method->name = name;
2010 if (name [0] == '.') {
2011 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2013 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2019 * mono_class_setup_methods:
2022 * Initializes the 'methods' array in the klass.
2023 * Calling this method should be avoided if possible since it allocates a lot
2024 * of long-living MonoMethod structures.
2025 * Methods belonging to an interface are assigned a sequential slot starting
2028 * On failure this function sets class->exception_type
2031 mono_class_setup_methods (MonoClass *class)
2034 MonoMethod **methods;
2039 mono_loader_lock ();
2041 if (class->methods) {
2042 mono_loader_unlock ();
2046 if (class->generic_class) {
2048 MonoClass *gklass = class->generic_class->container_class;
2050 mono_class_init (gklass);
2051 if (!gklass->exception_type)
2052 mono_class_setup_methods (gklass);
2053 if (gklass->exception_type) {
2054 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2055 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2056 mono_loader_unlock ();
2060 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2061 class->method.count = gklass->method.count;
2062 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2064 for (i = 0; i < class->method.count; i++) {
2065 methods [i] = mono_class_inflate_generic_method_full_checked (
2066 gklass->methods [i], class, mono_class_get_context (class), &error);
2067 if (!mono_error_ok (&error)) {
2068 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2069 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)));
2072 mono_error_cleanup (&error);
2073 mono_loader_unlock ();
2077 } else if (class->rank) {
2079 MonoMethod *amethod;
2080 MonoMethodSignature *sig;
2081 int count_generic = 0, first_generic = 0;
2084 class->method.count = 3 + (class->rank > 1? 2: 1);
2086 mono_class_setup_interfaces (class, &error);
2087 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2089 if (class->interface_count) {
2090 count_generic = generic_array_methods (class);
2091 first_generic = class->method.count;
2092 class->method.count += class->interface_count * count_generic;
2095 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2097 sig = mono_metadata_signature_alloc (class->image, class->rank);
2098 sig->ret = &mono_defaults.void_class->byval_arg;
2099 sig->pinvoke = TRUE;
2100 sig->hasthis = TRUE;
2101 for (i = 0; i < class->rank; ++i)
2102 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2104 amethod = create_array_method (class, ".ctor", sig);
2105 methods [method_num++] = amethod;
2106 if (class->rank > 1) {
2107 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2108 sig->ret = &mono_defaults.void_class->byval_arg;
2109 sig->pinvoke = TRUE;
2110 sig->hasthis = TRUE;
2111 for (i = 0; i < class->rank * 2; ++i)
2112 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2114 amethod = create_array_method (class, ".ctor", sig);
2115 methods [method_num++] = amethod;
2117 /* element Get (idx11, [idx2, ...]) */
2118 sig = mono_metadata_signature_alloc (class->image, class->rank);
2119 sig->ret = &class->element_class->byval_arg;
2120 sig->pinvoke = TRUE;
2121 sig->hasthis = TRUE;
2122 for (i = 0; i < class->rank; ++i)
2123 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2124 amethod = create_array_method (class, "Get", sig);
2125 methods [method_num++] = amethod;
2126 /* element& Address (idx11, [idx2, ...]) */
2127 sig = mono_metadata_signature_alloc (class->image, class->rank);
2128 sig->ret = &class->element_class->this_arg;
2129 sig->pinvoke = TRUE;
2130 sig->hasthis = TRUE;
2131 for (i = 0; i < class->rank; ++i)
2132 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2133 amethod = create_array_method (class, "Address", sig);
2134 methods [method_num++] = amethod;
2135 /* void Set (idx11, [idx2, ...], element) */
2136 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2137 sig->ret = &mono_defaults.void_class->byval_arg;
2138 sig->pinvoke = TRUE;
2139 sig->hasthis = TRUE;
2140 for (i = 0; i < class->rank; ++i)
2141 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2142 sig->params [i] = &class->element_class->byval_arg;
2143 amethod = create_array_method (class, "Set", sig);
2144 methods [method_num++] = amethod;
2146 for (i = 0; i < class->interface_count; i++)
2147 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2149 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2150 for (i = 0; i < class->method.count; ++i) {
2151 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2152 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2156 if (MONO_CLASS_IS_INTERFACE (class)) {
2158 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2159 for (i = 0; i < class->method.count; ++i) {
2160 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2161 methods [i]->slot = slot++;
2165 /* Needed because of the double-checking locking pattern */
2166 mono_memory_barrier ();
2168 class->methods = methods;
2170 if (mono_debugger_class_loaded_methods_func)
2171 mono_debugger_class_loaded_methods_func (class);
2173 mono_loader_unlock ();
2177 * mono_class_get_method_by_index:
2179 * Returns class->methods [index], initializing class->methods if neccesary.
2181 * LOCKING: Acquires the loader lock.
2184 mono_class_get_method_by_index (MonoClass *class, int index)
2186 /* Avoid calling setup_methods () if possible */
2187 if (class->generic_class && !class->methods) {
2188 MonoClass *gklass = class->generic_class->container_class;
2191 m = mono_class_inflate_generic_method_full (
2192 gklass->methods [index], class, mono_class_get_context (class));
2194 * If setup_methods () is called later for this class, no duplicates are created,
2195 * since inflate_generic_method guarantees that only one instance of a method
2196 * is created for each context.
2199 mono_class_setup_methods (class);
2200 g_assert (m == class->methods [index]);
2204 mono_class_setup_methods (class);
2205 if (class->exception_type) /*FIXME do proper error handling*/
2207 g_assert (index >= 0 && index < class->method.count);
2208 return class->methods [index];
2213 * mono_class_get_inflated_method:
2215 * Given an inflated class CLASS and a method METHOD which should be a method of
2216 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2219 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2221 MonoClass *gklass = class->generic_class->container_class;
2224 g_assert (method->klass == gklass);
2226 mono_class_setup_methods (gklass);
2227 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2229 for (i = 0; i < gklass->method.count; ++i) {
2230 if (gklass->methods [i] == method) {
2232 return class->methods [i];
2234 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2242 * mono_class_get_vtable_entry:
2244 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2245 * LOCKING: Acquires the loader lock.
2248 mono_class_get_vtable_entry (MonoClass *class, int offset)
2252 if (class->rank == 1) {
2254 * szarrays do not overwrite any methods of Array, so we can avoid
2255 * initializing their vtables in some cases.
2257 mono_class_setup_vtable (class->parent);
2258 if (offset < class->parent->vtable_size)
2259 return class->parent->vtable [offset];
2262 if (class->generic_class) {
2263 MonoClass *gklass = class->generic_class->container_class;
2264 mono_class_setup_vtable (gklass);
2265 m = gklass->vtable [offset];
2267 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2269 mono_class_setup_vtable (class);
2270 if (class->exception_type)
2272 m = class->vtable [offset];
2279 * mono_class_get_vtable_size:
2281 * Return the vtable size for KLASS.
2284 mono_class_get_vtable_size (MonoClass *klass)
2286 mono_class_setup_vtable (klass);
2288 return klass->vtable_size;
2291 /*This method can fail the class.*/
2293 mono_class_setup_properties (MonoClass *class)
2295 guint startm, endm, i, j;
2296 guint32 cols [MONO_PROPERTY_SIZE];
2297 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2298 MonoProperty *properties;
2301 if (class->ext && class->ext->properties)
2304 mono_loader_lock ();
2306 if (class->ext && class->ext->properties) {
2307 mono_loader_unlock ();
2311 mono_class_alloc_ext (class);
2313 if (class->generic_class) {
2314 MonoClass *gklass = class->generic_class->container_class;
2316 mono_class_init (gklass);
2317 mono_class_setup_properties (gklass);
2318 if (gklass->exception_type) {
2319 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2320 mono_loader_unlock ();
2324 class->ext->property = gklass->ext->property;
2326 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2328 for (i = 0; i < class->ext->property.count; i++) {
2329 MonoProperty *prop = &properties [i];
2331 *prop = gklass->ext->properties [i];
2334 prop->get = mono_class_inflate_generic_method_full (
2335 prop->get, class, mono_class_get_context (class));
2337 prop->set = mono_class_inflate_generic_method_full (
2338 prop->set, class, mono_class_get_context (class));
2340 prop->parent = class;
2343 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2344 int count = last - first;
2347 mono_class_setup_methods (class);
2348 if (class->exception_type) {
2349 mono_loader_unlock ();
2354 class->ext->property.first = first;
2355 class->ext->property.count = count;
2356 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2357 for (i = first; i < last; ++i) {
2358 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2359 properties [i - first].parent = class;
2360 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2361 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2363 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2364 for (j = startm; j < endm; ++j) {
2367 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2369 if (class->image->uncompressed_metadata)
2370 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2371 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2373 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2375 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2376 case METHOD_SEMANTIC_SETTER:
2377 properties [i - first].set = method;
2379 case METHOD_SEMANTIC_GETTER:
2380 properties [i - first].get = method;
2388 /*Flush any pending writes as we do double checked locking on class->properties */
2389 mono_memory_barrier ();
2391 /* Leave this assignment as the last op in the function */
2392 class->ext->properties = properties;
2394 mono_loader_unlock ();
2398 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2400 MonoMethod **om, **retval;
2403 for (om = methods, count = 0; *om; ++om, ++count)
2406 retval = g_new0 (MonoMethod*, count + 1);
2408 for (om = methods, count = 0; *om; ++om, ++count)
2409 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2414 /*This method can fail the class.*/
2416 mono_class_setup_events (MonoClass *class)
2419 guint startm, endm, i, j;
2420 guint32 cols [MONO_EVENT_SIZE];
2421 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2425 if (class->ext && class->ext->events)
2428 mono_loader_lock ();
2430 if (class->ext && class->ext->events) {
2431 mono_loader_unlock ();
2435 mono_class_alloc_ext (class);
2437 if (class->generic_class) {
2438 MonoClass *gklass = class->generic_class->container_class;
2439 MonoGenericContext *context;
2441 mono_class_setup_events (gklass);
2442 if (gklass->exception_type) {
2443 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2444 mono_loader_unlock ();
2448 class->ext->event = gklass->ext->event;
2449 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2451 if (class->ext->event.count)
2452 context = mono_class_get_context (class);
2454 for (i = 0; i < class->ext->event.count; i++) {
2455 MonoEvent *event = &class->ext->events [i];
2456 MonoEvent *gevent = &gklass->ext->events [i];
2458 event->parent = class;
2459 event->name = gevent->name;
2460 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2461 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2462 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2463 #ifndef MONO_SMALL_CONFIG
2464 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2466 event->attrs = gevent->attrs;
2469 mono_loader_unlock ();
2473 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2474 count = last - first;
2477 mono_class_setup_methods (class);
2478 if (class->exception_type) {
2479 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2480 mono_loader_unlock ();
2484 class->ext->event.first = first;
2485 class->ext->event.count = count;
2486 events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2487 for (i = first; i < last; ++i) {
2488 MonoEvent *event = &events [i - first];
2490 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2491 event->parent = class;
2492 event->attrs = cols [MONO_EVENT_FLAGS];
2493 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2495 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2496 for (j = startm; j < endm; ++j) {
2499 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2501 if (class->image->uncompressed_metadata)
2502 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2503 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2505 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2507 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2508 case METHOD_SEMANTIC_ADD_ON:
2509 event->add = method;
2511 case METHOD_SEMANTIC_REMOVE_ON:
2512 event->remove = method;
2514 case METHOD_SEMANTIC_FIRE:
2515 event->raise = method;
2517 case METHOD_SEMANTIC_OTHER: {
2518 #ifndef MONO_SMALL_CONFIG
2521 if (event->other == NULL) {
2522 event->other = g_new0 (MonoMethod*, 2);
2524 while (event->other [n])
2526 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2528 event->other [n] = method;
2529 /* NULL terminated */
2530 event->other [n + 1] = NULL;
2539 /*Flush any pending writes as we do double checked locking on class->properties */
2540 mono_memory_barrier ();
2542 /* Leave this assignment as the last op in the function */
2543 class->ext->events = events;
2545 mono_loader_unlock ();
2549 * Global pool of interface IDs, represented as a bitset.
2550 * LOCKING: this is supposed to be accessed with the loader lock held.
2552 static MonoBitSet *global_interface_bitset = NULL;
2555 * mono_unload_interface_ids:
2556 * @bitset: bit set of interface IDs
2558 * When an image is unloaded, the interface IDs associated with
2559 * the image are put back in the global pool of IDs so the numbers
2563 mono_unload_interface_ids (MonoBitSet *bitset)
2565 mono_loader_lock ();
2566 mono_bitset_sub (global_interface_bitset, bitset);
2567 mono_loader_unlock ();
2571 mono_unload_interface_id (MonoClass *class)
2573 if (global_interface_bitset && class->interface_id) {
2574 mono_loader_lock ();
2575 mono_bitset_clear (global_interface_bitset, class->interface_id);
2576 mono_loader_unlock ();
2581 * mono_get_unique_iid:
2584 * Assign a unique integer ID to the interface represented by @class.
2585 * The ID will positive and as small as possible.
2586 * LOCKING: this is supposed to be called with the loader lock held.
2587 * Returns: the new ID.
2590 mono_get_unique_iid (MonoClass *class)
2594 g_assert (MONO_CLASS_IS_INTERFACE (class));
2596 if (!global_interface_bitset) {
2597 global_interface_bitset = mono_bitset_new (128, 0);
2600 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2602 int old_size = mono_bitset_size (global_interface_bitset);
2603 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2604 mono_bitset_free (global_interface_bitset);
2605 global_interface_bitset = new_set;
2608 mono_bitset_set (global_interface_bitset, iid);
2609 /* set the bit also in the per-image set */
2610 if (!class->generic_class) {
2611 if (class->image->interface_bitset) {
2612 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2613 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2614 mono_bitset_free (class->image->interface_bitset);
2615 class->image->interface_bitset = new_set;
2618 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2620 mono_bitset_set (class->image->interface_bitset, iid);
2623 #ifndef MONO_SMALL_CONFIG
2624 if (mono_print_vtable) {
2626 char *type_name = mono_type_full_name (&class->byval_arg);
2627 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2628 generic_id = class->generic_class->context.class_inst->id;
2629 g_assert (generic_id != 0);
2633 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2638 g_assert (iid <= 65535);
2643 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2648 mono_class_setup_interfaces (klass, error);
2649 if (!mono_error_ok (error))
2652 for (i = 0; i < klass->interface_count; i++) {
2653 ic = klass->interfaces [i];
2656 *res = g_ptr_array_new ();
2657 g_ptr_array_add (*res, ic);
2658 mono_class_init (ic);
2659 if (ic->exception_type) {
2660 mono_error_set_type_load_class (error, ic, "Error Loading class");
2664 collect_implemented_interfaces_aux (ic, res, error);
2665 if (!mono_error_ok (error))
2671 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2673 GPtrArray *res = NULL;
2675 collect_implemented_interfaces_aux (klass, &res, error);
2676 if (!mono_error_ok (error)) {
2678 g_ptr_array_free (res, TRUE);
2685 compare_interface_ids (const void *p_key, const void *p_element) {
2686 const MonoClass *key = p_key;
2687 const MonoClass *element = *(MonoClass**) p_element;
2689 return (key->interface_id - element->interface_id);
2692 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2694 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2695 MonoClass **result = bsearch (
2697 klass->interfaces_packed,
2698 klass->interface_offsets_count,
2699 sizeof (MonoClass *),
2700 compare_interface_ids);
2702 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2709 * mono_class_interface_offset_with_variance:
2711 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2712 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2714 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2716 * FIXME figure out MS disambiguation rules and fix this function.
2719 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2720 int i = mono_class_interface_offset (klass, itf);
2721 *non_exact_match = FALSE;
2725 if (!mono_class_has_variant_generic_params (itf))
2728 for (i = 0; i < klass->interface_offsets_count; i++) {
2729 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2730 *non_exact_match = TRUE;
2731 return klass->interface_offsets_packed [i];
2739 print_implemented_interfaces (MonoClass *klass) {
2742 GPtrArray *ifaces = NULL;
2744 int ancestor_level = 0;
2746 name = mono_type_get_full_name (klass);
2747 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2750 for (i = 0; i < klass->interface_offsets_count; i++)
2751 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2752 klass->interfaces_packed [i]->interface_id,
2753 klass->interface_offsets_packed [i],
2754 klass->interfaces_packed [i]->method.count,
2755 klass->interfaces_packed [i]->name_space,
2756 klass->interfaces_packed [i]->name );
2757 printf ("Interface flags: ");
2758 for (i = 0; i <= klass->max_interface_id; i++)
2759 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2760 printf ("(%d,T)", i);
2762 printf ("(%d,F)", i);
2764 printf ("Dump interface flags:");
2765 #ifdef COMPRESSED_INTERFACE_BITMAP
2767 const uint8_t* p = klass->interface_bitmap;
2768 i = klass->max_interface_id;
2770 printf (" %d x 00 %02X", p [0], p [1]);
2776 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2777 printf (" %02X", klass->interface_bitmap [i]);
2780 while (klass != NULL) {
2781 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2782 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2783 if (!mono_error_ok (&error)) {
2784 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2785 mono_error_cleanup (&error);
2786 } else if (ifaces) {
2787 for (i = 0; i < ifaces->len; i++) {
2788 MonoClass *ic = g_ptr_array_index (ifaces, i);
2789 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2790 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2792 mono_class_interface_offset (klass, ic),
2797 g_ptr_array_free (ifaces, TRUE);
2800 klass = klass->parent;
2805 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2808 args [0] = &arg0->byval_arg;
2810 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2814 array_class_get_if_rank (MonoClass *class, guint rank)
2816 return rank ? mono_array_class_get (class, rank) : class;
2820 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2822 valuetype_types [0] = eclass;
2823 if (eclass == mono_defaults.int16_class)
2824 valuetype_types [1] = mono_defaults.uint16_class;
2825 else if (eclass == mono_defaults.uint16_class)
2826 valuetype_types [1] = mono_defaults.int16_class;
2827 else if (eclass == mono_defaults.int32_class)
2828 valuetype_types [1] = mono_defaults.uint32_class;
2829 else if (eclass == mono_defaults.uint32_class)
2830 valuetype_types [1] = mono_defaults.int32_class;
2831 else if (eclass == mono_defaults.int64_class)
2832 valuetype_types [1] = mono_defaults.uint64_class;
2833 else if (eclass == mono_defaults.uint64_class)
2834 valuetype_types [1] = mono_defaults.int64_class;
2835 else if (eclass == mono_defaults.byte_class)
2836 valuetype_types [1] = mono_defaults.sbyte_class;
2837 else if (eclass == mono_defaults.sbyte_class)
2838 valuetype_types [1] = mono_defaults.byte_class;
2839 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2840 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2843 /* this won't be needed once bug #325495 is completely fixed
2844 * though we'll need something similar to know which interfaces to allow
2845 * in arrays when they'll be lazyly created
2847 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2848 * MS returns diferrent types based on which instance is called. For example:
2849 * object obj = new byte[10][];
2850 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2851 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2854 * Fixing this should kill quite some code, save some bits and improve compatibility.
2857 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2859 MonoClass *eclass = class->element_class;
2860 static MonoClass* generic_icollection_class = NULL;
2861 static MonoClass* generic_ienumerable_class = NULL;
2862 static MonoClass* generic_ienumerator_class = NULL;
2863 static MonoClass* generic_ireadonlylist_class = NULL;
2864 static MonoClass* generic_ireadonlycollection_class = NULL;
2865 MonoClass *valuetype_types[2] = { NULL, NULL };
2866 MonoClass **interfaces = NULL;
2867 int i, nifaces, interface_count, real_count, original_rank;
2869 gboolean internal_enumerator;
2870 gboolean eclass_is_valuetype;
2872 if (!mono_defaults.generic_ilist_class) {
2876 internal_enumerator = FALSE;
2877 eclass_is_valuetype = FALSE;
2878 original_rank = eclass->rank;
2879 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2880 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2882 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2884 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2885 original_rank = eclass->rank;
2887 eclass = eclass->element_class;
2888 internal_enumerator = TRUE;
2889 *is_enumerator = TRUE;
2897 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2898 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2900 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2902 if (!generic_icollection_class) {
2903 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2904 "System.Collections.Generic", "ICollection`1");
2905 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2906 "System.Collections.Generic", "IEnumerable`1");
2907 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2908 "System.Collections.Generic", "IEnumerator`1");
2909 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2910 "System.Collections.Generic", "IReadOnlyList`1");
2911 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2912 "System.Collections.Generic", "IReadOnlyCollection`1");
2915 mono_class_init (eclass);
2918 * Arrays in 2.0 need to implement a number of generic interfaces
2919 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2920 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2921 * We collect the types needed to build the
2922 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2923 * the generic interfaces needed to implement.
2925 nifaces = generic_ireadonlylist_class ? 5 : 3;
2926 if (eclass->valuetype) {
2927 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2929 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2930 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2931 if (internal_enumerator) {
2933 if (valuetype_types [1])
2937 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2938 interfaces [0] = valuetype_types [0];
2939 if (valuetype_types [1])
2940 interfaces [nifaces] = valuetype_types [1];
2942 eclass_is_valuetype = TRUE;
2945 int idepth = eclass->idepth;
2946 if (!internal_enumerator)
2949 // FIXME: This doesn't seem to work/required for generic params
2950 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
2951 mono_class_setup_interface_offsets (eclass);
2953 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2954 /* we add object for interfaces and the supertypes for the other
2955 * types. The last of the supertypes is the element class itself which we
2956 * already created the explicit interfaces for (so we include it for IEnumerator
2957 * and exclude it for arrays).
2959 if (MONO_CLASS_IS_INTERFACE (eclass))
2962 interface_count += idepth;
2963 if (eclass->rank && eclass->element_class->valuetype) {
2964 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2965 if (valuetype_types [1])
2968 /* IList, ICollection, IEnumerable, IReadOnlyList */
2969 interface_count *= nifaces;
2970 real_count = interface_count;
2971 if (internal_enumerator) {
2972 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2973 if (valuetype_types [1])
2976 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2977 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2978 interfaces [0] = mono_defaults.object_class;
2982 for (i = 0; i < idepth; i++) {
2983 mono_class_init (eclass->supertypes [i]);
2984 interfaces [j] = eclass->supertypes [i];
2988 if (all_interfaces) {
2989 for (i = 0; i < eclass->interface_offsets_count; i++) {
2990 interfaces [j] = eclass->interfaces_packed [i];
2994 for (i = 0; i < eclass->interface_count; i++) {
2995 interfaces [j] = eclass->interfaces [i];
2999 if (valuetype_types [1]) {
3000 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3005 /* instantiate the generic interfaces */
3006 for (i = 0; i < interface_count; i += nifaces) {
3007 MonoClass *iface = interfaces [i];
3009 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3010 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3011 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3012 if (generic_ireadonlylist_class) {
3013 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3014 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3017 if (internal_enumerator) {
3019 /* instantiate IEnumerator<iface> */
3020 for (i = 0; i < interface_count; i++) {
3021 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3023 j = interface_count;
3024 if (!eclass_is_valuetype) {
3025 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3026 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3029 for (i = 0; i < eclass->idepth; i++) {
3030 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3034 for (i = 0; i < eclass->interface_offsets_count; i++) {
3035 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3039 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3041 if (valuetype_types [1])
3042 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3046 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3047 for (i = 0; i < real_count; ++i) {
3048 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3049 g_print ("%s implements %s\n", type_name, name);
3060 find_array_interface (MonoClass *klass, const char *name)
3063 for (i = 0; i < klass->interface_count; ++i) {
3064 if (strcmp (klass->interfaces [i]->name, name) == 0)
3071 * Return the number of virtual methods.
3072 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3073 * Return -1 on failure.
3074 * FIXME It would be nice if this information could be cached somewhere.
3077 count_virtual_methods (MonoClass *class)
3081 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3083 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3084 mono_class_setup_methods (class);
3085 if (class->exception_type)
3088 for (i = 0; i < class->method.count; ++i) {
3089 flags = class->methods [i]->flags;
3090 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3094 for (i = 0; i < class->method.count; ++i) {
3095 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3097 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3105 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3113 m = (l + num_ifaces) / 2;
3114 if (interfaces_full [m] == ic)
3116 if (l == num_ifaces)
3118 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3127 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3129 int i = find_interface (num_ifaces, interfaces_full, ic);
3131 return interface_offsets_full [i];
3136 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3138 int i = find_interface (num_ifaces, interfaces_full, ic);
3142 interface_offsets_full [i] = offset;
3145 for (i = 0; i < num_ifaces; ++i) {
3146 if (interfaces_full [i]) {
3148 if (interfaces_full [i]->interface_id < ic->interface_id)
3151 while (end < num_ifaces && interfaces_full [end]) end++;
3152 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3153 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3155 interfaces_full [i] = ic;
3156 interface_offsets_full [i] = offset;
3162 #ifdef COMPRESSED_INTERFACE_BITMAP
3165 * Compressed interface bitmap design.
3167 * Interface bitmaps take a large amount of memory, because their size is
3168 * linear with the maximum interface id assigned in the process (each interface
3169 * is assigned a unique id as it is loaded). The number of interface classes
3170 * is high because of the many implicit interfaces implemented by arrays (we'll
3171 * need to lazy-load them in the future).
3172 * Most classes implement a very small number of interfaces, so the bitmap is
3173 * sparse. This bitmap needs to be checked by interface casts, so access to the
3174 * needed bit must be fast and doable with few jit instructions.
3176 * The current compression format is as follows:
3177 * *) it is a sequence of one or more two-byte elements
3178 * *) the first byte in the element is the count of empty bitmap bytes
3179 * at the current bitmap position
3180 * *) the second byte in the element is an actual bitmap byte at the current
3183 * As an example, the following compressed bitmap bytes:
3184 * 0x07 0x01 0x00 0x7
3185 * correspond to the following bitmap:
3186 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3188 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3189 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3190 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3194 * mono_compress_bitmap:
3195 * @dest: destination buffer
3196 * @bitmap: bitmap buffer
3197 * @size: size of @bitmap in bytes
3199 * This is a mono internal function.
3200 * The @bitmap data is compressed into a format that is small but
3201 * still searchable in few instructions by the JIT and runtime.
3202 * The compressed data is stored in the buffer pointed to by the
3203 * @dest array. Passing a #NULL value for @dest allows to just compute
3204 * the size of the buffer.
3205 * This compression algorithm assumes the bits set in the bitmap are
3206 * few and far between, like in interface bitmaps.
3207 * Returns: the size of the compressed bitmap in bytes.
3210 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3214 const uint8_t *end = bitmap + size;
3215 while (bitmap < end) {
3216 if (*bitmap || numz == 255) {
3240 * mono_class_interface_match:
3241 * @bitmap: a compressed bitmap buffer
3242 * @id: the index to check in the bitmap
3244 * This is a mono internal function.
3245 * Checks if a bit is set in a compressed interface bitmap. @id must
3246 * be already checked for being smaller than the maximum id encoded in the
3249 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3253 mono_class_interface_match (const uint8_t *bitmap, int id)
3256 id -= bitmap [0] * 8;
3260 return bitmap [1] & (1 << id);
3269 * LOCKING: this is supposed to be called with the loader lock held.
3270 * Return -1 on failure and set exception_type
3273 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3277 int i, j, max_iid, num_ifaces;
3278 MonoClass **interfaces_full = NULL;
3279 int *interface_offsets_full = NULL;
3281 GPtrArray **ifaces_array = NULL;
3282 int interface_offsets_count;
3283 MonoClass **array_interfaces = NULL;
3284 int num_array_interfaces;
3285 int is_enumerator = FALSE;
3287 mono_class_setup_supertypes (class);
3289 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3290 * implicit interfaces have the property that they are assigned the same slot in the
3291 * vtables for compatible interfaces
3293 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3295 /* compute maximum number of slots and maximum interface id */
3297 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3298 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3299 for (j = 0; j < class->idepth; j++) {
3300 k = class->supertypes [j];
3301 num_ifaces += k->interface_count;
3302 for (i = 0; i < k->interface_count; i++) {
3303 ic = k->interfaces [i];
3306 mono_class_init (ic);
3308 if (max_iid < ic->interface_id)
3309 max_iid = ic->interface_id;
3311 ifaces = mono_class_get_implemented_interfaces (k, &error);
3312 if (!mono_error_ok (&error)) {
3313 char *name = mono_type_get_full_name (k);
3314 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)));
3316 mono_error_cleanup (&error);
3321 num_ifaces += ifaces->len;
3322 for (i = 0; i < ifaces->len; ++i) {
3323 ic = g_ptr_array_index (ifaces, i);
3324 if (max_iid < ic->interface_id)
3325 max_iid = ic->interface_id;
3327 ifaces_array [j] = ifaces;
3331 for (i = 0; i < num_array_interfaces; ++i) {
3332 ic = array_interfaces [i];
3333 mono_class_init (ic);
3334 if (max_iid < ic->interface_id)
3335 max_iid = ic->interface_id;
3338 if (MONO_CLASS_IS_INTERFACE (class)) {
3340 if (max_iid < class->interface_id)
3341 max_iid = class->interface_id;
3343 class->max_interface_id = max_iid;
3344 /* compute vtable offset for interfaces */
3345 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3346 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3348 for (i = 0; i < num_ifaces; i++) {
3349 interface_offsets_full [i] = -1;
3352 /* skip the current class */
3353 for (j = 0; j < class->idepth - 1; j++) {
3354 k = class->supertypes [j];
3355 ifaces = ifaces_array [j];
3358 for (i = 0; i < ifaces->len; ++i) {
3360 ic = g_ptr_array_index (ifaces, i);
3362 /*Force the sharing of interface offsets between parent and subtypes.*/
3363 io = mono_class_interface_offset (k, ic);
3365 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3370 g_assert (class == class->supertypes [class->idepth - 1]);
3371 ifaces = ifaces_array [class->idepth - 1];
3373 for (i = 0; i < ifaces->len; ++i) {
3375 ic = g_ptr_array_index (ifaces, i);
3376 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3378 count = count_virtual_methods (ic);
3380 char *name = mono_type_get_full_name (ic);
3381 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3390 if (MONO_CLASS_IS_INTERFACE (class))
3391 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3393 if (num_array_interfaces) {
3394 if (is_enumerator) {
3395 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3396 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3397 g_assert (ienumerator_offset >= 0);
3398 for (i = 0; i < num_array_interfaces; ++i) {
3399 ic = array_interfaces [i];
3400 if (strcmp (ic->name, "IEnumerator`1") == 0)
3401 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3403 g_assert_not_reached ();
3404 /*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);*/
3407 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3408 int ilist_iface_idx = find_array_interface (class, "IList`1");
3409 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3410 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3411 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3412 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3413 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3414 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3415 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3416 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3417 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3418 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3419 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3420 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3421 for (i = 0; i < num_array_interfaces; ++i) {
3423 ic = array_interfaces [i];
3424 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3425 offset = ilist_offset;
3426 else if (strcmp (ic->name, "ICollection`1") == 0)
3427 offset = icollection_offset;
3428 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3429 offset = ienumerable_offset;
3430 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3431 offset = ireadonlylist_offset;
3432 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3433 offset = ireadonlycollection_offset;
3435 g_assert_not_reached ();
3436 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3437 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3442 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3443 if (interface_offsets_full [i] != -1) {
3444 interface_offsets_count ++;
3449 * We might get called multiple times:
3450 * - mono_class_init ()
3451 * - mono_class_setup_vtable ().
3452 * - mono_class_setup_interface_offsets ().
3453 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3454 * means we have to overwrite those when called from other places (#4440).
3456 if (class->interfaces_packed && !overwrite) {
3457 g_assert (class->interface_offsets_count == interface_offsets_count);
3461 class->interface_offsets_count = interface_offsets_count;
3462 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3463 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3464 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3465 #ifdef COMPRESSED_INTERFACE_BITMAP
3466 bitmap = g_malloc0 (bsize);
3468 bitmap = mono_class_alloc0 (class, bsize);
3470 for (i = 0; i < interface_offsets_count; i++) {
3471 int id = interfaces_full [i]->interface_id;
3472 bitmap [id >> 3] |= (1 << (id & 7));
3473 class->interfaces_packed [i] = interfaces_full [i];
3474 class->interface_offsets_packed [i] = interface_offsets_full [i];
3475 /*if (num_array_interfaces)
3476 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]);*/
3478 #ifdef COMPRESSED_INTERFACE_BITMAP
3479 i = mono_compress_bitmap (NULL, bitmap, bsize);
3480 class->interface_bitmap = mono_class_alloc0 (class, i);
3481 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3484 class->interface_bitmap = bitmap;
3489 g_free (interfaces_full);
3490 g_free (interface_offsets_full);
3491 g_free (array_interfaces);
3492 for (i = 0; i < class->idepth; i++) {
3493 ifaces = ifaces_array [i];
3495 g_ptr_array_free (ifaces, TRUE);
3497 g_free (ifaces_array);
3499 //printf ("JUST DONE: ");
3500 //print_implemented_interfaces (class);
3506 * Setup interface offsets for interfaces.
3508 * - class->max_interface_id
3509 * - class->interface_offsets_count
3510 * - class->interfaces_packed
3511 * - class->interface_offsets_packed
3512 * - class->interface_bitmap
3514 * This function can fail @class.
3517 mono_class_setup_interface_offsets (MonoClass *class)
3519 mono_loader_lock ();
3521 setup_interface_offsets (class, 0, FALSE);
3523 mono_loader_unlock ();
3526 /*Checks if @klass has @parent as one of it's parents type gtd
3530 * Bar<T> : Foo<Bar<Bar<T>>>
3534 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3536 klass = mono_class_get_generic_type_definition (klass);
3537 parent = mono_class_get_generic_type_definition (parent);
3538 mono_class_setup_supertypes (klass);
3539 mono_class_setup_supertypes (parent);
3541 return klass->idepth >= parent->idepth &&
3542 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3546 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3548 MonoGenericInst *ginst;
3550 if (!class->generic_class) {
3551 mono_class_setup_vtable_full (class, in_setup);
3552 return class->exception_type == 0;
3555 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3556 if (class->generic_class->container_class->exception_type) {
3557 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3561 ginst = class->generic_class->context.class_inst;
3562 for (i = 0; i < ginst->type_argc; ++i) {
3564 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3566 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3567 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3568 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3570 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3571 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3579 * mono_class_setup_vtable:
3581 * Creates the generic vtable of CLASS.
3582 * Initializes the following fields in MonoClass:
3585 * Plus all the fields initialized by setup_interface_offsets ().
3586 * If there is an error during vtable construction, class->exception_type is set.
3588 * LOCKING: Acquires the loader lock.
3591 mono_class_setup_vtable (MonoClass *class)
3593 mono_class_setup_vtable_full (class, NULL);
3597 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3599 MonoMethod **overrides;
3600 MonoGenericContext *context;
3608 if (mono_debug_using_mono_debugger ())
3609 /* The debugger currently depends on this */
3610 mono_class_setup_methods (class);
3612 if (MONO_CLASS_IS_INTERFACE (class)) {
3613 /* This sets method->slot for all methods if this is an interface */
3614 mono_class_setup_methods (class);
3618 if (class->exception_type)
3621 if (g_list_find (in_setup, class))
3624 mono_loader_lock ();
3626 if (class->vtable) {
3627 mono_loader_unlock ();
3631 mono_stats.generic_vtable_count ++;
3632 in_setup = g_list_prepend (in_setup, class);
3634 if (class->generic_class) {
3635 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3636 mono_loader_unlock ();
3637 g_list_remove (in_setup, class);
3641 context = mono_class_get_context (class);
3642 type_token = class->generic_class->container_class->type_token;
3644 context = (MonoGenericContext *) class->generic_container;
3645 type_token = class->type_token;
3648 if (class->image->dynamic) {
3649 /* Generic instances can have zero method overrides without causing any harm.
3650 * This is true since we don't do layout all over again for them, we simply inflate
3651 * the layout of the parent.
3653 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3655 /* The following call fails if there are missing methods in the type */
3656 /* FIXME it's probably a good idea to avoid this for generic instances. */
3657 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3661 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3663 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3667 mono_loader_unlock ();
3668 g_list_remove (in_setup, class);
3673 #define DEBUG_INTERFACE_VTABLE_CODE 0
3674 #define TRACE_INTERFACE_VTABLE_CODE 0
3675 #define VERIFY_INTERFACE_VTABLE_CODE 0
3676 #define VTABLE_SELECTOR (1)
3678 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3679 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3680 if (!(VTABLE_SELECTOR)) break; \
3684 #define DEBUG_INTERFACE_VTABLE(stmt)
3687 #if TRACE_INTERFACE_VTABLE_CODE
3688 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3689 if (!(VTABLE_SELECTOR)) break; \
3693 #define TRACE_INTERFACE_VTABLE(stmt)
3696 #if VERIFY_INTERFACE_VTABLE_CODE
3697 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3698 if (!(VTABLE_SELECTOR)) break; \
3702 #define VERIFY_INTERFACE_VTABLE(stmt)
3706 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3708 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3712 GString *res = g_string_new ("");
3714 g_string_append_c (res, '(');
3715 for (i = 0; i < sig->param_count; ++i) {
3717 g_string_append_c (res, ',');
3718 mono_type_get_desc (res, sig->params [i], include_namespace);
3720 g_string_append (res, ")=>");
3721 if (sig->ret != NULL) {
3722 mono_type_get_desc (res, sig->ret, include_namespace);
3724 g_string_append (res, "NULL");
3727 g_string_free (res, FALSE);
3731 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3732 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3733 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3734 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3742 is_wcf_hack_disabled (void)
3744 static gboolean disabled;
3745 static gboolean inited = FALSE;
3747 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3754 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) {
3755 MonoMethodSignature *cmsig, *imsig;
3756 if (strcmp (im->name, cm->name) == 0) {
3757 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3758 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3761 if (! slot_is_empty) {
3762 if (require_newslot) {
3763 if (! interface_is_explicitly_implemented_by_class) {
3764 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3767 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3768 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3772 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3775 cmsig = mono_method_signature (cm);
3776 imsig = mono_method_signature (im);
3777 if (!cmsig || !imsig) {
3778 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3782 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3783 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3784 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3785 TRACE_INTERFACE_VTABLE (printf ("]"));
3788 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3789 /* CAS - SecurityAction.InheritanceDemand on interface */
3790 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3791 mono_secman_inheritancedemand_method (cm, im);
3794 if (mono_security_core_clr_enabled ())
3795 mono_security_core_clr_check_override (class, cm, im);
3797 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3798 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3799 char *body_name = mono_method_full_name (cm, TRUE);
3800 char *decl_name = mono_method_full_name (im, TRUE);
3801 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));
3809 MonoClass *ic = im->klass;
3810 const char *ic_name_space = ic->name_space;
3811 const char *ic_name = ic->name;
3814 if (! require_newslot) {
3815 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3818 if (cm->klass->rank == 0) {
3819 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3822 cmsig = mono_method_signature (cm);
3823 imsig = mono_method_signature (im);
3824 if (!cmsig || !imsig) {
3825 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3829 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3830 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3831 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3832 TRACE_INTERFACE_VTABLE (printf ("]"));
3835 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3836 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3839 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3840 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3843 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))) {
3844 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3848 subname = strstr (cm->name, ic_name_space);
3849 if (subname != cm->name) {
3850 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3853 subname += strlen (ic_name_space);
3854 if (subname [0] != '.') {
3855 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3859 if (strstr (subname, ic_name) != subname) {
3860 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3863 subname += strlen (ic_name);
3864 if (subname [0] != '.') {
3865 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3869 if (strcmp (subname, im->name) != 0) {
3870 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3874 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3875 /* CAS - SecurityAction.InheritanceDemand on interface */
3876 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3877 mono_secman_inheritancedemand_method (cm, im);
3880 if (mono_security_core_clr_enabled ())
3881 mono_security_core_clr_check_override (class, cm, im);
3883 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3884 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3885 char *body_name = mono_method_full_name (cm, TRUE);
3886 char *decl_name = mono_method_full_name (im, TRUE);
3887 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));
3897 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3899 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3900 MonoMethod *method = key;
3901 MonoMethod *override = value;
3902 MonoClass *method_class = mono_method_get_class (method);
3903 MonoClass *override_class = mono_method_get_class (override);
3905 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3906 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3907 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3910 print_overrides (GHashTable *override_map, const char *message) {
3912 printf ("Override map \"%s\" START:\n", message);
3913 g_hash_table_foreach (override_map, foreach_override, NULL);
3914 printf ("Override map \"%s\" END.\n", message);
3916 printf ("Override map \"%s\" EMPTY.\n", message);
3920 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3921 char *full_name = mono_type_full_name (&class->byval_arg);
3925 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3927 if (print_interfaces) {
3928 print_implemented_interfaces (class);
3929 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3932 if (class->parent) {
3933 parent_size = class->parent->vtable_size;
3937 for (i = 0; i < size; ++i) {
3938 MonoMethod *cm = vtable [i];
3939 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3940 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3942 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3950 #if VERIFY_INTERFACE_VTABLE_CODE
3952 mono_method_try_get_vtable_index (MonoMethod *method)
3954 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3955 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3956 if (imethod->declaring->is_generic)
3957 return imethod->declaring->slot;
3959 return method->slot;
3963 mono_class_verify_vtable (MonoClass *class)
3966 char *full_name = mono_type_full_name (&class->byval_arg);
3968 printf ("*** Verifying VTable of class '%s' \n", full_name);
3972 if (!class->methods)
3975 for (i = 0; i < class->method.count; ++i) {
3976 MonoMethod *cm = class->methods [i];
3979 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3983 full_name = mono_method_full_name (cm, TRUE);
3985 slot = mono_method_try_get_vtable_index (cm);
3987 if (slot >= class->vtable_size) {
3988 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
3992 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
3993 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
3994 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3995 g_free (other_name);
3998 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4005 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4007 char *method_signature;
4010 for (index = 0; index < onum; ++index) {
4011 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4012 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4014 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4015 type_name = mono_type_full_name (&class->byval_arg);
4016 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4017 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4018 g_free (method_signature);
4020 mono_class_setup_methods (class);
4021 if (class->exception_type) {
4022 char *name = mono_type_get_full_name (class);
4023 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4027 for (index = 0; index < class->method.count; ++index) {
4028 MonoMethod *cm = class->methods [index];
4029 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4031 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4032 g_free (method_signature);
4037 mono_method_get_method_definition (MonoMethod *method)
4039 while (method->is_inflated)
4040 method = ((MonoMethodInflated*)method)->declaring;
4045 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4049 for (i = 0; i < onum; ++i) {
4050 MonoMethod *decl = overrides [i * 2];
4051 MonoMethod *body = overrides [i * 2 + 1];
4053 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4054 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4058 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4059 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4060 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4062 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4066 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4067 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4068 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4070 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4074 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4075 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4079 body = mono_method_get_method_definition (body);
4080 decl = mono_method_get_method_definition (decl);
4082 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4083 char *body_name = mono_method_full_name (body, TRUE);
4084 char *decl_name = mono_method_full_name (decl, TRUE);
4085 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));
4095 mono_class_need_stelemref_method (MonoClass *class)
4097 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4101 * LOCKING: this is supposed to be called with the loader lock held.
4104 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4108 MonoMethod **vtable;
4109 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4110 GPtrArray *ifaces = NULL;
4111 GHashTable *override_map = NULL;
4112 gboolean security_enabled = mono_security_enabled ();
4114 gpointer class_iter;
4115 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4116 int first_non_interface_slot;
4118 GSList *virt_methods = NULL, *l;
4119 int stelemref_slot = 0;
4124 if (overrides && !verify_class_overrides (class, overrides, onum))
4127 ifaces = mono_class_get_implemented_interfaces (class, &error);
4128 if (!mono_error_ok (&error)) {
4129 char *name = mono_type_get_full_name (class);
4130 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)));
4132 mono_error_cleanup (&error);
4134 } else if (ifaces) {
4135 for (i = 0; i < ifaces->len; i++) {
4136 MonoClass *ic = g_ptr_array_index (ifaces, i);
4137 max_vtsize += ic->method.count;
4139 g_ptr_array_free (ifaces, TRUE);
4143 if (class->parent) {
4144 mono_class_init (class->parent);
4145 mono_class_setup_vtable_full (class->parent, in_setup);
4147 if (class->parent->exception_type) {
4148 char *name = mono_type_get_full_name (class->parent);
4149 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4154 max_vtsize += class->parent->vtable_size;
4155 cur_slot = class->parent->vtable_size;
4158 max_vtsize += class->method.count;
4160 /*Array have a slot for stelemref*/
4161 if (mono_class_need_stelemref_method (class)) {
4162 stelemref_slot = cur_slot;
4167 vtable = alloca (sizeof (gpointer) * max_vtsize);
4168 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4170 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4172 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4173 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4176 max_iid = class->max_interface_id;
4177 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4179 /* Optimized version for generic instances */
4180 if (class->generic_class) {
4182 MonoClass *gklass = class->generic_class->container_class;
4185 mono_class_setup_vtable_full (gklass, in_setup);
4186 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4187 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4191 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4192 class->vtable_size = gklass->vtable_size;
4193 for (i = 0; i < gklass->vtable_size; ++i)
4194 if (gklass->vtable [i]) {
4195 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4196 if (!mono_error_ok (&error)) {
4197 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4198 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4200 mono_error_cleanup (&error);
4204 tmp [i]->slot = gklass->vtable [i]->slot;
4206 mono_memory_barrier ();
4207 class->vtable = tmp;
4209 /* Have to set method->slot for abstract virtual methods */
4210 if (class->methods && gklass->methods) {
4211 for (i = 0; i < class->method.count; ++i)
4212 if (class->methods [i]->slot == -1)
4213 class->methods [i]->slot = gklass->methods [i]->slot;
4219 if (class->parent && class->parent->vtable_size) {
4220 MonoClass *parent = class->parent;
4223 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4225 // Also inherit parent interface vtables, just as a starting point.
4226 // This is needed otherwise bug-77127.exe fails when the property methods
4227 // have different names in the iterface and the class, because for child
4228 // classes the ".override" information is not used anymore.
4229 for (i = 0; i < parent->interface_offsets_count; i++) {
4230 MonoClass *parent_interface = parent->interfaces_packed [i];
4231 int interface_offset = mono_class_interface_offset (class, parent_interface);
4232 /*FIXME this is now dead code as this condition will never hold true.
4233 Since interface offsets are inherited then the offset of an interface implemented
4234 by a parent will never be the out of it's vtable boundary.
4236 if (interface_offset >= parent->vtable_size) {
4237 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4240 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4241 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4242 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4243 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4244 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4245 parent_interface_offset + j, parent_interface_offset, j,
4246 interface_offset + j, interface_offset, j));
4253 /*Array have a slot for stelemref*/
4254 if (mono_class_need_stelemref_method (class)) {
4255 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4257 method->slot = stelemref_slot;
4259 g_assert (method->slot == stelemref_slot);
4261 vtable [stelemref_slot] = method;
4264 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4265 /* override interface methods */
4266 for (i = 0; i < onum; i++) {
4267 MonoMethod *decl = overrides [i*2];
4268 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4270 dslot = mono_method_get_vtable_slot (decl);
4272 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4276 dslot += mono_class_interface_offset (class, decl->klass);
4277 vtable [dslot] = overrides [i*2 + 1];
4278 vtable [dslot]->slot = dslot;
4280 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4282 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4284 if (mono_security_core_clr_enabled ())
4285 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4288 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4289 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4292 * Create a list of virtual methods to avoid calling
4293 * mono_class_get_virtual_methods () which is slow because of the metadata
4297 gpointer iter = NULL;
4300 virt_methods = NULL;
4301 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4302 virt_methods = g_slist_prepend (virt_methods, cm);
4304 if (class->exception_type)
4308 // Loop on all implemented interfaces...
4309 for (i = 0; i < class->interface_offsets_count; i++) {
4310 MonoClass *parent = class->parent;
4312 gboolean interface_is_explicitly_implemented_by_class;
4315 ic = class->interfaces_packed [i];
4316 ic_offset = mono_class_interface_offset (class, ic);
4318 mono_class_setup_methods (ic);
4319 if (ic->exception_type)
4322 // Check if this interface is explicitly implemented (instead of just inherited)
4323 if (parent != NULL) {
4324 int implemented_interfaces_index;
4325 interface_is_explicitly_implemented_by_class = FALSE;
4326 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4327 if (ic == class->interfaces [implemented_interfaces_index]) {
4328 interface_is_explicitly_implemented_by_class = TRUE;
4333 interface_is_explicitly_implemented_by_class = TRUE;
4336 // Loop on all interface methods...
4337 for (im_index = 0; im_index < ic->method.count; im_index++) {
4338 MonoMethod *im = ic->methods [im_index];
4339 int im_slot = ic_offset + im->slot;
4340 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4342 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4345 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4347 // If there is an explicit implementation, just use it right away,
4348 // otherwise look for a matching method
4349 if (override_im == NULL) {
4354 // First look for a suitable method among the class methods
4356 for (l = virt_methods; l; l = l->next) {
4358 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)));
4359 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4360 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4361 vtable [im_slot] = cm;
4362 /* Why do we need this? */
4367 TRACE_INTERFACE_VTABLE (printf ("\n"));
4368 if (class->exception_type) /*Might be set by check_interface_method_override*/
4372 // If the slot is still empty, look in all the inherited virtual methods...
4373 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4374 MonoClass *parent = class->parent;
4375 // Reverse order, so that last added methods are preferred
4376 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4377 MonoMethod *cm = parent->vtable [cm_index];
4379 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));
4380 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4381 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4382 vtable [im_slot] = cm;
4383 /* Why do we need this? */
4389 if (class->exception_type) /*Might be set by check_interface_method_override*/
4391 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4395 g_assert (vtable [im_slot] == override_im);
4400 // If the class is not abstract, check that all its interface slots are full.
4401 // The check is done here and not directly at the end of the loop above because
4402 // it can happen (for injected generic array interfaces) that the same slot is
4403 // processed multiple times (those interfaces have overlapping slots), and it
4404 // will not always be the first pass the one that fills the slot.
4405 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4406 for (i = 0; i < class->interface_offsets_count; i++) {
4410 ic = class->interfaces_packed [i];
4411 ic_offset = mono_class_interface_offset (class, ic);
4413 for (im_index = 0; im_index < ic->method.count; im_index++) {
4414 MonoMethod *im = ic->methods [im_index];
4415 int im_slot = ic_offset + im->slot;
4417 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4420 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4421 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4422 if (vtable [im_slot] == NULL) {
4423 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4430 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4432 for (l = virt_methods; l; l = l->next) {
4435 * If the method is REUSE_SLOT, we must check in the
4436 * base class for a method to override.
4438 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4440 for (k = class->parent; k ; k = k->parent) {
4445 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4446 MonoMethodSignature *cmsig, *m1sig;
4448 cmsig = mono_method_signature (cm);
4449 m1sig = mono_method_signature (m1);
4451 if (!cmsig || !m1sig) {
4452 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4456 if (!strcmp(cm->name, m1->name) &&
4457 mono_metadata_signature_equal (cmsig, m1sig)) {
4459 /* CAS - SecurityAction.InheritanceDemand */
4460 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4461 mono_secman_inheritancedemand_method (cm, m1);
4464 if (mono_security_core_clr_enabled ())
4465 mono_security_core_clr_check_override (class, cm, m1);
4467 slot = mono_method_get_vtable_slot (m1);
4471 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4472 char *body_name = mono_method_full_name (cm, TRUE);
4473 char *decl_name = mono_method_full_name (m1, TRUE);
4474 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));
4480 g_assert (cm->slot < max_vtsize);
4482 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4483 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4484 mono_method_full_name (m1, 1), m1,
4485 mono_method_full_name (cm, 1), cm));
4486 g_hash_table_insert (override_map, m1, cm);
4490 if (k->exception_type)
4500 /*Non final newslot methods must be given a non-interface vtable slot*/
4501 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4505 cm->slot = cur_slot++;
4507 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4508 vtable [cm->slot] = cm;
4511 /* override non interface methods */
4512 for (i = 0; i < onum; i++) {
4513 MonoMethod *decl = overrides [i*2];
4514 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4515 g_assert (decl->slot != -1);
4516 vtable [decl->slot] = overrides [i*2 + 1];
4517 overrides [i * 2 + 1]->slot = decl->slot;
4519 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4520 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4521 mono_method_full_name (decl, 1), decl,
4522 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4523 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4525 if (mono_security_core_clr_enabled ())
4526 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4531 * If a method occupies more than one place in the vtable, and it is
4532 * overriden, then change the other occurances too.
4537 for (i = 0; i < max_vtsize; ++i)
4539 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4541 cm = g_hash_table_lookup (override_map, vtable [i]);
4546 g_hash_table_destroy (override_map);
4547 override_map = NULL;
4550 g_slist_free (virt_methods);
4551 virt_methods = NULL;
4553 /* Ensure that all vtable slots are filled with concrete instance methods */
4554 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4555 for (i = 0; i < cur_slot; ++i) {
4556 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4557 char *type_name = mono_type_get_full_name (class);
4558 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4559 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));
4561 g_free (method_name);
4567 if (class->generic_class) {
4568 MonoClass *gklass = class->generic_class->container_class;
4570 mono_class_init (gklass);
4572 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4574 /* Check that the vtable_size value computed in mono_class_init () is correct */
4575 if (class->vtable_size)
4576 g_assert (cur_slot == class->vtable_size);
4577 class->vtable_size = cur_slot;
4580 /* Try to share the vtable with our parent. */
4581 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4582 mono_memory_barrier ();
4583 class->vtable = class->parent->vtable;
4585 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4586 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4587 mono_memory_barrier ();
4588 class->vtable = tmp;
4591 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4592 if (mono_print_vtable) {
4595 print_implemented_interfaces (class);
4597 for (i = 0; i <= max_iid; i++)
4598 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4601 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4602 class->vtable_size, icount);
4604 for (i = 0; i < cur_slot; ++i) {
4609 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4610 mono_method_full_name (cm, TRUE));
4616 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4617 class->name, max_iid);
4619 for (i = 0; i < class->interface_count; i++) {
4620 ic = class->interfaces [i];
4621 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4622 mono_class_interface_offset (class, ic),
4623 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4626 for (k = class->parent; k ; k = k->parent) {
4627 for (i = 0; i < k->interface_count; i++) {
4628 ic = k->interfaces [i];
4629 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4630 mono_class_interface_offset (class, ic),
4631 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4637 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4642 char *name = mono_type_get_full_name (class);
4643 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4646 g_hash_table_destroy (override_map);
4648 g_slist_free (virt_methods);
4653 * mono_method_get_vtable_slot:
4655 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4656 * LOCKING: Acquires the loader lock.
4658 * FIXME Use proper MonoError machinery here.
4661 mono_method_get_vtable_slot (MonoMethod *method)
4663 if (method->slot == -1) {
4664 mono_class_setup_vtable (method->klass);
4665 if (method->klass->exception_type)
4667 if (method->slot == -1) {
4671 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4672 g_assert (method->klass->generic_class);
4673 gklass = method->klass->generic_class->container_class;
4674 mono_class_setup_methods (method->klass);
4675 g_assert (method->klass->methods);
4676 for (i = 0; i < method->klass->method.count; ++i) {
4677 if (method->klass->methods [i] == method)
4680 g_assert (i < method->klass->method.count);
4681 g_assert (gklass->methods);
4682 method->slot = gklass->methods [i]->slot;
4684 g_assert (method->slot != -1);
4686 return method->slot;
4690 * mono_method_get_vtable_index:
4693 * Returns the index into the runtime vtable to access the method or,
4694 * in the case of a virtual generic method, the virtual generic method
4695 * thunk. Returns -1 on failure.
4697 * FIXME Use proper MonoError machinery here.
4700 mono_method_get_vtable_index (MonoMethod *method)
4702 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4703 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4704 if (imethod->declaring->is_generic)
4705 return mono_method_get_vtable_slot (imethod->declaring);
4707 return mono_method_get_vtable_slot (method);
4710 static MonoMethod *default_ghc = NULL;
4711 static MonoMethod *default_finalize = NULL;
4712 static int finalize_slot = -1;
4713 static int ghc_slot = -1;
4716 initialize_object_slots (MonoClass *class)
4721 if (class == mono_defaults.object_class) {
4722 mono_class_setup_vtable (class);
4723 for (i = 0; i < class->vtable_size; ++i) {
4724 MonoMethod *cm = class->vtable [i];
4726 if (!strcmp (cm->name, "GetHashCode"))
4728 else if (!strcmp (cm->name, "Finalize"))
4732 g_assert (ghc_slot > 0);
4733 default_ghc = class->vtable [ghc_slot];
4735 g_assert (finalize_slot > 0);
4736 default_finalize = class->vtable [finalize_slot];
4741 MonoMethod *array_method;
4743 } GenericArrayMethodInfo;
4745 static int generic_array_method_num = 0;
4746 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4749 generic_array_methods (MonoClass *class)
4751 int i, count_generic = 0;
4752 GList *list = NULL, *tmp;
4753 if (generic_array_method_num)
4754 return generic_array_method_num;
4755 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4756 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4757 for (i = 0; i < class->parent->method.count; i++) {
4758 MonoMethod *m = class->parent->methods [i];
4759 if (!strncmp (m->name, "InternalArray__", 15)) {
4761 list = g_list_prepend (list, m);
4764 list = g_list_reverse (list);
4765 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4767 for (tmp = list; tmp; tmp = tmp->next) {
4768 const char *mname, *iname;
4770 MonoMethod *m = tmp->data;
4771 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4772 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4774 generic_array_method_info [i].array_method = m;
4775 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4776 iname = "System.Collections.Generic.ICollection`1.";
4777 mname = m->name + 27;
4778 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4779 iname = "System.Collections.Generic.IEnumerable`1.";
4780 mname = m->name + 27;
4781 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4782 iname = "System.Collections.Generic.IReadOnlyList`1.";
4783 mname = m->name + strlen (ireadonlylist_prefix);
4784 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4785 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4786 mname = m->name + strlen (ireadonlycollection_prefix);
4787 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4788 iname = "System.Collections.Generic.IList`1.";
4789 mname = m->name + 15;
4791 g_assert_not_reached ();
4794 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4795 strcpy (name, iname);
4796 strcpy (name + strlen (iname), mname);
4797 generic_array_method_info [i].name = name;
4800 /*g_print ("array generic methods: %d\n", count_generic);*/
4802 generic_array_method_num = count_generic;
4804 return generic_array_method_num;
4808 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4810 MonoGenericContext tmp_context;
4813 tmp_context.class_inst = NULL;
4814 tmp_context.method_inst = iface->generic_class->context.class_inst;
4815 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4817 for (i = 0; i < generic_array_method_num; i++) {
4818 MonoMethod *m = generic_array_method_info [i].array_method;
4819 MonoMethod *inflated;
4821 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4822 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4827 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4829 int null_length = strlen ("(null)");
4830 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4831 char *s = mono_image_alloc (image, len);
4834 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4835 g_assert (result == len - 1);
4841 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4843 gpointer exception_data = NULL;
4845 switch (error->exception_type) {
4846 case MONO_EXCEPTION_TYPE_LOAD:
4847 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4850 case MONO_EXCEPTION_MISSING_METHOD:
4851 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4854 case MONO_EXCEPTION_MISSING_FIELD: {
4855 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4856 const char *class_name;
4859 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4861 class_name = error->klass->name;
4863 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4866 g_free ((void*)class_name);
4870 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4873 if (error->ref_only)
4874 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.";
4876 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4878 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4882 case MONO_EXCEPTION_BAD_IMAGE:
4883 exception_data = error->msg;
4887 g_assert_not_reached ();
4890 mono_class_set_failure (class, error->exception_type, exception_data);
4895 * @class: the class to initialize
4897 * Compute the instance_size, class_size and other infos that cannot be
4898 * computed at mono_class_get() time. Also compute vtable_size if possible.
4899 * Returns TRUE on success or FALSE if there was a problem in loading
4900 * the type (incorrect assemblies, missing assemblies, methods, etc).
4902 * LOCKING: Acquires the loader lock.
4905 mono_class_init (MonoClass *class)
4908 MonoCachedClassInfo cached_info;
4909 gboolean has_cached_info;
4913 /* Double-checking locking pattern */
4914 if (class->inited || class->exception_type)
4915 return class->exception_type == MONO_EXCEPTION_NONE;
4917 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4919 /* We do everything inside the lock to prevent races */
4920 mono_loader_lock ();
4922 if (class->inited || class->exception_type) {
4923 mono_loader_unlock ();
4924 /* Somebody might have gotten in before us */
4925 return class->exception_type == MONO_EXCEPTION_NONE;
4928 if (class->init_pending) {
4929 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4933 class->init_pending = 1;
4935 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4936 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4941 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4942 MonoClass *element_class = class->element_class;
4943 if (!element_class->inited)
4944 mono_class_init (element_class);
4945 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4946 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4951 /* CAS - SecurityAction.InheritanceDemand */
4952 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4953 mono_secman_inheritancedemand_class (class, class->parent);
4956 mono_stats.initialized_class_count++;
4958 if (class->generic_class && !class->generic_class->is_dynamic) {
4959 MonoClass *gklass = class->generic_class->container_class;
4961 mono_stats.generic_class_count++;
4963 class->method = gklass->method;
4964 class->field = gklass->field;
4966 mono_class_init (gklass);
4967 // FIXME: Why is this needed ?
4968 if (!gklass->exception_type)
4969 mono_class_setup_methods (gklass);
4970 if (gklass->exception_type) {
4971 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4975 if (MONO_CLASS_IS_INTERFACE (class))
4976 class->interface_id = mono_get_unique_iid (class);
4979 if (class->parent && !class->parent->inited)
4980 mono_class_init (class->parent);
4982 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
4984 if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
4985 class->nested_classes_inited = TRUE;
4988 * Computes the size used by the fields, and their locations
4990 if (has_cached_info) {
4991 class->instance_size = cached_info.instance_size;
4992 class->sizes.class_size = cached_info.class_size;
4993 class->packing_size = cached_info.packing_size;
4994 class->min_align = cached_info.min_align;
4995 class->blittable = cached_info.blittable;
4996 class->has_references = cached_info.has_references;
4997 class->has_static_refs = cached_info.has_static_refs;
4998 class->no_special_static_fields = cached_info.no_special_static_fields;
5001 if (!class->size_inited){
5002 mono_class_setup_fields (class);
5003 if (class->exception_type || mono_loader_get_last_error ())
5007 /* Initialize arrays */
5009 class->method.count = 3 + (class->rank > 1? 2: 1);
5011 if (class->interface_count) {
5012 int count_generic = generic_array_methods (class);
5013 class->method.count += class->interface_count * count_generic;
5017 mono_class_setup_supertypes (class);
5020 initialize_object_slots (class);
5023 * Initialize the rest of the data without creating a generic vtable if possible.
5024 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5025 * also avoid computing a generic vtable.
5027 if (has_cached_info) {
5029 class->vtable_size = cached_info.vtable_size;
5030 class->has_finalize = cached_info.has_finalize;
5031 class->has_finalize_inited = TRUE;
5032 class->ghcimpl = cached_info.ghcimpl;
5033 class->has_cctor = cached_info.has_cctor;
5034 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5035 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5036 * The first slot if for array with.
5038 static int szarray_vtable_size[2] = { 0 };
5040 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5043 if (!szarray_vtable_size [slot]) {
5044 mono_class_setup_vtable (class);
5045 szarray_vtable_size [slot] = class->vtable_size;
5047 class->vtable_size = szarray_vtable_size[slot];
5049 class->has_finalize_inited = TRUE;
5050 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5051 MonoClass *gklass = class->generic_class->container_class;
5053 /* Generic instance case */
5054 class->ghcimpl = gklass->ghcimpl;
5055 class->has_finalize = mono_class_has_finalizer (gklass);
5056 class->has_finalize_inited = TRUE;
5057 class->has_cctor = gklass->has_cctor;
5059 mono_class_setup_vtable (gklass);
5060 if (gklass->exception_type) {
5061 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5065 class->vtable_size = gklass->vtable_size;
5069 /* ghcimpl is not currently used
5071 if (class->parent) {
5072 MonoMethod *cmethod = class->vtable [ghc_slot];
5073 if (cmethod->is_inflated)
5074 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5075 if (cmethod == default_ghc) {
5081 /* C# doesn't allow interfaces to have cctors */
5082 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5083 MonoMethod *cmethod = NULL;
5085 if (class->type_token) {
5086 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5087 /* The find_method function ignores the 'flags' argument */
5088 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5089 class->has_cctor = 1;
5091 mono_class_setup_methods (class);
5092 if (class->exception_type)
5095 for (i = 0; i < class->method.count; ++i) {
5096 MonoMethod *method = class->methods [i];
5097 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5098 (strcmp (".cctor", method->name) == 0)) {
5099 class->has_cctor = 1;
5107 if (class->parent) {
5108 int first_iface_slot;
5109 /* This will compute class->parent->vtable_size for some classes */
5110 mono_class_init (class->parent);
5111 if (class->parent->exception_type) {
5112 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5115 if (mono_loader_get_last_error ())
5117 if (!class->parent->vtable_size) {
5118 /* FIXME: Get rid of this somehow */
5119 mono_class_setup_vtable (class->parent);
5120 if (class->parent->exception_type) {
5121 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5124 if (mono_loader_get_last_error ())
5127 first_iface_slot = class->parent->vtable_size;
5128 if (mono_class_need_stelemref_method (class))
5130 setup_interface_offsets (class, first_iface_slot, TRUE);
5132 setup_interface_offsets (class, 0, TRUE);
5135 if (mono_security_core_clr_enabled ())
5136 mono_security_core_clr_check_inheritance (class);
5138 if (mono_loader_get_last_error ()) {
5139 if (class->exception_type == MONO_EXCEPTION_NONE) {
5140 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5142 mono_loader_clear_error ();
5145 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5146 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5151 /* Because of the double-checking locking pattern */
5152 mono_memory_barrier ();
5154 class->init_pending = 0;
5156 mono_loader_unlock ();
5158 if (mono_debugger_class_init_func)
5159 mono_debugger_class_init_func (class);
5161 return class->exception_type == MONO_EXCEPTION_NONE;
5165 * mono_class_has_finalizer:
5167 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5171 mono_class_has_finalizer (MonoClass *klass)
5173 if (!klass->has_finalize_inited) {
5174 MonoClass *class = klass;
5176 mono_loader_lock ();
5178 /* Interfaces and valuetypes are not supposed to have finalizers */
5179 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5180 MonoMethod *cmethod = NULL;
5182 if (class->parent && class->parent->has_finalize) {
5183 class->has_finalize = 1;
5185 if (class->parent) {
5187 * Can't search in metadata for a method named Finalize, because that
5188 * ignores overrides.
5190 mono_class_setup_vtable (class);
5191 if (class->exception_type || mono_loader_get_last_error ())
5193 cmethod = class->vtable [finalize_slot];
5197 g_assert (class->vtable_size > finalize_slot);
5199 class->has_finalize = 0;
5200 if (class->parent) {
5201 if (cmethod->is_inflated)
5202 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5203 if (cmethod != default_finalize) {
5204 class->has_finalize = 1;
5211 mono_memory_barrier ();
5212 klass->has_finalize_inited = TRUE;
5214 mono_loader_unlock ();
5217 return klass->has_finalize;
5220 mono_loader_unlock ();
5225 mono_is_corlib_image (MonoImage *image)
5227 /* FIXME: allow the dynamic case for our compilers and with full trust */
5229 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5231 return image == mono_defaults.corlib;
5235 * LOCKING: this assumes the loader lock is held
5238 mono_class_setup_mono_type (MonoClass *class)
5240 const char *name = class->name;
5241 const char *nspace = class->name_space;
5242 gboolean is_corlib = mono_is_corlib_image (class->image);
5244 class->this_arg.byref = 1;
5245 class->this_arg.data.klass = class;
5246 class->this_arg.type = MONO_TYPE_CLASS;
5247 class->byval_arg.data.klass = class;
5248 class->byval_arg.type = MONO_TYPE_CLASS;
5250 if (is_corlib && !strcmp (nspace, "System")) {
5251 if (!strcmp (name, "ValueType")) {
5253 * do not set the valuetype bit for System.ValueType.
5254 * class->valuetype = 1;
5256 class->blittable = TRUE;
5257 } else if (!strcmp (name, "Enum")) {
5259 * do not set the valuetype bit for System.Enum.
5260 * class->valuetype = 1;
5262 class->valuetype = 0;
5263 class->enumtype = 0;
5264 } else if (!strcmp (name, "Object")) {
5265 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5266 } else if (!strcmp (name, "String")) {
5267 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5268 } else if (!strcmp (name, "TypedReference")) {
5269 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5273 if (class->valuetype) {
5274 int t = MONO_TYPE_VALUETYPE;
5276 if (is_corlib && !strcmp (nspace, "System")) {
5279 if (!strcmp (name, "Boolean")) {
5280 t = MONO_TYPE_BOOLEAN;
5281 } else if (!strcmp(name, "Byte")) {
5283 class->blittable = TRUE;
5287 if (!strcmp (name, "Char")) {
5292 if (!strcmp (name, "Double")) {
5294 class->blittable = TRUE;
5298 if (!strcmp (name, "Int32")) {
5300 class->blittable = TRUE;
5301 } else if (!strcmp(name, "Int16")) {
5303 class->blittable = TRUE;
5304 } else if (!strcmp(name, "Int64")) {
5306 class->blittable = TRUE;
5307 } else if (!strcmp(name, "IntPtr")) {
5309 class->blittable = TRUE;
5313 if (!strcmp (name, "Single")) {
5315 class->blittable = TRUE;
5316 } else if (!strcmp(name, "SByte")) {
5318 class->blittable = TRUE;
5322 if (!strcmp (name, "UInt32")) {
5324 class->blittable = TRUE;
5325 } else if (!strcmp(name, "UInt16")) {
5327 class->blittable = TRUE;
5328 } else if (!strcmp(name, "UInt64")) {
5330 class->blittable = TRUE;
5331 } else if (!strcmp(name, "UIntPtr")) {
5333 class->blittable = TRUE;
5337 if (!strcmp (name, "TypedReference")) {
5338 t = MONO_TYPE_TYPEDBYREF;
5339 class->blittable = TRUE;
5343 if (!strcmp (name, "Void")) {
5351 class->this_arg.type = class->byval_arg.type = t;
5354 if (MONO_CLASS_IS_INTERFACE (class))
5355 class->interface_id = mono_get_unique_iid (class);
5361 * COM initialization is delayed until needed.
5362 * However when a [ComImport] attribute is present on a type it will trigger
5363 * the initialization. This is not a problem unless the BCL being executed
5364 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5367 init_com_from_comimport (MonoClass *class)
5369 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5370 if (mono_security_core_clr_enabled ()) {
5371 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5372 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5373 /* but it can not be made available for application (i.e. user code) since all COM calls
5374 * are considered native calls. In this case we fail with a TypeLoadException (just like
5375 * Silverlight 2 does */
5376 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5381 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5383 #endif /*DISABLE_COM*/
5386 * LOCKING: this assumes the loader lock is held
5389 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5391 gboolean system_namespace;
5392 gboolean is_corlib = mono_is_corlib_image (class->image);
5394 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5396 /* if root of the hierarchy */
5397 if (system_namespace && !strcmp (class->name, "Object")) {
5398 class->parent = NULL;
5399 class->instance_size = sizeof (MonoObject);
5402 if (!strcmp (class->name, "<Module>")) {
5403 class->parent = NULL;
5404 class->instance_size = 0;
5408 if (!MONO_CLASS_IS_INTERFACE (class)) {
5409 /* Imported COM Objects always derive from __ComObject. */
5411 if (MONO_CLASS_IS_IMPORT (class)) {
5412 init_com_from_comimport (class);
5413 if (parent == mono_defaults.object_class)
5414 parent = mono_class_get_com_object_class ();
5418 /* set the parent to something useful and safe, but mark the type as broken */
5419 parent = mono_defaults.object_class;
5420 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5423 class->parent = parent;
5425 if (parent->generic_class && !parent->name) {
5427 * If the parent is a generic instance, we may get
5428 * called before it is fully initialized, especially
5429 * before it has its name.
5434 #ifndef DISABLE_REMOTING
5435 class->marshalbyref = parent->marshalbyref;
5436 class->contextbound = parent->contextbound;
5439 class->delegate = parent->delegate;
5441 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5442 mono_class_set_is_com_object (class);
5444 if (system_namespace) {
5445 #ifndef DISABLE_REMOTING
5446 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5447 class->marshalbyref = 1;
5449 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5450 class->contextbound = 1;
5452 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5453 class->delegate = 1;
5456 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5457 (strcmp (class->parent->name_space, "System") == 0)))
5458 class->valuetype = 1;
5459 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5460 class->valuetype = class->enumtype = 1;
5462 /*class->enumtype = class->parent->enumtype; */
5464 /* initialize com types if COM interfaces are present */
5466 if (MONO_CLASS_IS_IMPORT (class))
5467 init_com_from_comimport (class);
5469 class->parent = NULL;
5475 * mono_class_setup_supertypes:
5478 * Build the data structure needed to make fast type checks work.
5479 * This currently sets two fields in @class:
5480 * - idepth: distance between @class and System.Object in the type
5482 * - supertypes: array of classes: each element has a class in the hierarchy
5483 * starting from @class up to System.Object
5485 * LOCKING: this assumes the loader lock is held
5488 mono_class_setup_supertypes (MonoClass *class)
5491 MonoClass **supertypes;
5493 if (class->supertypes)
5496 if (class->parent && !class->parent->supertypes)
5497 mono_class_setup_supertypes (class->parent);
5499 class->idepth = class->parent->idepth + 1;
5503 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5504 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5506 if (class->parent) {
5507 supertypes [class->idepth - 1] = class;
5508 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5510 supertypes [0] = class;
5513 mono_atomic_store_release (&class->supertypes, supertypes);
5517 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5519 MonoClass *gtd = (MonoClass*)user_data;
5520 /* Only try to fix generic instances of @gtd */
5521 if (gclass->generic_class->container_class != gtd)
5524 /* Check if the generic instance has no parent. */
5525 if (gtd->parent && !gclass->parent)
5526 mono_generic_class_setup_parent (gclass, gtd);
5532 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5534 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5535 mono_error_set_type_load_class (error, class, msg);
5539 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5541 MonoLoaderError *lerror = mono_loader_get_last_error ();
5544 set_failure_from_loader_error (class, lerror);
5545 mono_error_set_from_loader_error (error);
5549 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5550 mono_error_set_type_load_class (error, class, msg);
5555 * mono_class_create_from_typedef:
5556 * @image: image where the token is valid
5557 * @type_token: typedef token
5558 * @error: used to return any error found while creating the type
5560 * Create the MonoClass* representing the specified type token.
5561 * @type_token must be a TypeDef token.
5563 * FIXME: don't return NULL on failure, just the the caller figure it out.
5566 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5568 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5569 MonoClass *class, *parent = NULL;
5570 guint32 cols [MONO_TYPEDEF_SIZE];
5571 guint32 cols_next [MONO_TYPEDEF_SIZE];
5572 guint tidx = mono_metadata_token_index (type_token);
5573 MonoGenericContext *context = NULL;
5574 const char *name, *nspace;
5576 MonoClass **interfaces;
5577 guint32 field_last, method_last;
5578 guint32 nesting_tokeen;
5580 mono_error_init (error);
5582 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5583 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5584 g_assert (!mono_loader_get_last_error ());
5588 mono_loader_lock ();
5590 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5591 mono_loader_unlock ();
5592 g_assert (!mono_loader_get_last_error ());
5596 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5598 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5599 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5601 class = mono_image_alloc0 (image, sizeof (MonoClass));
5604 class->name_space = nspace;
5606 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5608 class->image = image;
5609 class->type_token = type_token;
5610 class->flags = cols [MONO_TYPEDEF_FLAGS];
5612 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5614 classes_size += sizeof (MonoClass);
5617 * Check whether we're a generic type definition.
5619 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5620 if (class->generic_container) {
5621 class->is_generic = 1;
5622 class->generic_container->owner.klass = class;
5623 context = &class->generic_container->context;
5626 if (class->generic_container)
5627 enable_gclass_recording ();
5629 if (cols [MONO_TYPEDEF_EXTENDS]) {
5631 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5633 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5634 /*WARNING: this must satisfy mono_metadata_type_hash*/
5635 class->this_arg.byref = 1;
5636 class->this_arg.data.klass = class;
5637 class->this_arg.type = MONO_TYPE_CLASS;
5638 class->byval_arg.data.klass = class;
5639 class->byval_arg.type = MONO_TYPE_CLASS;
5641 parent = mono_class_get_full (image, parent_token, context);
5643 if (parent == NULL) {
5644 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5645 goto parent_failure;
5648 for (tmp = parent; tmp; tmp = tmp->parent) {
5650 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5651 goto parent_failure;
5653 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5654 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5655 goto parent_failure;
5660 mono_class_setup_parent (class, parent);
5662 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5663 mono_class_setup_mono_type (class);
5665 if (class->generic_container)
5666 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5669 * This might access class->byval_arg for recursion generated by generic constraints,
5670 * so it has to come after setup_mono_type ().
5672 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5673 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5674 if (!mono_error_ok (error)) {
5675 /*FIXME implement a mono_class_set_failure_from_mono_error */
5676 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5677 mono_loader_unlock ();
5678 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5679 g_assert (!mono_loader_get_last_error ());
5684 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5688 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5692 class->cast_class = class->element_class = class;
5694 if (!class->enumtype) {
5695 if (!mono_metadata_interfaces_from_typedef_full (
5696 image, type_token, &interfaces, &icount, FALSE, context)){
5697 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5698 mono_loader_unlock ();
5699 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5703 class->interfaces = interfaces;
5704 class->interface_count = icount;
5705 class->interfaces_inited = 1;
5708 /*g_print ("Load class %s\n", name);*/
5711 * Compute the field and method lists
5713 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5714 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5716 if (tt->rows > tidx){
5717 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5718 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5719 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5721 field_last = image->tables [MONO_TABLE_FIELD].rows;
5722 method_last = image->tables [MONO_TABLE_METHOD].rows;
5725 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5726 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5727 class->field.count = field_last - class->field.first;
5729 class->field.count = 0;
5731 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5732 class->method.count = method_last - class->method.first;
5734 class->method.count = 0;
5736 /* reserve space to store vector pointer in arrays */
5737 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5738 class->instance_size += 2 * sizeof (gpointer);
5739 g_assert (class->field.count == 0);
5742 if (class->enumtype) {
5743 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5744 if (!enum_basetype) {
5745 /*set it to a default value as the whole runtime can't handle this to be null*/
5746 class->cast_class = class->element_class = mono_defaults.int32_class;
5747 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5748 mono_loader_unlock ();
5749 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5750 g_assert (!mono_loader_get_last_error ());
5753 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5757 * If we're a generic type definition, load the constraints.
5758 * We must do this after the class has been constructed to make certain recursive scenarios
5761 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5762 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5763 mono_loader_unlock ();
5764 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5765 g_assert (!mono_loader_get_last_error ());
5769 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5770 if (!strncmp (name, "Vector", 6))
5771 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");
5774 mono_loader_unlock ();
5776 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5777 g_assert (!mono_loader_get_last_error ());
5782 mono_class_setup_mono_type (class);
5783 mono_loader_unlock ();
5784 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5785 g_assert (!mono_loader_get_last_error ());
5789 /** is klass Nullable<T>? */
5791 mono_class_is_nullable (MonoClass *klass)
5793 return klass->generic_class != NULL &&
5794 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5798 /** if klass is T? return T */
5800 mono_class_get_nullable_param (MonoClass *klass)
5802 g_assert (mono_class_is_nullable (klass));
5803 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5807 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5811 MonoGenericClass *gclass = klass->generic_class;
5813 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5814 if (!mono_error_ok (&error)) {
5815 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5816 klass->parent = mono_defaults.object_class;
5817 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5818 mono_error_cleanup (&error);
5822 mono_class_setup_parent (klass, klass->parent);
5824 if (klass->enumtype) {
5825 klass->cast_class = gtd->cast_class;
5826 klass->element_class = gtd->element_class;
5832 * Create the `MonoClass' for an instantiation of a generic type.
5833 * We only do this if we actually need it.
5836 mono_generic_class_get_class (MonoGenericClass *gclass)
5838 MonoClass *klass, *gklass;
5840 if (gclass->cached_class)
5841 return gclass->cached_class;
5843 mono_loader_lock ();
5844 if (gclass->cached_class) {
5845 mono_loader_unlock ();
5846 return gclass->cached_class;
5849 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5851 gklass = gclass->container_class;
5853 if (record_gclass_instantiation > 0)
5854 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5856 if (gklass->nested_in) {
5857 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5858 klass->nested_in = gklass->nested_in;
5861 klass->name = gklass->name;
5862 klass->name_space = gklass->name_space;
5864 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5866 klass->image = gklass->image;
5867 klass->flags = gklass->flags;
5868 klass->type_token = gklass->type_token;
5869 klass->field.count = gklass->field.count;
5871 klass->is_inflated = 1;
5872 klass->generic_class = gclass;
5874 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5875 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5876 klass->this_arg.byref = TRUE;
5877 klass->enumtype = gklass->enumtype;
5878 klass->valuetype = gklass->valuetype;
5880 klass->cast_class = klass->element_class = klass;
5882 if (mono_class_is_nullable (klass))
5883 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5886 * We're not interested in the nested classes of a generic instance.
5887 * We use the generic type definition to look for nested classes.
5890 mono_generic_class_setup_parent (klass, gklass);
5892 if (gclass->is_dynamic) {
5895 mono_class_setup_supertypes (klass);
5897 if (klass->enumtype) {
5899 * For enums, gklass->fields might not been set, but instance_size etc. is
5900 * already set in mono_reflection_create_internal_class (). For non-enums,
5901 * these will be computed normally in mono_class_layout_fields ().
5903 klass->instance_size = gklass->instance_size;
5904 klass->sizes.class_size = gklass->sizes.class_size;
5905 mono_memory_barrier ();
5906 klass->size_inited = 1;
5910 mono_memory_barrier ();
5911 gclass->cached_class = klass;
5913 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5915 inflated_classes ++;
5916 inflated_classes_size += sizeof (MonoClass);
5918 mono_loader_unlock ();
5924 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5926 MonoClass *klass, **ptr;
5928 MonoGenericContainer *container = mono_generic_param_owner (param);
5932 image = mono_defaults.corlib;
5934 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5935 classes_size += sizeof (MonoClass);
5938 klass->name = pinfo->name;
5940 int n = mono_generic_param_num (param);
5941 klass->name = mono_image_alloc0 (image, 16);
5942 sprintf ((char*)klass->name, "%d", n);
5947 MonoMethod *omethod = container->owner.method;
5948 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5950 MonoClass *oklass = container->owner.klass;
5951 klass->name_space = oklass ? oklass->name_space : "";
5954 klass->name_space = "";
5957 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5961 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5965 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5966 klass->parent = pinfo->constraints [0];
5968 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5969 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5971 klass->parent = mono_defaults.object_class;
5974 if (count - pos > 0) {
5975 klass->interface_count = count - pos;
5976 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5977 klass->interfaces_inited = TRUE;
5978 for (i = pos; i < count; i++)
5979 klass->interfaces [i - pos] = pinfo->constraints [i];
5982 klass->image = image;
5984 klass->inited = TRUE;
5985 klass->cast_class = klass->element_class = klass;
5986 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5988 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5989 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5990 klass->this_arg.byref = TRUE;
5992 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5993 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5995 /*Init these fields to sane values*/
5996 klass->min_align = 1;
5997 klass->instance_size = sizeof (gpointer);
5998 mono_memory_barrier ();
5999 klass->size_inited = 1;
6001 mono_class_setup_supertypes (klass);
6003 if (count - pos > 0) {
6004 mono_class_setup_vtable (klass->parent);
6005 if (klass->parent->exception_type)
6006 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6008 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6014 #define FAST_CACHE_SIZE 16
6017 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6019 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6020 MonoImage *image = param->image;
6025 if (n < FAST_CACHE_SIZE) {
6027 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6029 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6031 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6032 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6037 * LOCKING: Acquires the loader lock.
6040 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6042 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6043 MonoImage *image = param->image;
6048 if (n < FAST_CACHE_SIZE) {
6050 /* No locking needed */
6051 if (!image->mvar_cache_fast)
6052 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6053 image->mvar_cache_fast [n] = klass;
6055 if (!image->var_cache_fast)
6056 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6057 image->var_cache_fast [n] = klass;
6061 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6063 mono_loader_lock ();
6064 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6066 ht = g_hash_table_new (NULL, NULL);
6067 mono_memory_barrier ();
6069 image->mvar_cache_slow = ht;
6071 image->var_cache_slow = ht;
6073 mono_loader_unlock ();
6076 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6080 * LOCKING: Acquires the loader lock.
6083 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6085 MonoGenericContainer *container = mono_generic_param_owner (param);
6086 MonoGenericParamInfo *pinfo;
6089 mono_loader_lock ();
6092 pinfo = mono_generic_param_info (param);
6093 if (pinfo->pklass) {
6094 mono_loader_unlock ();
6095 return pinfo->pklass;
6101 klass = get_anon_gparam_class (param, is_mvar);
6103 mono_loader_unlock ();
6108 if (!image && container) {
6110 MonoMethod *method = container->owner.method;
6111 image = (method && method->klass) ? method->klass->image : NULL;
6113 MonoClass *klass = container->owner.klass;
6114 // FIXME: 'klass' should not be null
6115 // But, monodis creates GenericContainers without associating a owner to it
6116 image = klass ? klass->image : NULL;
6120 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6122 mono_memory_barrier ();
6125 pinfo->pklass = klass;
6127 set_anon_gparam_class (param, is_mvar, klass);
6129 mono_loader_unlock ();
6131 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6132 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6138 mono_ptr_class_get (MonoType *type)
6141 MonoClass *el_class;
6145 el_class = mono_class_from_mono_type (type);
6146 image = el_class->image;
6148 mono_loader_lock ();
6150 if (!image->ptr_cache)
6151 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6153 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6154 mono_loader_unlock ();
6157 result = mono_image_alloc0 (image, sizeof (MonoClass));
6159 classes_size += sizeof (MonoClass);
6161 result->parent = NULL; /* no parent for PTR types */
6162 result->name_space = el_class->name_space;
6163 name = g_strdup_printf ("%s*", el_class->name);
6164 result->name = mono_image_strdup (image, name);
6167 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6169 result->image = el_class->image;
6170 result->inited = TRUE;
6171 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6172 /* Can pointers get boxed? */
6173 result->instance_size = sizeof (gpointer);
6174 result->cast_class = result->element_class = el_class;
6175 result->blittable = TRUE;
6177 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6178 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6179 result->this_arg.byref = TRUE;
6181 mono_class_setup_supertypes (result);
6183 g_hash_table_insert (image->ptr_cache, el_class, result);
6185 mono_loader_unlock ();
6187 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6193 mono_fnptr_class_get (MonoMethodSignature *sig)
6196 static GHashTable *ptr_hash = NULL;
6198 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6200 mono_loader_lock ();
6203 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6205 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6206 mono_loader_unlock ();
6209 result = g_new0 (MonoClass, 1);
6211 result->parent = NULL; /* no parent for PTR types */
6212 result->name_space = "System";
6213 result->name = "MonoFNPtrFakeClass";
6215 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6217 result->image = mono_defaults.corlib; /* need to fix... */
6218 result->inited = TRUE;
6219 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6220 /* Can pointers get boxed? */
6221 result->instance_size = sizeof (gpointer);
6222 result->cast_class = result->element_class = result;
6223 result->blittable = TRUE;
6225 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6226 result->this_arg.data.method = result->byval_arg.data.method = sig;
6227 result->this_arg.byref = TRUE;
6228 result->blittable = TRUE;
6230 mono_class_setup_supertypes (result);
6232 g_hash_table_insert (ptr_hash, sig, result);
6234 mono_loader_unlock ();
6236 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6242 mono_class_from_mono_type (MonoType *type)
6244 switch (type->type) {
6245 case MONO_TYPE_OBJECT:
6246 return type->data.klass? type->data.klass: mono_defaults.object_class;
6247 case MONO_TYPE_VOID:
6248 return type->data.klass? type->data.klass: mono_defaults.void_class;
6249 case MONO_TYPE_BOOLEAN:
6250 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6251 case MONO_TYPE_CHAR:
6252 return type->data.klass? type->data.klass: mono_defaults.char_class;
6254 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6256 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6258 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6260 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6262 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6264 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6266 return type->data.klass? type->data.klass: mono_defaults.int_class;
6268 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6270 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6272 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6274 return type->data.klass? type->data.klass: mono_defaults.single_class;
6276 return type->data.klass? type->data.klass: mono_defaults.double_class;
6277 case MONO_TYPE_STRING:
6278 return type->data.klass? type->data.klass: mono_defaults.string_class;
6279 case MONO_TYPE_TYPEDBYREF:
6280 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6281 case MONO_TYPE_ARRAY:
6282 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6284 return mono_ptr_class_get (type->data.type);
6285 case MONO_TYPE_FNPTR:
6286 return mono_fnptr_class_get (type->data.method);
6287 case MONO_TYPE_SZARRAY:
6288 return mono_array_class_get (type->data.klass, 1);
6289 case MONO_TYPE_CLASS:
6290 case MONO_TYPE_VALUETYPE:
6291 return type->data.klass;
6292 case MONO_TYPE_GENERICINST:
6293 return mono_generic_class_get_class (type->data.generic_class);
6295 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6296 case MONO_TYPE_MVAR:
6297 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6299 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6300 g_assert_not_reached ();
6307 * mono_type_retrieve_from_typespec
6308 * @image: context where the image is created
6309 * @type_spec: typespec token
6310 * @context: the generic context used to evaluate generic instantiations in
6313 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6315 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6317 mono_error_init (error);
6318 *did_inflate = FALSE;
6321 char *name = mono_class_name_from_token (image, type_spec);
6322 char *assembly = mono_assembly_name_from_token (image, type_spec);
6323 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6327 if (context && (context->class_inst || context->method_inst)) {
6328 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6330 if (!mono_error_ok (error))
6335 *did_inflate = TRUE;
6342 * mono_class_create_from_typespec
6343 * @image: context where the image is created
6344 * @type_spec: typespec token
6345 * @context: the generic context used to evaluate generic instantiations in
6348 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6351 gboolean inflated = FALSE;
6352 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6353 if (!mono_error_ok (error))
6355 ret = mono_class_from_mono_type (t);
6357 mono_metadata_free_type (t);
6362 * mono_bounded_array_class_get:
6363 * @element_class: element class
6364 * @rank: the dimension of the array class
6365 * @bounded: whenever the array has non-zero bounds
6367 * Returns: a class object describing the array with element type @element_type and
6371 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6375 MonoClass *parent = NULL;
6376 GSList *list, *rootlist = NULL;
6379 gboolean corlib_type = FALSE;
6381 g_assert (rank <= 255);
6384 /* bounded only matters for one-dimensional arrays */
6387 image = eclass->image;
6389 if (rank == 1 && !bounded) {
6391 * This case is very frequent not just during compilation because of calls
6392 * from mono_class_from_mono_type (), mono_array_new (),
6393 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6395 EnterCriticalSection (&image->szarray_cache_lock);
6396 if (!image->szarray_cache)
6397 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6398 class = g_hash_table_lookup (image->szarray_cache, eclass);
6399 LeaveCriticalSection (&image->szarray_cache_lock);
6403 mono_loader_lock ();
6405 mono_loader_lock ();
6407 if (!image->array_cache)
6408 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6410 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6411 for (; list; list = list->next) {
6413 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6414 mono_loader_unlock ();
6421 /* for the building corlib use System.Array from it */
6422 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6423 parent = mono_class_from_name (image, "System", "Array");
6426 parent = mono_defaults.array_class;
6427 if (!parent->inited)
6428 mono_class_init (parent);
6431 class = mono_image_alloc0 (image, sizeof (MonoClass));
6433 class->image = image;
6434 class->name_space = eclass->name_space;
6435 nsize = strlen (eclass->name);
6436 name = g_malloc (nsize + 2 + rank + 1);
6437 memcpy (name, eclass->name, nsize);
6440 memset (name + nsize + 1, ',', rank - 1);
6442 name [nsize + rank] = '*';
6443 name [nsize + rank + bounded] = ']';
6444 name [nsize + rank + bounded + 1] = 0;
6445 class->name = mono_image_strdup (image, name);
6448 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6450 classes_size += sizeof (MonoClass);
6452 class->type_token = 0;
6453 /* all arrays are marked serializable and sealed, bug #42779 */
6454 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6455 class->parent = parent;
6456 class->instance_size = mono_class_instance_size (class->parent);
6458 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6459 /*Arrays of those two types are invalid.*/
6460 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6461 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6462 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6463 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6464 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6466 /* element_size -1 is ok as this is not an instantitable type*/
6467 class->sizes.element_size = -1;
6469 class->sizes.element_size = mono_class_array_element_size (eclass);
6471 mono_class_setup_supertypes (class);
6473 if (eclass->generic_class)
6474 mono_class_init (eclass);
6475 if (!eclass->size_inited)
6476 mono_class_setup_fields (eclass);
6477 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6478 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6480 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6484 if (eclass->enumtype)
6485 class->cast_class = eclass->element_class;
6487 class->cast_class = eclass;
6489 switch (class->cast_class->byval_arg.type) {
6491 class->cast_class = mono_defaults.byte_class;
6494 class->cast_class = mono_defaults.int16_class;
6497 #if SIZEOF_VOID_P == 4
6501 class->cast_class = mono_defaults.int32_class;
6504 #if SIZEOF_VOID_P == 8
6508 class->cast_class = mono_defaults.int64_class;
6512 class->element_class = eclass;
6514 if ((rank > 1) || bounded) {
6515 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6516 class->byval_arg.type = MONO_TYPE_ARRAY;
6517 class->byval_arg.data.array = at;
6518 at->eklass = eclass;
6520 /* FIXME: complete.... */
6522 class->byval_arg.type = MONO_TYPE_SZARRAY;
6523 class->byval_arg.data.klass = eclass;
6525 class->this_arg = class->byval_arg;
6526 class->this_arg.byref = 1;
6531 class->generic_container = eclass->generic_container;
6533 if (rank == 1 && !bounded) {
6534 MonoClass *prev_class;
6536 EnterCriticalSection (&image->szarray_cache_lock);
6537 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6539 /* Someone got in before us */
6542 g_hash_table_insert (image->szarray_cache, eclass, class);
6543 LeaveCriticalSection (&image->szarray_cache_lock);
6545 list = g_slist_append (rootlist, class);
6546 g_hash_table_insert (image->array_cache, eclass, list);
6549 mono_loader_unlock ();
6551 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6557 * mono_array_class_get:
6558 * @element_class: element class
6559 * @rank: the dimension of the array class
6561 * Returns: a class object describing the array with element type @element_type and
6565 mono_array_class_get (MonoClass *eclass, guint32 rank)
6567 return mono_bounded_array_class_get (eclass, rank, FALSE);
6571 * mono_class_instance_size:
6574 * Returns: the size of an object instance
6577 mono_class_instance_size (MonoClass *klass)
6579 if (!klass->size_inited)
6580 mono_class_init (klass);
6582 return klass->instance_size;
6586 * mono_class_min_align:
6589 * Returns: minimm alignment requirements
6592 mono_class_min_align (MonoClass *klass)
6594 if (!klass->size_inited)
6595 mono_class_init (klass);
6597 return klass->min_align;
6601 * mono_class_value_size:
6604 * This function is used for value types, and return the
6605 * space and the alignment to store that kind of value object.
6607 * Returns: the size of a value of kind @klass
6610 mono_class_value_size (MonoClass *klass, guint32 *align)
6614 /* fixme: check disable, because we still have external revereces to
6615 * mscorlib and Dummy Objects
6617 /*g_assert (klass->valuetype);*/
6619 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6622 *align = klass->min_align;
6628 * mono_class_data_size:
6631 * Returns: the size of the static class data
6634 mono_class_data_size (MonoClass *klass)
6637 mono_class_init (klass);
6639 /* in arrays, sizes.class_size is unioned with element_size
6640 * and arrays have no static fields
6644 return klass->sizes.class_size;
6648 * Auxiliary routine to mono_class_get_field
6650 * Takes a field index instead of a field token.
6652 static MonoClassField *
6653 mono_class_get_field_idx (MonoClass *class, int idx)
6655 mono_class_setup_fields_locking (class);
6656 if (class->exception_type)
6660 if (class->image->uncompressed_metadata) {
6662 * class->field.first points to the FieldPtr table, while idx points into the
6663 * Field table, so we have to do a search.
6665 /*FIXME this is broken for types with multiple fields with the same name.*/
6666 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6669 for (i = 0; i < class->field.count; ++i)
6670 if (mono_field_get_name (&class->fields [i]) == name)
6671 return &class->fields [i];
6672 g_assert_not_reached ();
6674 if (class->field.count) {
6675 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6676 return &class->fields [idx - class->field.first];
6680 class = class->parent;
6686 * mono_class_get_field:
6687 * @class: the class to lookup the field.
6688 * @field_token: the field token
6690 * Returns: A MonoClassField representing the type and offset of
6691 * the field, or a NULL value if the field does not belong to this
6695 mono_class_get_field (MonoClass *class, guint32 field_token)
6697 int idx = mono_metadata_token_index (field_token);
6699 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6701 return mono_class_get_field_idx (class, idx - 1);
6705 * mono_class_get_field_from_name:
6706 * @klass: the class to lookup the field.
6707 * @name: the field name
6709 * Search the class @klass and it's parents for a field with the name @name.
6711 * Returns: the MonoClassField pointer of the named field or NULL
6714 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6716 return mono_class_get_field_from_name_full (klass, name, NULL);
6720 * mono_class_get_field_from_name_full:
6721 * @klass: the class to lookup the field.
6722 * @name: the field name
6723 * @type: the type of the fields. This optional.
6725 * Search the class @klass and it's parents for a field with the name @name and type @type.
6727 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6728 * of its generic type definition.
6730 * Returns: the MonoClassField pointer of the named field or NULL
6733 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6737 mono_class_setup_fields_locking (klass);
6738 if (klass->exception_type)
6742 for (i = 0; i < klass->field.count; ++i) {
6743 MonoClassField *field = &klass->fields [i];
6745 if (strcmp (name, mono_field_get_name (field)) != 0)
6749 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6750 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6755 klass = klass->parent;
6761 * mono_class_get_field_token:
6762 * @field: the field we need the token of
6764 * Get the token of a field. Note that the tokesn is only valid for the image
6765 * the field was loaded from. Don't use this function for fields in dynamic types.
6767 * Returns: the token representing the field in the image it was loaded from.
6770 mono_class_get_field_token (MonoClassField *field)
6772 MonoClass *klass = field->parent;
6775 mono_class_setup_fields_locking (klass);
6780 for (i = 0; i < klass->field.count; ++i) {
6781 if (&klass->fields [i] == field) {
6782 int idx = klass->field.first + i + 1;
6784 if (klass->image->uncompressed_metadata)
6785 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6786 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6789 klass = klass->parent;
6792 g_assert_not_reached ();
6797 mono_field_get_index (MonoClassField *field)
6799 int index = field - field->parent->fields;
6801 g_assert (index >= 0 && index < field->parent->field.count);
6807 * mono_class_get_field_default_value:
6809 * Return the default value of the field as a pointer into the metadata blob.
6812 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6815 guint32 constant_cols [MONO_CONSTANT_SIZE];
6817 MonoClass *klass = field->parent;
6819 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6821 if (!klass->ext || !klass->ext->field_def_values) {
6822 mono_loader_lock ();
6823 mono_class_alloc_ext (klass);
6824 if (!klass->ext->field_def_values)
6825 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6826 mono_loader_unlock ();
6829 field_index = mono_field_get_index (field);
6831 if (!klass->ext->field_def_values [field_index].data) {
6832 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6836 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6838 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6839 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6840 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6843 *def_type = klass->ext->field_def_values [field_index].def_type;
6844 return klass->ext->field_def_values [field_index].data;
6848 mono_property_get_index (MonoProperty *prop)
6850 int index = prop - prop->parent->ext->properties;
6852 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6858 * mono_class_get_property_default_value:
6860 * Return the default value of the field as a pointer into the metadata blob.
6863 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6866 guint32 constant_cols [MONO_CONSTANT_SIZE];
6867 MonoClass *klass = property->parent;
6869 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6871 * We don't cache here because it is not used by C# so it's quite rare, but
6872 * we still do the lookup in klass->ext because that is where the data
6873 * is stored for dynamic assemblies.
6876 if (klass->image->dynamic) {
6877 int prop_index = mono_property_get_index (property);
6878 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6879 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6880 return klass->ext->prop_def_values [prop_index].data;
6884 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6888 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6889 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6890 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6894 mono_class_get_event_token (MonoEvent *event)
6896 MonoClass *klass = event->parent;
6901 for (i = 0; i < klass->ext->event.count; ++i) {
6902 if (&klass->ext->events [i] == event)
6903 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6906 klass = klass->parent;
6909 g_assert_not_reached ();
6914 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6918 gpointer iter = NULL;
6919 while ((p = mono_class_get_properties (klass, &iter))) {
6920 if (! strcmp (name, p->name))
6923 klass = klass->parent;
6929 mono_class_get_property_token (MonoProperty *prop)
6931 MonoClass *klass = prop->parent;
6935 gpointer iter = NULL;
6936 while ((p = mono_class_get_properties (klass, &iter))) {
6937 if (&klass->ext->properties [i] == prop)
6938 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6942 klass = klass->parent;
6945 g_assert_not_reached ();
6950 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6952 const char *name, *nspace;
6954 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6956 switch (type_token & 0xff000000){
6957 case MONO_TOKEN_TYPE_DEF: {
6958 guint32 cols [MONO_TYPEDEF_SIZE];
6959 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6960 guint tidx = mono_metadata_token_index (type_token);
6962 if (tidx > tt->rows)
6963 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6965 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6966 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6967 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6968 if (strlen (nspace) == 0)
6969 return g_strdup_printf ("%s", name);
6971 return g_strdup_printf ("%s.%s", nspace, name);
6974 case MONO_TOKEN_TYPE_REF: {
6976 guint32 cols [MONO_TYPEREF_SIZE];
6977 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6978 guint tidx = mono_metadata_token_index (type_token);
6981 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6983 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6984 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6985 mono_error_cleanup (&error);
6989 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
6990 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
6991 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
6992 if (strlen (nspace) == 0)
6993 return g_strdup_printf ("%s", name);
6995 return g_strdup_printf ("%s.%s", nspace, name);
6998 case MONO_TOKEN_TYPE_SPEC:
6999 return g_strdup_printf ("Typespec 0x%08x", type_token);
7001 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7006 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7009 return g_strdup_printf ("DynamicAssembly %s", image->name);
7011 switch (type_token & 0xff000000){
7012 case MONO_TOKEN_TYPE_DEF:
7013 if (image->assembly)
7014 return mono_stringify_assembly_name (&image->assembly->aname);
7015 else if (image->assembly_name)
7016 return g_strdup (image->assembly_name);
7017 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7018 case MONO_TOKEN_TYPE_REF: {
7020 MonoAssemblyName aname;
7021 guint32 cols [MONO_TYPEREF_SIZE];
7022 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7023 guint32 idx = mono_metadata_token_index (type_token);
7026 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7028 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7029 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7030 mono_error_cleanup (&error);
7033 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7035 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7036 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7037 case MONO_RESOLTION_SCOPE_MODULE:
7039 return g_strdup ("");
7040 case MONO_RESOLTION_SCOPE_MODULEREF:
7042 return g_strdup ("");
7043 case MONO_RESOLTION_SCOPE_TYPEREF:
7045 return g_strdup ("");
7046 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7047 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7048 return mono_stringify_assembly_name (&aname);
7050 g_assert_not_reached ();
7054 case MONO_TOKEN_TYPE_SPEC:
7056 return g_strdup ("");
7058 g_assert_not_reached ();
7065 * mono_class_get_full:
7066 * @image: the image where the class resides
7067 * @type_token: the token for the class
7068 * @context: the generic context used to evaluate generic instantiations in
7070 * Returns: the MonoClass that represents @type_token in @image
7073 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7076 MonoClass *class = NULL;
7078 if (image->dynamic) {
7079 int table = mono_metadata_token_table (type_token);
7081 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7082 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7085 return mono_lookup_dynamic_token (image, type_token, context);
7088 switch (type_token & 0xff000000){
7089 case MONO_TOKEN_TYPE_DEF:
7090 class = mono_class_create_from_typedef (image, type_token, &error);
7091 if (!mono_error_ok (&error)) {
7092 mono_loader_set_error_from_mono_error (&error);
7093 /*FIXME don't swallow the error message*/
7094 mono_error_cleanup (&error);
7098 case MONO_TOKEN_TYPE_REF:
7099 class = mono_class_from_typeref (image, type_token);
7101 case MONO_TOKEN_TYPE_SPEC:
7102 class = mono_class_create_from_typespec (image, type_token, context, &error);
7103 if (!mono_error_ok (&error)) {
7104 /*FIXME don't swallow the error message*/
7105 mono_error_cleanup (&error);
7109 g_warning ("unknown token type %x", type_token & 0xff000000);
7110 g_assert_not_reached ();
7114 char *name = mono_class_name_from_token (image, type_token);
7115 char *assembly = mono_assembly_name_from_token (image, type_token);
7116 mono_loader_set_error_type_load (name, assembly);
7126 * mono_type_get_full:
7127 * @image: the image where the type resides
7128 * @type_token: the token for the type
7129 * @context: the generic context used to evaluate generic instantiations in
7131 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7133 * Returns: the MonoType that represents @type_token in @image
7136 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7139 MonoType *type = NULL;
7140 gboolean inflated = FALSE;
7142 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7144 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7146 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7147 MonoClass *class = mono_class_get_full (image, type_token, context);
7148 return class ? mono_class_get_type (class) : NULL;
7151 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7153 if (!mono_error_ok (&error)) {
7154 /*FIXME don't swalloc the error message.*/
7155 char *name = mono_class_name_from_token (image, type_token);
7156 char *assembly = mono_assembly_name_from_token (image, type_token);
7158 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7160 mono_error_cleanup (&error);
7161 mono_loader_set_error_type_load (name, assembly);
7166 MonoType *tmp = type;
7167 type = mono_class_get_type (mono_class_from_mono_type (type));
7168 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7169 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7170 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7172 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7174 if (type->type != tmp->type)
7177 mono_metadata_free_type (tmp);
7184 mono_class_get (MonoImage *image, guint32 type_token)
7186 return mono_class_get_full (image, type_token, NULL);
7190 * mono_image_init_name_cache:
7192 * Initializes the class name cache stored in image->name_cache.
7194 * LOCKING: Acquires the corresponding image lock.
7197 mono_image_init_name_cache (MonoImage *image)
7199 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7200 guint32 cols [MONO_TYPEDEF_SIZE];
7203 guint32 i, visib, nspace_index;
7204 GHashTable *name_cache2, *nspace_table;
7206 mono_image_lock (image);
7208 if (image->name_cache) {
7209 mono_image_unlock (image);
7213 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7215 if (image->dynamic) {
7216 mono_image_unlock (image);
7220 /* Temporary hash table to avoid lookups in the nspace_table */
7221 name_cache2 = g_hash_table_new (NULL, NULL);
7223 for (i = 1; i <= t->rows; ++i) {
7224 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7225 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7227 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7228 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7230 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7232 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7233 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7235 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7236 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7237 if (!nspace_table) {
7238 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7239 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7240 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7243 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7246 /* Load type names from EXPORTEDTYPES table */
7248 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7249 guint32 cols [MONO_EXP_TYPE_SIZE];
7252 for (i = 0; i < t->rows; ++i) {
7253 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7254 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7255 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7257 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7258 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7259 if (!nspace_table) {
7260 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7261 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7262 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7265 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7269 g_hash_table_destroy (name_cache2);
7270 mono_image_unlock (image);
7273 /*FIXME Only dynamic assemblies should allow this operation.*/
7275 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7276 const char *name, guint32 index)
7278 GHashTable *nspace_table;
7279 GHashTable *name_cache;
7282 mono_image_lock (image);
7284 if (!image->name_cache)
7285 mono_image_init_name_cache (image);
7287 name_cache = image->name_cache;
7288 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7289 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7290 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7293 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7294 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7296 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7298 mono_image_unlock (image);
7307 find_nocase (gpointer key, gpointer value, gpointer user_data)
7309 char *name = (char*)key;
7310 FindUserData *data = (FindUserData*)user_data;
7312 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7313 data->value = value;
7317 * mono_class_from_name_case:
7318 * @image: The MonoImage where the type is looked up in
7319 * @name_space: the type namespace
7320 * @name: the type short name.
7322 * Obtains a MonoClass with a given namespace and a given name which
7323 * is located in the given MonoImage. The namespace and name
7324 * lookups are case insensitive.
7327 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7329 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7330 guint32 cols [MONO_TYPEDEF_SIZE];
7335 if (image->dynamic) {
7337 FindUserData user_data;
7339 mono_image_lock (image);
7341 if (!image->name_cache)
7342 mono_image_init_name_cache (image);
7344 user_data.key = name_space;
7345 user_data.value = NULL;
7346 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7348 if (user_data.value) {
7349 GHashTable *nspace_table = (GHashTable*)user_data.value;
7351 user_data.key = name;
7352 user_data.value = NULL;
7354 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7356 if (user_data.value)
7357 token = GPOINTER_TO_UINT (user_data.value);
7360 mono_image_unlock (image);
7363 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7369 /* add a cache if needed */
7370 for (i = 1; i <= t->rows; ++i) {
7371 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7372 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7374 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7375 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7377 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7379 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7380 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7381 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7382 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7388 return_nested_in (MonoClass *class, char *nested)
7391 char *s = strchr (nested, '/');
7392 gpointer iter = NULL;
7399 while ((found = mono_class_get_nested_types (class, &iter))) {
7400 if (strcmp (found->name, nested) == 0) {
7402 return return_nested_in (found, s);
7410 search_modules (MonoImage *image, const char *name_space, const char *name)
7412 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7413 MonoImage *file_image;
7418 * The EXPORTEDTYPES table only contains public types, so have to search the
7420 * Note: image->modules contains the contents of the MODULEREF table, while
7421 * the real module list is in the FILE table.
7423 for (i = 0; i < file_table->rows; i++) {
7424 guint32 cols [MONO_FILE_SIZE];
7425 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7426 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7429 file_image = mono_image_load_file_for_image (image, i + 1);
7431 class = mono_class_from_name (file_image, name_space, name);
7441 * mono_class_from_name:
7442 * @image: The MonoImage where the type is looked up in
7443 * @name_space: the type namespace
7444 * @name: the type short name.
7446 * Obtains a MonoClass with a given namespace and a given name which
7447 * is located in the given MonoImage.
7450 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7452 GHashTable *nspace_table;
7453 MonoImage *loaded_image;
7460 if ((nested = strchr (name, '/'))) {
7461 int pos = nested - name;
7462 int len = strlen (name);
7465 memcpy (buf, name, len + 1);
7467 nested = buf + pos + 1;
7471 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7472 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7473 gboolean res = get_class_from_name (image, name_space, name, &class);
7476 class = search_modules (image, name_space, name);
7478 return class ? return_nested_in (class, nested) : NULL;
7484 mono_image_lock (image);
7486 if (!image->name_cache)
7487 mono_image_init_name_cache (image);
7489 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7492 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7494 mono_image_unlock (image);
7496 if (!token && image->dynamic && image->modules) {
7497 /* Search modules as well */
7498 for (i = 0; i < image->module_count; ++i) {
7499 MonoImage *module = image->modules [i];
7501 class = mono_class_from_name (module, name_space, name);
7508 class = search_modules (image, name_space, name);
7516 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7517 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7518 guint32 cols [MONO_EXP_TYPE_SIZE];
7521 idx = mono_metadata_token_index (token);
7523 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7525 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7526 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7527 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7530 class = mono_class_from_name (loaded_image, name_space, name);
7532 return return_nested_in (class, nested);
7534 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7535 guint32 assembly_idx;
7537 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7539 mono_assembly_load_reference (image, assembly_idx - 1);
7540 g_assert (image->references [assembly_idx - 1]);
7541 if (image->references [assembly_idx - 1] == (gpointer)-1)
7544 /* FIXME: Cycle detection */
7545 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7547 g_error ("not yet implemented");
7551 token = MONO_TOKEN_TYPE_DEF | token;
7553 class = mono_class_get (image, token);
7555 return return_nested_in (class, nested);
7559 /*FIXME test for interfaces with variant generic arguments*/
7561 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7562 gboolean check_interfaces)
7564 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7565 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7567 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7570 for (i = 0; i < klass->interface_count; i ++) {
7571 MonoClass *ic = klass->interfaces [i];
7576 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7581 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7584 if (klassc == mono_defaults.object_class)
7591 mono_type_is_generic_argument (MonoType *type)
7593 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7597 mono_class_has_variant_generic_params (MonoClass *klass)
7600 MonoGenericContainer *container;
7602 if (!klass->generic_class)
7605 container = klass->generic_class->container_class->generic_container;
7607 for (i = 0; i < container->type_argc; ++i)
7608 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7615 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7617 if (target == candidate)
7620 if (check_for_reference_conv &&
7621 mono_type_is_generic_argument (&target->byval_arg) &&
7622 mono_type_is_generic_argument (&candidate->byval_arg)) {
7623 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7624 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7626 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7629 if (!mono_class_is_assignable_from (target, candidate))
7635 * @container the generic container from the GTD
7636 * @klass: the class to be assigned to
7637 * @oklass: the source class
7639 * Both klass and oklass must be instances of the same generic interface.
7640 * Return true if @klass can be assigned to a @klass variable
7643 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7646 MonoType **klass_argv, **oklass_argv;
7647 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7648 MonoGenericContainer *container = klass_gtd->generic_container;
7650 if (klass == oklass)
7653 /*Viable candidates are instances of the same generic interface*/
7654 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7657 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7658 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7660 for (j = 0; j < container->type_argc; ++j) {
7661 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7662 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7664 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7668 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7669 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7671 if (param1_class != param2_class) {
7672 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7673 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7675 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7676 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7686 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7688 MonoGenericParam *gparam, *ogparam;
7689 MonoGenericParamInfo *tinfo, *cinfo;
7690 MonoClass **candidate_class;
7691 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7694 if (target == candidate)
7696 if (target->byval_arg.type != candidate->byval_arg.type)
7699 gparam = target->byval_arg.data.generic_param;
7700 ogparam = candidate->byval_arg.data.generic_param;
7701 tinfo = mono_generic_param_info (gparam);
7702 cinfo = mono_generic_param_info (ogparam);
7704 class_constraint_satisfied = FALSE;
7705 valuetype_constraint_satisfied = FALSE;
7707 /*candidate must have a super set of target's special constraints*/
7708 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7709 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7711 if (cinfo->constraints) {
7712 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7713 MonoClass *cc = *candidate_class;
7715 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7716 class_constraint_satisfied = TRUE;
7717 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7718 valuetype_constraint_satisfied = TRUE;
7721 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7722 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7724 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7726 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7728 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7729 valuetype_constraint_satisfied)) {
7734 /*candidate type constraints must be a superset of target's*/
7735 if (tinfo->constraints) {
7736 MonoClass **target_class;
7737 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7738 MonoClass *tc = *target_class;
7741 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7742 * check it's constraints since it satisfy the constraint by itself.
7744 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7747 if (!cinfo->constraints)
7750 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7751 MonoClass *cc = *candidate_class;
7753 if (mono_class_is_assignable_from (tc, cc))
7757 * This happens when we have the following:
7759 * Bar<K> where K : IFace
7760 * Foo<T, U> where T : U where U : IFace
7762 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7765 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7766 if (mono_gparam_is_assignable_from (target, cc))
7770 if (!*candidate_class)
7775 /*candidate itself must have a constraint that satisfy target*/
7776 if (cinfo->constraints) {
7777 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7778 MonoClass *cc = *candidate_class;
7779 if (mono_class_is_assignable_from (target, cc))
7787 * mono_class_is_assignable_from:
7788 * @klass: the class to be assigned to
7789 * @oklass: the source class
7791 * Return: true if an instance of object oklass can be assigned to an
7792 * instance of object @klass
7795 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7797 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7799 mono_class_init (klass);
7801 if (!oklass->inited)
7802 mono_class_init (oklass);
7804 if (klass->exception_type || oklass->exception_type)
7807 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7808 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7810 return mono_gparam_is_assignable_from (klass, oklass);
7813 if (MONO_CLASS_IS_INTERFACE (klass)) {
7814 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7815 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7816 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7820 for (i = 0; constraints [i]; ++i) {
7821 if (mono_class_is_assignable_from (klass, constraints [i]))
7829 /* interface_offsets might not be set for dynamic classes */
7830 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7832 * oklass might be a generic type parameter but they have
7833 * interface_offsets set.
7835 return mono_reflection_call_is_assignable_to (oklass, klass);
7836 if (!oklass->interface_bitmap)
7837 /* Happens with generic instances of not-yet created dynamic types */
7839 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7842 if (mono_class_has_variant_generic_params (klass)) {
7845 mono_class_setup_interfaces (oklass, &error);
7846 if (!mono_error_ok (&error)) {
7847 mono_error_cleanup (&error);
7851 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7852 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7853 MonoClass *iface = oklass->interfaces_packed [i];
7855 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7860 } else if (klass->delegate) {
7861 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7863 }else if (klass->rank) {
7864 MonoClass *eclass, *eoclass;
7866 if (oklass->rank != klass->rank)
7869 /* vectors vs. one dimensional arrays */
7870 if (oklass->byval_arg.type != klass->byval_arg.type)
7873 eclass = klass->cast_class;
7874 eoclass = oklass->cast_class;
7877 * a is b does not imply a[] is b[] when a is a valuetype, and
7878 * b is a reference type.
7881 if (eoclass->valuetype) {
7882 if ((eclass == mono_defaults.enum_class) ||
7883 (eclass == mono_defaults.enum_class->parent) ||
7884 (eclass == mono_defaults.object_class))
7888 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7889 } else if (mono_class_is_nullable (klass)) {
7890 if (mono_class_is_nullable (oklass))
7891 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7893 return mono_class_is_assignable_from (klass->cast_class, oklass);
7894 } else if (klass == mono_defaults.object_class)
7897 return mono_class_has_parent (oklass, klass);
7900 /*Check if @oklass is variant compatible with @klass.*/
7902 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7905 MonoType **klass_argv, **oklass_argv;
7906 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7907 MonoGenericContainer *container = klass_gtd->generic_container;
7909 /*Viable candidates are instances of the same generic interface*/
7910 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7913 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7914 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7916 for (j = 0; j < container->type_argc; ++j) {
7917 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7918 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7920 if (param1_class->valuetype != param2_class->valuetype)
7924 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7925 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7927 if (param1_class != param2_class) {
7928 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7929 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7931 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7932 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7940 /*Check if @candidate implements the interface @target*/
7942 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7946 gboolean is_variant = mono_class_has_variant_generic_params (target);
7948 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7949 if (mono_class_is_variant_compatible_slow (target, candidate))
7954 if (candidate == target)
7957 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7958 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7959 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7961 if (tb && tb->interfaces) {
7962 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7963 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7964 MonoClass *iface_class;
7966 /* we can't realize the type here since it can do pretty much anything. */
7969 iface_class = mono_class_from_mono_type (iface->type);
7970 if (iface_class == target)
7972 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
7974 if (mono_class_implement_interface_slow (target, iface_class))
7979 /*setup_interfaces don't mono_class_init anything*/
7980 mono_class_setup_interfaces (candidate, &error);
7981 if (!mono_error_ok (&error)) {
7982 mono_error_cleanup (&error);
7986 for (i = 0; i < candidate->interface_count; ++i) {
7987 if (candidate->interfaces [i] == target)
7990 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
7993 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
7997 candidate = candidate->parent;
7998 } while (candidate);
8004 * Check if @oklass can be assigned to @klass.
8005 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8008 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8010 if (candidate == target)
8012 if (target == mono_defaults.object_class)
8015 if (mono_class_has_parent (candidate, target))
8018 /*If target is not an interface there is no need to check them.*/
8019 if (MONO_CLASS_IS_INTERFACE (target))
8020 return mono_class_implement_interface_slow (target, candidate);
8022 if (target->delegate && mono_class_has_variant_generic_params (target))
8023 return mono_class_is_variant_compatible (target, candidate, FALSE);
8025 /*FIXME properly handle nullables and arrays */
8026 /*FIXME properly handle (M)VAR */
8031 * mono_class_get_cctor:
8032 * @klass: A MonoClass pointer
8034 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8037 mono_class_get_cctor (MonoClass *klass)
8039 MonoCachedClassInfo cached_info;
8041 if (klass->image->dynamic) {
8043 * has_cctor is not set for these classes because mono_class_init () is
8046 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8049 if (!klass->has_cctor)
8052 if (mono_class_get_cached_class_info (klass, &cached_info))
8053 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8055 if (klass->generic_class && !klass->methods)
8056 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8058 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8062 * mono_class_get_finalizer:
8063 * @klass: The MonoClass pointer
8065 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8068 mono_class_get_finalizer (MonoClass *klass)
8070 MonoCachedClassInfo cached_info;
8073 mono_class_init (klass);
8074 if (!mono_class_has_finalizer (klass))
8077 if (mono_class_get_cached_class_info (klass, &cached_info))
8078 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8080 mono_class_setup_vtable (klass);
8081 return klass->vtable [finalize_slot];
8086 * mono_class_needs_cctor_run:
8087 * @klass: the MonoClass pointer
8088 * @caller: a MonoMethod describing the caller
8090 * Determines whenever the class has a static constructor and whenever it
8091 * needs to be called when executing CALLER.
8094 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8098 method = mono_class_get_cctor (klass);
8100 return (method == caller) ? FALSE : TRUE;
8106 * mono_class_array_element_size:
8109 * Returns: the number of bytes an element of type @klass
8110 * uses when stored into an array.
8113 mono_class_array_element_size (MonoClass *klass)
8115 MonoType *type = &klass->byval_arg;
8118 switch (type->type) {
8121 case MONO_TYPE_BOOLEAN:
8125 case MONO_TYPE_CHAR:
8134 case MONO_TYPE_CLASS:
8135 case MONO_TYPE_STRING:
8136 case MONO_TYPE_OBJECT:
8137 case MONO_TYPE_SZARRAY:
8138 case MONO_TYPE_ARRAY:
8140 case MONO_TYPE_MVAR:
8141 return sizeof (gpointer);
8146 case MONO_TYPE_VALUETYPE:
8147 if (type->data.klass->enumtype) {
8148 type = mono_class_enum_basetype (type->data.klass);
8149 klass = klass->element_class;
8152 return mono_class_instance_size (klass) - sizeof (MonoObject);
8153 case MONO_TYPE_GENERICINST:
8154 type = &type->data.generic_class->container_class->byval_arg;
8157 case MONO_TYPE_VOID:
8161 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8167 * mono_array_element_size:
8168 * @ac: pointer to a #MonoArrayClass
8170 * Returns: the size of single array element.
8173 mono_array_element_size (MonoClass *ac)
8175 g_assert (ac->rank);
8176 return ac->sizes.element_size;
8180 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8181 MonoGenericContext *context)
8183 if (image->dynamic) {
8184 MonoClass *tmp_handle_class;
8185 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8187 g_assert (tmp_handle_class);
8189 *handle_class = tmp_handle_class;
8191 if (tmp_handle_class == mono_defaults.typehandle_class)
8192 return &((MonoClass*)obj)->byval_arg;
8197 switch (token & 0xff000000) {
8198 case MONO_TOKEN_TYPE_DEF:
8199 case MONO_TOKEN_TYPE_REF:
8200 case MONO_TOKEN_TYPE_SPEC: {
8203 *handle_class = mono_defaults.typehandle_class;
8204 type = mono_type_get_full (image, token, context);
8207 mono_class_init (mono_class_from_mono_type (type));
8208 /* We return a MonoType* as handle */
8211 case MONO_TOKEN_FIELD_DEF: {
8213 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8217 *handle_class = mono_defaults.fieldhandle_class;
8218 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8221 mono_class_init (class);
8222 return mono_class_get_field (class, token);
8224 case MONO_TOKEN_METHOD_DEF:
8225 case MONO_TOKEN_METHOD_SPEC: {
8227 meth = mono_get_method_full (image, token, NULL, context);
8229 *handle_class = mono_defaults.methodhandle_class;
8232 case MONO_TOKEN_MEMBER_REF: {
8233 guint32 cols [MONO_MEMBERREF_SIZE];
8235 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8236 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8237 mono_metadata_decode_blob_size (sig, &sig);
8238 if (*sig == 0x6) { /* it's a field */
8240 MonoClassField *field;
8241 field = mono_field_from_token (image, token, &klass, context);
8243 *handle_class = mono_defaults.fieldhandle_class;
8247 meth = mono_get_method_full (image, token, NULL, context);
8249 *handle_class = mono_defaults.methodhandle_class;
8254 g_warning ("Unknown token 0x%08x in ldtoken", token);
8261 * This function might need to call runtime functions so it can't be part
8262 * of the metadata library.
8264 static MonoLookupDynamicToken lookup_dynamic = NULL;
8267 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8269 lookup_dynamic = func;
8273 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8275 MonoClass *handle_class;
8277 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8281 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8283 return lookup_dynamic (image, token, valid_token, handle_class, context);
8286 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8289 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8291 get_cached_class_info = func;
8295 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8297 if (!get_cached_class_info)
8300 return get_cached_class_info (klass, res);
8304 mono_install_get_class_from_name (MonoGetClassFromName func)
8306 get_class_from_name = func;
8310 mono_class_get_image (MonoClass *klass)
8312 return klass->image;
8316 * mono_class_get_element_class:
8317 * @klass: the MonoClass to act on
8319 * Returns: the element class of an array or an enumeration.
8322 mono_class_get_element_class (MonoClass *klass)
8324 return klass->element_class;
8328 * mono_class_is_valuetype:
8329 * @klass: the MonoClass to act on
8331 * Returns: true if the MonoClass represents a ValueType.
8334 mono_class_is_valuetype (MonoClass *klass)
8336 return klass->valuetype;
8340 * mono_class_is_enum:
8341 * @klass: the MonoClass to act on
8343 * Returns: true if the MonoClass represents an enumeration.
8346 mono_class_is_enum (MonoClass *klass)
8348 return klass->enumtype;
8352 * mono_class_enum_basetype:
8353 * @klass: the MonoClass to act on
8355 * Returns: the underlying type representation for an enumeration.
8358 mono_class_enum_basetype (MonoClass *klass)
8360 if (klass->element_class == klass)
8361 /* SRE or broken types */
8364 return &klass->element_class->byval_arg;
8368 * mono_class_get_parent
8369 * @klass: the MonoClass to act on
8371 * Returns: the parent class for this class.
8374 mono_class_get_parent (MonoClass *klass)
8376 return klass->parent;
8380 * mono_class_get_nesting_type;
8381 * @klass: the MonoClass to act on
8383 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8386 mono_class_get_nesting_type (MonoClass *klass)
8388 return klass->nested_in;
8392 * mono_class_get_rank:
8393 * @klass: the MonoClass to act on
8395 * Returns: the rank for the array (the number of dimensions).
8398 mono_class_get_rank (MonoClass *klass)
8404 * mono_class_get_flags:
8405 * @klass: the MonoClass to act on
8407 * The type flags from the TypeDef table from the metadata.
8408 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8411 * Returns: the flags from the TypeDef table.
8414 mono_class_get_flags (MonoClass *klass)
8416 return klass->flags;
8420 * mono_class_get_name
8421 * @klass: the MonoClass to act on
8423 * Returns: the name of the class.
8426 mono_class_get_name (MonoClass *klass)
8432 * mono_class_get_namespace:
8433 * @klass: the MonoClass to act on
8435 * Returns: the namespace of the class.
8438 mono_class_get_namespace (MonoClass *klass)
8440 return klass->name_space;
8444 * mono_class_get_type:
8445 * @klass: the MonoClass to act on
8447 * This method returns the internal Type representation for the class.
8449 * Returns: the MonoType from the class.
8452 mono_class_get_type (MonoClass *klass)
8454 return &klass->byval_arg;
8458 * mono_class_get_type_token
8459 * @klass: the MonoClass to act on
8461 * This method returns type token for the class.
8463 * Returns: the type token for the class.
8466 mono_class_get_type_token (MonoClass *klass)
8468 return klass->type_token;
8472 * mono_class_get_byref_type:
8473 * @klass: the MonoClass to act on
8478 mono_class_get_byref_type (MonoClass *klass)
8480 return &klass->this_arg;
8484 * mono_class_num_fields:
8485 * @klass: the MonoClass to act on
8487 * Returns: the number of static and instance fields in the class.
8490 mono_class_num_fields (MonoClass *klass)
8492 return klass->field.count;
8496 * mono_class_num_methods:
8497 * @klass: the MonoClass to act on
8499 * Returns: the number of methods in the class.
8502 mono_class_num_methods (MonoClass *klass)
8504 return klass->method.count;
8508 * mono_class_num_properties
8509 * @klass: the MonoClass to act on
8511 * Returns: the number of properties in the class.
8514 mono_class_num_properties (MonoClass *klass)
8516 mono_class_setup_properties (klass);
8518 return klass->ext->property.count;
8522 * mono_class_num_events:
8523 * @klass: the MonoClass to act on
8525 * Returns: the number of events in the class.
8528 mono_class_num_events (MonoClass *klass)
8530 mono_class_setup_events (klass);
8532 return klass->ext->event.count;
8536 * mono_class_get_fields:
8537 * @klass: the MonoClass to act on
8539 * This routine is an iterator routine for retrieving the fields in a class.
8541 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8542 * iterate over all of the elements. When no more values are
8543 * available, the return value is NULL.
8545 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8548 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8550 MonoClassField* field;
8554 mono_class_setup_fields_locking (klass);
8555 if (klass->exception_type)
8557 /* start from the first */
8558 if (klass->field.count) {
8559 return *iter = &klass->fields [0];
8567 if (field < &klass->fields [klass->field.count]) {
8568 return *iter = field;
8574 * mono_class_get_methods
8575 * @klass: the MonoClass to act on
8577 * This routine is an iterator routine for retrieving the fields in a class.
8579 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8580 * iterate over all of the elements. When no more values are
8581 * available, the return value is NULL.
8583 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8586 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8588 MonoMethod** method;
8592 mono_class_setup_methods (klass);
8595 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8596 * FIXME we should better report this error to the caller
8598 if (!klass->methods)
8600 /* start from the first */
8601 if (klass->method.count) {
8602 *iter = &klass->methods [0];
8603 return klass->methods [0];
8611 if (method < &klass->methods [klass->method.count]) {
8619 * mono_class_get_virtual_methods:
8621 * Iterate over the virtual methods of KLASS.
8623 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8626 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8628 MonoMethod** method;
8631 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
8633 mono_class_setup_methods (klass);
8635 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8636 * FIXME we should better report this error to the caller
8638 if (!klass->methods)
8640 /* start from the first */
8641 method = &klass->methods [0];
8646 while (method < &klass->methods [klass->method.count]) {
8647 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8651 if (method < &klass->methods [klass->method.count]) {
8658 /* Search directly in metadata to avoid calling setup_methods () */
8659 MonoMethod *res = NULL;
8665 start_index = GPOINTER_TO_UINT (*iter);
8668 for (i = start_index; i < klass->method.count; ++i) {
8671 /* class->method.first points into the methodptr table */
8672 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8674 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8678 if (i < klass->method.count) {
8679 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8680 /* Add 1 here so the if (*iter) check fails */
8681 *iter = GUINT_TO_POINTER (i + 1);
8690 * mono_class_get_properties:
8691 * @klass: the MonoClass to act on
8693 * This routine is an iterator routine for retrieving the properties in a class.
8695 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8696 * iterate over all of the elements. When no more values are
8697 * available, the return value is NULL.
8699 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8702 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8704 MonoProperty* property;
8708 mono_class_setup_properties (klass);
8709 /* start from the first */
8710 if (klass->ext->property.count) {
8711 return *iter = &klass->ext->properties [0];
8719 if (property < &klass->ext->properties [klass->ext->property.count]) {
8720 return *iter = property;
8726 * mono_class_get_events:
8727 * @klass: the MonoClass to act on
8729 * This routine is an iterator routine for retrieving the properties in a class.
8731 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8732 * iterate over all of the elements. When no more values are
8733 * available, the return value is NULL.
8735 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8738 mono_class_get_events (MonoClass* klass, gpointer *iter)
8744 mono_class_setup_events (klass);
8745 /* start from the first */
8746 if (klass->ext->event.count) {
8747 return *iter = &klass->ext->events [0];
8755 if (event < &klass->ext->events [klass->ext->event.count]) {
8756 return *iter = event;
8762 * mono_class_get_interfaces
8763 * @klass: the MonoClass to act on
8765 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8767 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8768 * iterate over all of the elements. When no more values are
8769 * available, the return value is NULL.
8771 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8774 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8782 mono_class_init (klass);
8783 if (!klass->interfaces_inited) {
8784 mono_class_setup_interfaces (klass, &error);
8785 if (!mono_error_ok (&error)) {
8786 mono_error_cleanup (&error);
8790 /* start from the first */
8791 if (klass->interface_count) {
8792 *iter = &klass->interfaces [0];
8793 return klass->interfaces [0];
8801 if (iface < &klass->interfaces [klass->interface_count]) {
8809 * mono_class_get_nested_types
8810 * @klass: the MonoClass to act on
8812 * This routine is an iterator routine for retrieving the nested types of a class.
8813 * This works only if @klass is non-generic, or a generic type definition.
8815 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8816 * iterate over all of the elements. When no more values are
8817 * available, the return value is NULL.
8819 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8822 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8830 if (!klass->nested_classes_inited) {
8831 if (!klass->type_token)
8832 klass->nested_classes_inited = TRUE;
8833 mono_loader_lock ();
8834 if (!klass->nested_classes_inited) {
8835 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8838 guint32 cols [MONO_NESTED_CLASS_SIZE];
8839 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8840 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8841 if (!mono_error_ok (&error)) {
8842 /*FIXME don't swallow the error message*/
8843 mono_error_cleanup (&error);
8845 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8848 mono_class_alloc_ext (klass);
8849 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8851 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8854 mono_memory_barrier ();
8855 klass->nested_classes_inited = TRUE;
8856 mono_loader_unlock ();
8860 /* start from the first */
8861 if (klass->ext && klass->ext->nested_classes) {
8862 *iter = klass->ext->nested_classes;
8863 return klass->ext->nested_classes->data;
8865 /* no nested types */
8879 * mono_field_get_name:
8880 * @field: the MonoClassField to act on
8882 * Returns: the name of the field.
8885 mono_field_get_name (MonoClassField *field)
8891 * mono_field_get_type:
8892 * @field: the MonoClassField to act on
8894 * Returns: MonoType of the field.
8897 mono_field_get_type (MonoClassField *field)
8900 MonoType *type = mono_field_get_type_checked (field, &error);
8901 if (!mono_error_ok (&error)) {
8902 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8903 mono_error_cleanup (&error);
8910 * mono_field_get_type_checked:
8911 * @field: the MonoClassField to act on
8912 * @error: used to return any erro found while retrieving @field type
8914 * Returns: MonoType of the field.
8917 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
8919 mono_error_init (error);
8921 mono_field_resolve_type (field, error);
8926 * mono_field_get_parent:
8927 * @field: the MonoClassField to act on
8929 * Returns: MonoClass where the field was defined.
8932 mono_field_get_parent (MonoClassField *field)
8934 return field->parent;
8938 * mono_field_get_flags;
8939 * @field: the MonoClassField to act on
8941 * The metadata flags for a field are encoded using the
8942 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
8944 * Returns: the flags for the field.
8947 mono_field_get_flags (MonoClassField *field)
8950 return mono_field_resolve_flags (field);
8951 return field->type->attrs;
8955 * mono_field_get_offset;
8956 * @field: the MonoClassField to act on
8958 * Returns: the field offset.
8961 mono_field_get_offset (MonoClassField *field)
8963 return field->offset;
8967 mono_field_get_rva (MonoClassField *field)
8971 MonoClass *klass = field->parent;
8973 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
8975 if (!klass->ext || !klass->ext->field_def_values) {
8976 mono_loader_lock ();
8977 mono_class_alloc_ext (klass);
8978 if (!klass->ext->field_def_values)
8979 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
8980 mono_loader_unlock ();
8983 field_index = mono_field_get_index (field);
8985 if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
8986 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
8988 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
8989 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
8992 return klass->ext->field_def_values [field_index].data;
8996 * mono_field_get_data;
8997 * @field: the MonoClassField to act on
8999 * Returns: pointer to the metadata constant value or to the field
9000 * data if it has an RVA flag.
9003 mono_field_get_data (MonoClassField *field)
9005 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9006 MonoTypeEnum def_type;
9008 return mono_class_get_field_default_value (field, &def_type);
9009 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9010 return mono_field_get_rva (field);
9017 * mono_property_get_name:
9018 * @prop: the MonoProperty to act on
9020 * Returns: the name of the property
9023 mono_property_get_name (MonoProperty *prop)
9029 * mono_property_get_set_method
9030 * @prop: the MonoProperty to act on.
9032 * Returns: the setter method of the property (A MonoMethod)
9035 mono_property_get_set_method (MonoProperty *prop)
9041 * mono_property_get_get_method
9042 * @prop: the MonoProperty to act on.
9044 * Returns: the setter method of the property (A MonoMethod)
9047 mono_property_get_get_method (MonoProperty *prop)
9053 * mono_property_get_parent:
9054 * @prop: the MonoProperty to act on.
9056 * Returns: the MonoClass where the property was defined.
9059 mono_property_get_parent (MonoProperty *prop)
9061 return prop->parent;
9065 * mono_property_get_flags:
9066 * @prop: the MonoProperty to act on.
9068 * The metadata flags for a property are encoded using the
9069 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9071 * Returns: the flags for the property.
9074 mono_property_get_flags (MonoProperty *prop)
9080 * mono_event_get_name:
9081 * @event: the MonoEvent to act on
9083 * Returns: the name of the event.
9086 mono_event_get_name (MonoEvent *event)
9092 * mono_event_get_add_method:
9093 * @event: The MonoEvent to act on.
9095 * Returns: the @add' method for the event (a MonoMethod).
9098 mono_event_get_add_method (MonoEvent *event)
9104 * mono_event_get_remove_method:
9105 * @event: The MonoEvent to act on.
9107 * Returns: the @remove method for the event (a MonoMethod).
9110 mono_event_get_remove_method (MonoEvent *event)
9112 return event->remove;
9116 * mono_event_get_raise_method:
9117 * @event: The MonoEvent to act on.
9119 * Returns: the @raise method for the event (a MonoMethod).
9122 mono_event_get_raise_method (MonoEvent *event)
9124 return event->raise;
9128 * mono_event_get_parent:
9129 * @event: the MonoEvent to act on.
9131 * Returns: the MonoClass where the event is defined.
9134 mono_event_get_parent (MonoEvent *event)
9136 return event->parent;
9140 * mono_event_get_flags
9141 * @event: the MonoEvent to act on.
9143 * The metadata flags for an event are encoded using the
9144 * EVENT_* constants. See the tabledefs.h file for details.
9146 * Returns: the flags for the event.
9149 mono_event_get_flags (MonoEvent *event)
9151 return event->attrs;
9155 * mono_class_get_method_from_name:
9156 * @klass: where to look for the method
9157 * @name_space: name of the method
9158 * @param_count: number of parameters. -1 for any number.
9160 * Obtains a MonoMethod with a given name and number of parameters.
9161 * It only works if there are no multiple signatures for any given method name.
9164 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9166 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9170 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9172 MonoMethod *res = NULL;
9175 /* Search directly in the metadata to avoid calling setup_methods () */
9176 for (i = 0; i < klass->method.count; ++i) {
9177 guint32 cols [MONO_METHOD_SIZE];
9179 MonoMethodSignature *sig;
9181 /* class->method.first points into the methodptr table */
9182 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9184 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9185 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9186 if (param_count == -1) {
9190 sig = mono_method_signature (method);
9191 if (sig && sig->param_count == param_count) {
9202 * mono_class_get_method_from_name_flags:
9203 * @klass: where to look for the method
9204 * @name_space: name of the method
9205 * @param_count: number of parameters. -1 for any number.
9206 * @flags: flags which must be set in the method
9208 * Obtains a MonoMethod with a given name and number of parameters.
9209 * It only works if there are no multiple signatures for any given method name.
9212 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9214 MonoMethod *res = NULL;
9217 mono_class_init (klass);
9219 if (klass->generic_class && !klass->methods) {
9220 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9222 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9226 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9227 mono_class_setup_methods (klass);
9229 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9230 See mono/tests/array_load_exception.il
9231 FIXME we should better report this error to the caller
9233 if (!klass->methods)
9235 for (i = 0; i < klass->method.count; ++i) {
9236 MonoMethod *method = klass->methods [i];
9238 if (method->name[0] == name [0] &&
9239 !strcmp (name, method->name) &&
9240 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9241 ((method->flags & flags) == flags)) {
9248 res = find_method_in_metadata (klass, name, param_count, flags);
9255 * mono_class_set_failure:
9256 * @klass: class in which the failure was detected
9257 * @ex_type: the kind of exception/error to be thrown (later)
9258 * @ex_data: exception data (specific to each type of exception/error)
9260 * Keep a detected failure informations in the class for later processing.
9261 * Note that only the first failure is kept.
9263 * LOCKING: Acquires the loader lock.
9266 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9268 if (klass->exception_type)
9271 mono_loader_lock ();
9272 klass->exception_type = ex_type;
9274 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9275 mono_loader_unlock ();
9281 * mono_class_get_exception_data:
9283 * Return the exception_data property of KLASS.
9285 * LOCKING: Acquires the loader lock.
9288 mono_class_get_exception_data (MonoClass *klass)
9290 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9294 * mono_classes_init:
9296 * Initialize the resources used by this module.
9299 mono_classes_init (void)
9301 mono_counters_register ("Inflated methods size",
9302 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9303 mono_counters_register ("Inflated classes",
9304 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9305 mono_counters_register ("Inflated classes size",
9306 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9307 mono_counters_register ("MonoClass size",
9308 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9309 mono_counters_register ("MonoClassExt size",
9310 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9314 * mono_classes_cleanup:
9316 * Free the resources used by this module.
9319 mono_classes_cleanup (void)
9321 if (global_interface_bitset)
9322 mono_bitset_free (global_interface_bitset);
9323 global_interface_bitset = NULL;
9327 * mono_class_get_exception_for_failure:
9328 * @klass: class in which the failure was detected
9330 * Return a constructed MonoException than the caller can then throw
9331 * using mono_raise_exception - or NULL if no failure is present (or
9332 * doesn't result in an exception).
9335 mono_class_get_exception_for_failure (MonoClass *klass)
9337 gpointer exception_data = mono_class_get_exception_data (klass);
9339 switch (klass->exception_type) {
9340 #ifndef DISABLE_SECURITY
9341 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9342 MonoDomain *domain = mono_domain_get ();
9343 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9344 MonoMethod *method = exception_data;
9345 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9346 MonoObject *exc = NULL;
9350 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9351 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9352 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9354 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9355 return (MonoException*) exc;
9358 case MONO_EXCEPTION_TYPE_LOAD: {
9361 char *str = mono_type_get_full_name (klass);
9362 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9363 name = mono_string_new (mono_domain_get (), str);
9365 ex = mono_get_exception_type_load (name, astr);
9369 case MONO_EXCEPTION_MISSING_METHOD: {
9370 char *class_name = exception_data;
9371 char *assembly_name = class_name + strlen (class_name) + 1;
9373 return mono_get_exception_missing_method (class_name, assembly_name);
9375 case MONO_EXCEPTION_MISSING_FIELD: {
9376 char *class_name = exception_data;
9377 char *member_name = class_name + strlen (class_name) + 1;
9379 return mono_get_exception_missing_field (class_name, member_name);
9381 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9382 char *msg_format = exception_data;
9383 char *assembly_name = msg_format + strlen (msg_format) + 1;
9384 char *msg = g_strdup_printf (msg_format, assembly_name);
9387 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9393 case MONO_EXCEPTION_BAD_IMAGE: {
9394 return mono_get_exception_bad_image_format (exception_data);
9397 MonoLoaderError *error;
9400 error = mono_loader_get_last_error ();
9402 ex = mono_loader_error_prepare_exception (error);
9406 /* TODO - handle other class related failures */
9413 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9415 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9416 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9418 if (outer_klass == inner_klass)
9420 inner_klass = inner_klass->nested_in;
9421 } while (inner_klass);
9426 mono_class_get_generic_type_definition (MonoClass *klass)
9428 return klass->generic_class ? klass->generic_class->container_class : klass;
9432 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9434 * Generic instantiations are ignored for all super types of @klass.
9436 * Visibility checks ignoring generic instantiations.
9439 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9442 klass = mono_class_get_generic_type_definition (klass);
9443 parent = mono_class_get_generic_type_definition (parent);
9444 mono_class_setup_supertypes (klass);
9446 for (i = 0; i < klass->idepth; ++i) {
9447 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9453 * Subtype can only access parent members with family protection if the site object
9454 * is subclass of Subtype. For example:
9455 * class A { protected int x; }
9457 * void valid_access () {
9461 * void invalid_access () {
9468 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9470 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9473 if (context_klass == NULL)
9475 /*if access_klass is not member_klass context_klass must be type compat*/
9476 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9482 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9485 if (accessing == accessed)
9487 if (!accessed || !accessing)
9490 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9491 * anywhere so untrusted friends are not safe to access platform's code internals */
9492 if (mono_security_core_clr_enabled ()) {
9493 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9497 mono_assembly_load_friends (accessed);
9498 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9499 MonoAssemblyName *friend = tmp->data;
9500 /* Be conservative with checks */
9503 if (strcmp (accessing->aname.name, friend->name))
9505 if (friend->public_key_token [0]) {
9506 if (!accessing->aname.public_key_token [0])
9508 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9517 * If klass is a generic type or if it is derived from a generic type, return the
9518 * MonoClass of the generic definition
9519 * Returns NULL if not found
9522 get_generic_definition_class (MonoClass *klass)
9525 if (klass->generic_class && klass->generic_class->container_class)
9526 return klass->generic_class->container_class;
9527 klass = klass->parent;
9533 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9536 for (i = 0; i < ginst->type_argc; ++i) {
9537 MonoType *type = ginst->type_argv[i];
9538 switch (type->type) {
9539 case MONO_TYPE_SZARRAY:
9540 if (!can_access_type (access_klass, type->data.klass))
9543 case MONO_TYPE_ARRAY:
9544 if (!can_access_type (access_klass, type->data.array->eklass))
9548 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9551 case MONO_TYPE_CLASS:
9552 case MONO_TYPE_VALUETYPE:
9553 case MONO_TYPE_GENERICINST:
9554 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9562 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9566 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9569 if (access_klass->element_class && !access_klass->enumtype)
9570 access_klass = access_klass->element_class;
9572 if (member_klass->element_class && !member_klass->enumtype)
9573 member_klass = member_klass->element_class;
9575 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9577 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9580 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9583 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9586 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9589 /*Non nested type with nested visibility. We just fail it.*/
9590 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9593 switch (access_level) {
9594 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9595 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9597 case TYPE_ATTRIBUTE_PUBLIC:
9600 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9603 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9604 return is_nesting_type (member_klass, access_klass);
9606 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9607 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9609 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9610 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9612 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9613 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9614 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9616 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9617 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9618 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9623 /* FIXME: check visibility of type, too */
9625 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9627 MonoClass *member_generic_def;
9628 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9631 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9632 access_klass->generic_container) &&
9633 (member_generic_def = get_generic_definition_class (member_klass))) {
9634 MonoClass *access_container;
9636 if (access_klass->generic_container)
9637 access_container = access_klass;
9639 access_container = access_klass->generic_class->container_class;
9641 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9645 /* Partition I 8.5.3.2 */
9646 /* the access level values are the same for fields and methods */
9647 switch (access_level) {
9648 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9649 /* same compilation unit */
9650 return access_klass->image == member_klass->image;
9651 case FIELD_ATTRIBUTE_PRIVATE:
9652 return access_klass == member_klass;
9653 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9654 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9655 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9658 case FIELD_ATTRIBUTE_ASSEMBLY:
9659 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9660 case FIELD_ATTRIBUTE_FAMILY:
9661 if (is_valid_family_access (access_klass, member_klass, context_klass))
9664 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9665 if (is_valid_family_access (access_klass, member_klass, context_klass))
9667 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9668 case FIELD_ATTRIBUTE_PUBLIC:
9675 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9677 /* FIXME: check all overlapping fields */
9678 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9680 MonoClass *nested = method->klass->nested_in;
9682 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9685 nested = nested->nested_in;
9692 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9694 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9696 MonoClass *nested = method->klass->nested_in;
9698 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9701 nested = nested->nested_in;
9706 * with generics calls to explicit interface implementations can be expressed
9707 * directly: the method is private, but we must allow it. This may be opening
9708 * a hole or the generics code should handle this differently.
9709 * Maybe just ensure the interface type is public.
9711 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9717 * mono_method_can_access_method_full:
9718 * @method: The caller method
9719 * @called: The called method
9720 * @context_klass: The static type on stack of the owner @called object used
9722 * This function must be used with instance calls, as they have more strict family accessibility.
9723 * It can be used with static methods, but context_klass should be NULL.
9725 * Returns: TRUE if caller have proper visibility and acessibility to @called
9728 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9730 MonoClass *access_class = method->klass;
9731 MonoClass *member_class = called->klass;
9732 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9734 MonoClass *nested = access_class->nested_in;
9736 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9739 nested = nested->nested_in;
9746 can = can_access_type (access_class, member_class);
9748 MonoClass *nested = access_class->nested_in;
9750 can = can_access_type (nested, member_class);
9753 nested = nested->nested_in;
9760 if (called->is_inflated) {
9761 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9762 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9771 * mono_method_can_access_field_full:
9772 * @method: The caller method
9773 * @field: The accessed field
9774 * @context_klass: The static type on stack of the owner @field object used
9776 * This function must be used with instance fields, as they have more strict family accessibility.
9777 * It can be used with static fields, but context_klass should be NULL.
9779 * Returns: TRUE if caller have proper visibility and acessibility to @field
9782 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9784 MonoClass *access_class = method->klass;
9785 MonoClass *member_class = field->parent;
9786 /* FIXME: check all overlapping fields */
9787 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9789 MonoClass *nested = access_class->nested_in;
9791 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9794 nested = nested->nested_in;
9801 can = can_access_type (access_class, member_class);
9803 MonoClass *nested = access_class->nested_in;
9805 can = can_access_type (nested, member_class);
9808 nested = nested->nested_in;
9818 * mono_class_can_access_class:
9819 * @source_class: The source class
9820 * @target_class: The accessed class
9822 * This function returns is @target_class is visible to @source_class
9824 * Returns: TRUE if source have proper visibility and acessibility to target
9827 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9829 return can_access_type (source_class, target_class);
9833 * mono_type_is_valid_enum_basetype:
9834 * @type: The MonoType to check
9836 * Returns: TRUE if the type can be used as the basetype of an enum
9838 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9839 switch (type->type) {
9842 case MONO_TYPE_BOOLEAN:
9845 case MONO_TYPE_CHAR:
9858 * mono_class_is_valid_enum:
9859 * @klass: An enum class to be validated
9861 * This method verify the required properties an enum should have.
9863 * Returns: TRUE if the informed enum class is valid
9865 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9866 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9867 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9869 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9870 MonoClassField * field;
9871 gpointer iter = NULL;
9872 gboolean found_base_field = FALSE;
9874 g_assert (klass->enumtype);
9875 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9876 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9880 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9883 while ((field = mono_class_get_fields (klass, &iter))) {
9884 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9885 if (found_base_field)
9887 found_base_field = TRUE;
9888 if (!mono_type_is_valid_enum_basetype (field->type))
9893 if (!found_base_field)
9896 if (klass->method.count > 0)
9903 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9905 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
9909 * mono_class_setup_interface_id:
9911 * Initializes MonoClass::interface_id if required.
9913 * LOCKING: Acquires the loader lock.
9916 mono_class_setup_interface_id (MonoClass *class)
9918 mono_loader_lock ();
9919 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
9920 class->interface_id = mono_get_unique_iid (class);
9921 mono_loader_unlock ();
9925 * mono_class_alloc_ext:
9927 * Allocate klass->ext if not already done.
9928 * LOCKING: Assumes the loader lock is held.
9931 mono_class_alloc_ext (MonoClass *klass)
9934 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
9935 class_ext_size += sizeof (MonoClassExt);
9940 * mono_class_setup_interfaces:
9942 * Initialize class->interfaces/interfaces_count.
9943 * LOCKING: Acquires the loader lock.
9944 * This function can fail the type.
9947 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
9951 mono_error_init (error);
9953 if (klass->interfaces_inited)
9956 mono_loader_lock ();
9958 if (klass->interfaces_inited) {
9959 mono_loader_unlock ();
9963 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
9966 /* generic IList, ICollection, IEnumerable */
9967 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
9968 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
9970 args [0] = &klass->element_class->byval_arg;
9971 klass->interfaces [0] = mono_class_bind_generic_parameters (
9972 mono_defaults.generic_ilist_class, 1, args, FALSE);
9973 if (klass->interface_count > 1)
9974 klass->interfaces [1] = mono_class_bind_generic_parameters (
9975 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
9976 } else if (klass->generic_class) {
9977 MonoClass *gklass = klass->generic_class->container_class;
9979 klass->interface_count = gklass->interface_count;
9980 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
9981 for (i = 0; i < klass->interface_count; i++) {
9982 klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
9983 if (!mono_error_ok (error)) {
9984 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
9985 klass->interfaces = NULL;
9991 mono_memory_barrier ();
9993 klass->interfaces_inited = TRUE;
9995 mono_loader_unlock ();
9999 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10001 MonoClass *class = field->parent;
10002 MonoImage *image = class->image;
10003 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10004 int field_idx = field - class->fields;
10006 mono_error_init (error);
10009 MonoClassField *gfield = >d->fields [field_idx];
10010 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10011 if (!mono_error_ok (error)) {
10012 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10013 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10017 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10018 if (!mono_error_ok (error)) {
10019 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10020 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10025 guint32 cols [MONO_FIELD_SIZE];
10026 MonoGenericContainer *container = NULL;
10027 int idx = class->field.first + field_idx;
10029 /*FIXME, in theory we do not lazy load SRE fields*/
10030 g_assert (!image->dynamic);
10032 if (class->generic_container) {
10033 container = class->generic_container;
10035 container = gtd->generic_container;
10036 g_assert (container);
10039 /* class->field.first and idx points into the fieldptr table */
10040 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10042 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10043 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10044 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10048 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10050 mono_metadata_decode_value (sig, &sig);
10051 /* FIELD signature == 0x06 */
10052 g_assert (*sig == 0x06);
10053 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10055 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10060 mono_field_resolve_flags (MonoClassField *field)
10062 MonoClass *class = field->parent;
10063 MonoImage *image = class->image;
10064 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10065 int field_idx = field - class->fields;
10069 MonoClassField *gfield = >d->fields [field_idx];
10070 return mono_field_get_flags (gfield);
10072 int idx = class->field.first + field_idx;
10074 /*FIXME, in theory we do not lazy load SRE fields*/
10075 g_assert (!image->dynamic);
10077 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10082 * mono_class_setup_basic_field_info:
10083 * @class: The class to initialize
10085 * Initializes the class->fields array of fields.
10086 * Aquires the loader lock.
10089 mono_class_setup_basic_field_info_locking (MonoClass *class)
10091 mono_loader_lock ();
10092 mono_class_setup_basic_field_info (class);
10093 mono_loader_unlock ();
10097 * mono_class_get_fields_lazy:
10098 * @klass: the MonoClass to act on
10100 * This routine is an iterator routine for retrieving the fields in a class.
10101 * Only minimal information about fields are loaded. Accessors must be used
10102 * for all MonoClassField returned.
10104 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10105 * iterate over all of the elements. When no more values are
10106 * available, the return value is NULL.
10108 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10111 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10113 MonoClassField* field;
10117 mono_class_setup_basic_field_info_locking (klass);
10118 if (!klass->fields)
10120 /* start from the first */
10121 if (klass->field.count) {
10122 return *iter = &klass->fields [0];
10130 if (field < &klass->fields [klass->field.count]) {
10131 return *iter = field;
10137 mono_class_full_name (MonoClass *klass)
10139 return mono_type_full_name (&klass->byval_arg);