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;
1429 if (class->setup_fields_called)
1432 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1434 * This happens when a generic instance of an unfinished generic typebuilder
1435 * is used as an element type for creating an array type. We can't initialize
1436 * the fields of this class using the fields of gklass, since gklass is not
1437 * finished yet, fields could be added to it later.
1442 mono_class_setup_basic_field_info (class);
1443 top = class->field.count;
1446 mono_class_setup_fields (gtd);
1447 if (gtd->exception_type) {
1448 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1453 class->instance_size = 0;
1455 class->sizes.class_size = 0;
1457 if (class->parent) {
1458 /* For generic instances, class->parent might not have been initialized */
1459 mono_class_init (class->parent);
1460 if (!class->parent->size_inited) {
1461 mono_class_setup_fields (class->parent);
1462 if (class->parent->exception_type) {
1463 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1467 class->instance_size += class->parent->instance_size;
1468 class->min_align = class->parent->min_align;
1469 /* we use |= since it may have been set already */
1470 class->has_references |= class->parent->has_references;
1471 blittable = class->parent->blittable;
1473 class->instance_size = sizeof (MonoObject);
1474 class->min_align = 1;
1477 /* We can't really enable 16 bytes alignment until the GC supports it.
1478 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1479 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1480 Bug #506144 is an example of this issue.
1482 if (class->simd_type)
1483 class->min_align = 16;
1485 /* Get the real size */
1486 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1488 if (explicit_size) {
1489 if ((packing_size & 0xfffffff0) != 0) {
1490 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1491 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1494 class->packing_size = packing_size;
1495 real_size += class->instance_size;
1499 if (explicit_size && real_size) {
1500 class->instance_size = MAX (real_size, class->instance_size);
1502 class->blittable = blittable;
1503 mono_memory_barrier ();
1504 class->size_inited = 1;
1505 class->fields_inited = 1;
1509 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1512 /* Prevent infinite loops if the class references itself */
1513 class->setup_fields_called = 1;
1515 if (class->generic_container) {
1516 container = class->generic_container;
1518 container = gtd->generic_container;
1519 g_assert (container);
1523 * Fetch all the field information.
1525 for (i = 0; i < top; i++){
1526 int idx = class->field.first + i;
1527 field = &class->fields [i];
1529 field->parent = class;
1532 mono_field_resolve_type (field, &error);
1533 if (!mono_error_ok (&error)) {
1534 /*mono_field_resolve_type already failed class*/
1535 mono_error_cleanup (&error);
1539 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1540 g_assert (field->type);
1543 if (mono_field_is_deleted (field))
1546 MonoClassField *gfield = >d->fields [i];
1547 field->offset = gfield->offset;
1549 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1551 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1552 field->offset = offset;
1554 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1555 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1558 if (field->offset < -1) { /*-1 is used to encode special static fields */
1559 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1565 /* Only do these checks if we still think this type is blittable */
1566 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1567 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1570 MonoClass *field_class = mono_class_from_mono_type (field->type);
1572 mono_class_setup_fields (field_class);
1573 if (field_class->exception_type) {
1574 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1578 if (!field_class || !field_class->blittable)
1583 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1584 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1585 blittable = class->element_class->blittable;
1588 if (mono_type_has_exceptions (field->type)) {
1589 char *class_name = mono_type_get_full_name (class);
1590 char *type_name = mono_type_full_name (field->type);
1592 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1593 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1594 g_free (class_name);
1598 /* The def_value of fields is compute lazily during vtable creation */
1601 if (class == mono_defaults.string_class)
1604 class->blittable = blittable;
1606 if (class->enumtype && !mono_class_enum_basetype (class)) {
1607 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1610 if (explicit_size && real_size) {
1611 class->instance_size = MAX (real_size, class->instance_size);
1614 if (class->exception_type)
1616 mono_class_layout_fields (class);
1618 /*valuetypes can't be neither bigger than 1Mb or empty. */
1619 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1620 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1622 mono_memory_barrier ();
1623 class->fields_inited = 1;
1627 * mono_class_setup_fields_locking:
1628 * @class: The class to initialize
1630 * Initializes the class->fields array of fields.
1631 * Aquires the loader lock.
1634 mono_class_setup_fields_locking (MonoClass *class)
1636 /* This can be checked without locks */
1637 if (class->fields_inited)
1639 mono_loader_lock ();
1640 mono_class_setup_fields (class);
1641 mono_loader_unlock ();
1645 * mono_class_has_references:
1647 * Returns whenever @klass->has_references is set, initializing it if needed.
1648 * Aquires the loader lock.
1651 mono_class_has_references (MonoClass *klass)
1653 if (klass->init_pending) {
1654 /* Be conservative */
1657 mono_class_init (klass);
1659 return klass->has_references;
1664 * mono_type_get_basic_type_from_generic:
1667 * Returns a closed type corresponding to the possibly open type
1671 mono_type_get_basic_type_from_generic (MonoType *type)
1673 /* When we do generic sharing we let type variables stand for reference types. */
1674 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1675 return &mono_defaults.object_class->byval_arg;
1680 * mono_class_layout_fields:
1683 * Compute the placement of fields inside an object or struct, according to
1684 * the layout rules and set the following fields in @class:
1685 * - has_references (if the class contains instance references firled or structs that contain references)
1686 * - has_static_refs (same, but for static fields)
1687 * - instance_size (size of the object in memory)
1688 * - class_size (size needed for the static fields)
1689 * - size_inited (flag set when the instance_size is set)
1691 * LOCKING: this is supposed to be called with the loader lock held.
1694 mono_class_layout_fields (MonoClass *class)
1697 const int top = class->field.count;
1698 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1699 guint32 pass, passes, real_size;
1700 gboolean gc_aware_layout = FALSE;
1701 MonoClassField *field;
1704 * When we do generic sharing we need to have layout
1705 * information for open generic classes (either with a generic
1706 * context containing type variables or with a generic
1707 * container), so we don't return in that case anymore.
1711 * Enable GC aware auto layout: in this mode, reference
1712 * fields are grouped together inside objects, increasing collector
1714 * Requires that all classes whose layout is known to native code be annotated
1715 * with [StructLayout (LayoutKind.Sequential)]
1716 * Value types have gc_aware_layout disabled by default, as per
1717 * what the default is for other runtimes.
1719 /* corlib is missing [StructLayout] directives in many places */
1720 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1721 if (!class->valuetype)
1722 gc_aware_layout = TRUE;
1725 /* Compute klass->has_references */
1727 * Process non-static fields first, since static fields might recursively
1728 * refer to the class itself.
1730 for (i = 0; i < top; i++) {
1733 field = &class->fields [i];
1735 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1736 ftype = mono_type_get_underlying_type (field->type);
1737 ftype = mono_type_get_basic_type_from_generic (ftype);
1738 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1739 class->has_references = TRUE;
1743 for (i = 0; i < top; i++) {
1746 field = &class->fields [i];
1748 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1749 ftype = mono_type_get_underlying_type (field->type);
1750 ftype = mono_type_get_basic_type_from_generic (ftype);
1751 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1752 class->has_static_refs = TRUE;
1756 for (i = 0; i < top; i++) {
1759 field = &class->fields [i];
1761 ftype = mono_type_get_underlying_type (field->type);
1762 ftype = mono_type_get_basic_type_from_generic (ftype);
1763 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1764 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1765 class->has_static_refs = TRUE;
1767 class->has_references = TRUE;
1772 * Compute field layout and total size (not considering static fields)
1776 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1777 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1779 if (gc_aware_layout)
1784 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1787 if (class->parent) {
1788 mono_class_setup_fields (class->parent);
1789 if (class->parent->exception_type) {
1790 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1793 real_size = class->parent->instance_size;
1795 real_size = sizeof (MonoObject);
1798 for (pass = 0; pass < passes; ++pass) {
1799 for (i = 0; i < top; i++){
1804 field = &class->fields [i];
1806 if (mono_field_is_deleted (field))
1808 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1811 ftype = mono_type_get_underlying_type (field->type);
1812 ftype = mono_type_get_basic_type_from_generic (ftype);
1813 if (gc_aware_layout) {
1814 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1823 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1824 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1825 /* This field is a hack inserted by MCS to empty structures */
1829 size = mono_type_size (field->type, &align);
1831 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1832 align = class->packing_size ? MIN (class->packing_size, align): align;
1833 /* if the field has managed references, we need to force-align it
1836 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1837 align = MAX (align, sizeof (gpointer));
1839 class->min_align = MAX (align, class->min_align);
1840 field->offset = real_size;
1842 field->offset += align - 1;
1843 field->offset &= ~(align - 1);
1845 /*TypeBuilders produce all sort of weird things*/
1846 g_assert (class->image->dynamic || field->offset > 0);
1847 real_size = field->offset + size;
1850 class->instance_size = MAX (real_size, class->instance_size);
1852 if (class->instance_size & (class->min_align - 1)) {
1853 class->instance_size += class->min_align - 1;
1854 class->instance_size &= ~(class->min_align - 1);
1858 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1860 for (i = 0; i < top; i++) {
1865 field = &class->fields [i];
1868 * There must be info about all the fields in a type if it
1869 * uses explicit layout.
1872 if (mono_field_is_deleted (field))
1874 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1877 size = mono_type_size (field->type, &align);
1878 align = class->packing_size ? MIN (class->packing_size, align): align;
1879 class->min_align = MAX (align, class->min_align);
1882 * When we get here, field->offset is already set by the
1883 * loader (for either runtime fields or fields loaded from metadata).
1884 * The offset is from the start of the object: this works for both
1885 * classes and valuetypes.
1887 field->offset += sizeof (MonoObject);
1888 ftype = mono_type_get_underlying_type (field->type);
1889 ftype = mono_type_get_basic_type_from_generic (ftype);
1890 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1891 if (field->offset % sizeof (gpointer)) {
1892 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1899 real_size = MAX (real_size, size + field->offset);
1901 class->instance_size = MAX (real_size, class->instance_size);
1902 if (class->instance_size & (class->min_align - 1)) {
1903 class->instance_size += class->min_align - 1;
1904 class->instance_size &= ~(class->min_align - 1);
1909 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1911 * For small structs, set min_align to at least the struct size to improve
1912 * performance, and since the JIT memset/memcpy code assumes this and generates
1913 * unaligned accesses otherwise. See #78990 for a testcase.
1915 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1916 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1919 mono_memory_barrier ();
1920 class->size_inited = 1;
1923 * Compute static field layout and size
1925 for (i = 0; i < top; i++){
1929 field = &class->fields [i];
1931 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1933 if (mono_field_is_deleted (field))
1936 if (mono_type_has_exceptions (field->type)) {
1937 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1941 size = mono_type_size (field->type, &align);
1942 field->offset = class->sizes.class_size;
1943 /*align is always non-zero here*/
1944 field->offset += align - 1;
1945 field->offset &= ~(align - 1);
1946 class->sizes.class_size = field->offset + size;
1951 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
1955 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
1956 method->klass = class;
1957 method->flags = METHOD_ATTRIBUTE_PUBLIC;
1958 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
1959 method->signature = sig;
1960 method->name = name;
1963 if (name [0] == '.') {
1964 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
1966 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
1972 * mono_class_setup_methods:
1975 * Initializes the 'methods' array in the klass.
1976 * Calling this method should be avoided if possible since it allocates a lot
1977 * of long-living MonoMethod structures.
1978 * Methods belonging to an interface are assigned a sequential slot starting
1981 * On failure this function sets class->exception_type
1984 mono_class_setup_methods (MonoClass *class)
1987 MonoMethod **methods;
1992 mono_loader_lock ();
1994 if (class->methods) {
1995 mono_loader_unlock ();
1999 if (class->generic_class) {
2001 MonoClass *gklass = class->generic_class->container_class;
2003 mono_class_init (gklass);
2004 if (!gklass->exception_type)
2005 mono_class_setup_methods (gklass);
2006 if (gklass->exception_type) {
2007 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2008 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2009 mono_loader_unlock ();
2013 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2014 class->method.count = gklass->method.count;
2015 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2017 for (i = 0; i < class->method.count; i++) {
2018 methods [i] = mono_class_inflate_generic_method_full_checked (
2019 gklass->methods [i], class, mono_class_get_context (class), &error);
2020 if (!mono_error_ok (&error)) {
2021 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2022 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)));
2025 mono_error_cleanup (&error);
2026 mono_loader_unlock ();
2030 } else if (class->rank) {
2032 MonoMethod *amethod;
2033 MonoMethodSignature *sig;
2034 int count_generic = 0, first_generic = 0;
2037 class->method.count = 3 + (class->rank > 1? 2: 1);
2039 mono_class_setup_interfaces (class, &error);
2040 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2042 if (class->interface_count) {
2043 count_generic = generic_array_methods (class);
2044 first_generic = class->method.count;
2045 class->method.count += class->interface_count * count_generic;
2048 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2050 sig = mono_metadata_signature_alloc (class->image, class->rank);
2051 sig->ret = &mono_defaults.void_class->byval_arg;
2052 sig->pinvoke = TRUE;
2053 sig->hasthis = TRUE;
2054 for (i = 0; i < class->rank; ++i)
2055 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2057 amethod = create_array_method (class, ".ctor", sig);
2058 methods [method_num++] = amethod;
2059 if (class->rank > 1) {
2060 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2061 sig->ret = &mono_defaults.void_class->byval_arg;
2062 sig->pinvoke = TRUE;
2063 sig->hasthis = TRUE;
2064 for (i = 0; i < class->rank * 2; ++i)
2065 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2067 amethod = create_array_method (class, ".ctor", sig);
2068 methods [method_num++] = amethod;
2070 /* element Get (idx11, [idx2, ...]) */
2071 sig = mono_metadata_signature_alloc (class->image, class->rank);
2072 sig->ret = &class->element_class->byval_arg;
2073 sig->pinvoke = TRUE;
2074 sig->hasthis = TRUE;
2075 for (i = 0; i < class->rank; ++i)
2076 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2077 amethod = create_array_method (class, "Get", sig);
2078 methods [method_num++] = amethod;
2079 /* element& Address (idx11, [idx2, ...]) */
2080 sig = mono_metadata_signature_alloc (class->image, class->rank);
2081 sig->ret = &class->element_class->this_arg;
2082 sig->pinvoke = TRUE;
2083 sig->hasthis = TRUE;
2084 for (i = 0; i < class->rank; ++i)
2085 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2086 amethod = create_array_method (class, "Address", sig);
2087 methods [method_num++] = amethod;
2088 /* void Set (idx11, [idx2, ...], element) */
2089 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2090 sig->ret = &mono_defaults.void_class->byval_arg;
2091 sig->pinvoke = TRUE;
2092 sig->hasthis = TRUE;
2093 for (i = 0; i < class->rank; ++i)
2094 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2095 sig->params [i] = &class->element_class->byval_arg;
2096 amethod = create_array_method (class, "Set", sig);
2097 methods [method_num++] = amethod;
2099 for (i = 0; i < class->interface_count; i++)
2100 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2102 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2103 for (i = 0; i < class->method.count; ++i) {
2104 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2105 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2109 if (MONO_CLASS_IS_INTERFACE (class)) {
2111 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2112 for (i = 0; i < class->method.count; ++i) {
2113 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2114 methods [i]->slot = slot++;
2118 /* Needed because of the double-checking locking pattern */
2119 mono_memory_barrier ();
2121 class->methods = methods;
2123 if (mono_debugger_class_loaded_methods_func)
2124 mono_debugger_class_loaded_methods_func (class);
2126 mono_loader_unlock ();
2130 * mono_class_get_method_by_index:
2132 * Returns class->methods [index], initializing class->methods if neccesary.
2134 * LOCKING: Acquires the loader lock.
2137 mono_class_get_method_by_index (MonoClass *class, int index)
2139 /* Avoid calling setup_methods () if possible */
2140 if (class->generic_class && !class->methods) {
2141 MonoClass *gklass = class->generic_class->container_class;
2144 m = mono_class_inflate_generic_method_full (
2145 gklass->methods [index], class, mono_class_get_context (class));
2147 * If setup_methods () is called later for this class, no duplicates are created,
2148 * since inflate_generic_method guarantees that only one instance of a method
2149 * is created for each context.
2152 mono_class_setup_methods (class);
2153 g_assert (m == class->methods [index]);
2157 mono_class_setup_methods (class);
2158 if (class->exception_type) /*FIXME do proper error handling*/
2160 g_assert (index >= 0 && index < class->method.count);
2161 return class->methods [index];
2166 * mono_class_get_inflated_method:
2168 * Given an inflated class CLASS and a method METHOD which should be a method of
2169 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2172 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2174 MonoClass *gklass = class->generic_class->container_class;
2177 g_assert (method->klass == gklass);
2179 mono_class_setup_methods (gklass);
2180 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2182 for (i = 0; i < gklass->method.count; ++i) {
2183 if (gklass->methods [i] == method) {
2185 return class->methods [i];
2187 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2195 * mono_class_get_vtable_entry:
2197 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2198 * LOCKING: Acquires the loader lock.
2201 mono_class_get_vtable_entry (MonoClass *class, int offset)
2205 if (class->rank == 1) {
2207 * szarrays do not overwrite any methods of Array, so we can avoid
2208 * initializing their vtables in some cases.
2210 mono_class_setup_vtable (class->parent);
2211 if (offset < class->parent->vtable_size)
2212 return class->parent->vtable [offset];
2215 if (class->generic_class) {
2216 MonoClass *gklass = class->generic_class->container_class;
2217 mono_class_setup_vtable (gklass);
2218 m = gklass->vtable [offset];
2220 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2222 mono_class_setup_vtable (class);
2223 if (class->exception_type)
2225 m = class->vtable [offset];
2232 * mono_class_get_vtable_size:
2234 * Return the vtable size for KLASS.
2237 mono_class_get_vtable_size (MonoClass *klass)
2239 mono_class_setup_vtable (klass);
2241 return klass->vtable_size;
2244 /*This method can fail the class.*/
2246 mono_class_setup_properties (MonoClass *class)
2248 guint startm, endm, i, j;
2249 guint32 cols [MONO_PROPERTY_SIZE];
2250 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2251 MonoProperty *properties;
2254 if (class->ext && class->ext->properties)
2257 mono_loader_lock ();
2259 if (class->ext && class->ext->properties) {
2260 mono_loader_unlock ();
2264 mono_class_alloc_ext (class);
2266 if (class->generic_class) {
2267 MonoClass *gklass = class->generic_class->container_class;
2269 mono_class_init (gklass);
2270 mono_class_setup_properties (gklass);
2271 if (gklass->exception_type) {
2272 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2273 mono_loader_unlock ();
2277 class->ext->property = gklass->ext->property;
2279 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2281 for (i = 0; i < class->ext->property.count; i++) {
2282 MonoProperty *prop = &properties [i];
2284 *prop = gklass->ext->properties [i];
2287 prop->get = mono_class_inflate_generic_method_full (
2288 prop->get, class, mono_class_get_context (class));
2290 prop->set = mono_class_inflate_generic_method_full (
2291 prop->set, class, mono_class_get_context (class));
2293 prop->parent = class;
2296 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2297 int count = last - first;
2300 mono_class_setup_methods (class);
2301 if (class->exception_type) {
2302 mono_loader_unlock ();
2307 class->ext->property.first = first;
2308 class->ext->property.count = count;
2309 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2310 for (i = first; i < last; ++i) {
2311 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2312 properties [i - first].parent = class;
2313 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2314 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2316 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2317 for (j = startm; j < endm; ++j) {
2320 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2322 if (class->image->uncompressed_metadata)
2323 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2324 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2326 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2328 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2329 case METHOD_SEMANTIC_SETTER:
2330 properties [i - first].set = method;
2332 case METHOD_SEMANTIC_GETTER:
2333 properties [i - first].get = method;
2341 /*Flush any pending writes as we do double checked locking on class->properties */
2342 mono_memory_barrier ();
2344 /* Leave this assignment as the last op in the function */
2345 class->ext->properties = properties;
2347 mono_loader_unlock ();
2351 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2353 MonoMethod **om, **retval;
2356 for (om = methods, count = 0; *om; ++om, ++count)
2359 retval = g_new0 (MonoMethod*, count + 1);
2361 for (om = methods, count = 0; *om; ++om, ++count)
2362 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2367 /*This method can fail the class.*/
2369 mono_class_setup_events (MonoClass *class)
2372 guint startm, endm, i, j;
2373 guint32 cols [MONO_EVENT_SIZE];
2374 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2378 if (class->ext && class->ext->events)
2381 mono_loader_lock ();
2383 if (class->ext && class->ext->events) {
2384 mono_loader_unlock ();
2388 mono_class_alloc_ext (class);
2390 if (class->generic_class) {
2391 MonoClass *gklass = class->generic_class->container_class;
2392 MonoGenericContext *context;
2394 mono_class_setup_events (gklass);
2395 if (gklass->exception_type) {
2396 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2397 mono_loader_unlock ();
2401 class->ext->event = gklass->ext->event;
2402 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2404 if (class->ext->event.count)
2405 context = mono_class_get_context (class);
2407 for (i = 0; i < class->ext->event.count; i++) {
2408 MonoEvent *event = &class->ext->events [i];
2409 MonoEvent *gevent = &gklass->ext->events [i];
2411 event->parent = class;
2412 event->name = gevent->name;
2413 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2414 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2415 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2416 #ifndef MONO_SMALL_CONFIG
2417 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2419 event->attrs = gevent->attrs;
2422 mono_loader_unlock ();
2426 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2427 count = last - first;
2430 mono_class_setup_methods (class);
2431 if (class->exception_type) {
2432 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2433 mono_loader_unlock ();
2437 class->ext->event.first = first;
2438 class->ext->event.count = count;
2439 events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2440 for (i = first; i < last; ++i) {
2441 MonoEvent *event = &events [i - first];
2443 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2444 event->parent = class;
2445 event->attrs = cols [MONO_EVENT_FLAGS];
2446 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2448 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2449 for (j = startm; j < endm; ++j) {
2452 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2454 if (class->image->uncompressed_metadata)
2455 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2456 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2458 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2460 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2461 case METHOD_SEMANTIC_ADD_ON:
2462 event->add = method;
2464 case METHOD_SEMANTIC_REMOVE_ON:
2465 event->remove = method;
2467 case METHOD_SEMANTIC_FIRE:
2468 event->raise = method;
2470 case METHOD_SEMANTIC_OTHER: {
2471 #ifndef MONO_SMALL_CONFIG
2474 if (event->other == NULL) {
2475 event->other = g_new0 (MonoMethod*, 2);
2477 while (event->other [n])
2479 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2481 event->other [n] = method;
2482 /* NULL terminated */
2483 event->other [n + 1] = NULL;
2492 /*Flush any pending writes as we do double checked locking on class->properties */
2493 mono_memory_barrier ();
2495 /* Leave this assignment as the last op in the function */
2496 class->ext->events = events;
2498 mono_loader_unlock ();
2502 * Global pool of interface IDs, represented as a bitset.
2503 * LOCKING: this is supposed to be accessed with the loader lock held.
2505 static MonoBitSet *global_interface_bitset = NULL;
2508 * mono_unload_interface_ids:
2509 * @bitset: bit set of interface IDs
2511 * When an image is unloaded, the interface IDs associated with
2512 * the image are put back in the global pool of IDs so the numbers
2516 mono_unload_interface_ids (MonoBitSet *bitset)
2518 mono_loader_lock ();
2519 mono_bitset_sub (global_interface_bitset, bitset);
2520 mono_loader_unlock ();
2524 mono_unload_interface_id (MonoClass *class)
2526 if (global_interface_bitset && class->interface_id) {
2527 mono_loader_lock ();
2528 mono_bitset_clear (global_interface_bitset, class->interface_id);
2529 mono_loader_unlock ();
2534 * mono_get_unique_iid:
2537 * Assign a unique integer ID to the interface represented by @class.
2538 * The ID will positive and as small as possible.
2539 * LOCKING: this is supposed to be called with the loader lock held.
2540 * Returns: the new ID.
2543 mono_get_unique_iid (MonoClass *class)
2547 g_assert (MONO_CLASS_IS_INTERFACE (class));
2549 if (!global_interface_bitset) {
2550 global_interface_bitset = mono_bitset_new (128, 0);
2553 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2555 int old_size = mono_bitset_size (global_interface_bitset);
2556 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2557 mono_bitset_free (global_interface_bitset);
2558 global_interface_bitset = new_set;
2561 mono_bitset_set (global_interface_bitset, iid);
2562 /* set the bit also in the per-image set */
2563 if (!class->generic_class) {
2564 if (class->image->interface_bitset) {
2565 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2566 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2567 mono_bitset_free (class->image->interface_bitset);
2568 class->image->interface_bitset = new_set;
2571 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2573 mono_bitset_set (class->image->interface_bitset, iid);
2576 #ifndef MONO_SMALL_CONFIG
2577 if (mono_print_vtable) {
2579 char *type_name = mono_type_full_name (&class->byval_arg);
2580 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2581 generic_id = class->generic_class->context.class_inst->id;
2582 g_assert (generic_id != 0);
2586 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2591 g_assert (iid <= 65535);
2596 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2601 mono_class_setup_interfaces (klass, error);
2602 if (!mono_error_ok (error))
2605 for (i = 0; i < klass->interface_count; i++) {
2606 ic = klass->interfaces [i];
2609 *res = g_ptr_array_new ();
2610 g_ptr_array_add (*res, ic);
2611 mono_class_init (ic);
2612 if (ic->exception_type) {
2613 mono_error_set_type_load_class (error, ic, "Error Loading class");
2617 collect_implemented_interfaces_aux (ic, res, error);
2618 if (!mono_error_ok (error))
2624 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2626 GPtrArray *res = NULL;
2628 collect_implemented_interfaces_aux (klass, &res, error);
2629 if (!mono_error_ok (error)) {
2631 g_ptr_array_free (res, TRUE);
2638 compare_interface_ids (const void *p_key, const void *p_element) {
2639 const MonoClass *key = p_key;
2640 const MonoClass *element = *(MonoClass**) p_element;
2642 return (key->interface_id - element->interface_id);
2645 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2647 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2648 MonoClass **result = bsearch (
2650 klass->interfaces_packed,
2651 klass->interface_offsets_count,
2652 sizeof (MonoClass *),
2653 compare_interface_ids);
2655 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2662 * mono_class_interface_offset_with_variance:
2664 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2665 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2667 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2669 * FIXME figure out MS disambiguation rules and fix this function.
2672 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2673 int i = mono_class_interface_offset (klass, itf);
2674 *non_exact_match = FALSE;
2678 if (!mono_class_has_variant_generic_params (itf))
2681 for (i = 0; i < klass->interface_offsets_count; i++) {
2682 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2683 *non_exact_match = TRUE;
2684 return klass->interface_offsets_packed [i];
2692 print_implemented_interfaces (MonoClass *klass) {
2695 GPtrArray *ifaces = NULL;
2697 int ancestor_level = 0;
2699 name = mono_type_get_full_name (klass);
2700 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2703 for (i = 0; i < klass->interface_offsets_count; i++)
2704 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2705 klass->interfaces_packed [i]->interface_id,
2706 klass->interface_offsets_packed [i],
2707 klass->interfaces_packed [i]->method.count,
2708 klass->interfaces_packed [i]->name_space,
2709 klass->interfaces_packed [i]->name );
2710 printf ("Interface flags: ");
2711 for (i = 0; i <= klass->max_interface_id; i++)
2712 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2713 printf ("(%d,T)", i);
2715 printf ("(%d,F)", i);
2717 printf ("Dump interface flags:");
2718 #ifdef COMPRESSED_INTERFACE_BITMAP
2720 const uint8_t* p = klass->interface_bitmap;
2721 i = klass->max_interface_id;
2723 printf (" %d x 00 %02X", p [0], p [1]);
2729 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2730 printf (" %02X", klass->interface_bitmap [i]);
2733 while (klass != NULL) {
2734 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2735 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2736 if (!mono_error_ok (&error)) {
2737 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2738 mono_error_cleanup (&error);
2739 } else if (ifaces) {
2740 for (i = 0; i < ifaces->len; i++) {
2741 MonoClass *ic = g_ptr_array_index (ifaces, i);
2742 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2743 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2745 mono_class_interface_offset (klass, ic),
2750 g_ptr_array_free (ifaces, TRUE);
2753 klass = klass->parent;
2758 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2761 args [0] = &arg0->byval_arg;
2763 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2767 array_class_get_if_rank (MonoClass *class, guint rank)
2769 return rank ? mono_array_class_get (class, rank) : class;
2773 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2775 valuetype_types [0] = eclass;
2776 if (eclass == mono_defaults.int16_class)
2777 valuetype_types [1] = mono_defaults.uint16_class;
2778 else if (eclass == mono_defaults.uint16_class)
2779 valuetype_types [1] = mono_defaults.int16_class;
2780 else if (eclass == mono_defaults.int32_class)
2781 valuetype_types [1] = mono_defaults.uint32_class;
2782 else if (eclass == mono_defaults.uint32_class)
2783 valuetype_types [1] = mono_defaults.int32_class;
2784 else if (eclass == mono_defaults.int64_class)
2785 valuetype_types [1] = mono_defaults.uint64_class;
2786 else if (eclass == mono_defaults.uint64_class)
2787 valuetype_types [1] = mono_defaults.int64_class;
2788 else if (eclass == mono_defaults.byte_class)
2789 valuetype_types [1] = mono_defaults.sbyte_class;
2790 else if (eclass == mono_defaults.sbyte_class)
2791 valuetype_types [1] = mono_defaults.byte_class;
2792 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2793 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2796 /* this won't be needed once bug #325495 is completely fixed
2797 * though we'll need something similar to know which interfaces to allow
2798 * in arrays when they'll be lazyly created
2800 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2801 * MS returns diferrent types based on which instance is called. For example:
2802 * object obj = new byte[10][];
2803 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2804 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2807 * Fixing this should kill quite some code, save some bits and improve compatibility.
2810 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2812 MonoClass *eclass = class->element_class;
2813 static MonoClass* generic_icollection_class = NULL;
2814 static MonoClass* generic_ienumerable_class = NULL;
2815 static MonoClass* generic_ienumerator_class = NULL;
2816 static MonoClass* generic_ireadonlylist_class = NULL;
2817 static MonoClass* generic_ireadonlycollection_class = NULL;
2818 MonoClass *valuetype_types[2] = { NULL, NULL };
2819 MonoClass **interfaces = NULL;
2820 int i, nifaces, interface_count, real_count, original_rank;
2822 gboolean internal_enumerator;
2823 gboolean eclass_is_valuetype;
2825 if (!mono_defaults.generic_ilist_class) {
2829 internal_enumerator = FALSE;
2830 eclass_is_valuetype = FALSE;
2831 original_rank = eclass->rank;
2832 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2833 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2835 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2837 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2838 original_rank = eclass->rank;
2840 eclass = eclass->element_class;
2841 internal_enumerator = TRUE;
2842 *is_enumerator = TRUE;
2850 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2851 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2853 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2855 if (!generic_icollection_class) {
2856 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2857 "System.Collections.Generic", "ICollection`1");
2858 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2859 "System.Collections.Generic", "IEnumerable`1");
2860 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2861 "System.Collections.Generic", "IEnumerator`1");
2862 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2863 "System.Collections.Generic", "IReadOnlyList`1");
2864 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2865 "System.Collections.Generic", "IReadOnlyCollection`1");
2868 mono_class_init (eclass);
2871 * Arrays in 2.0 need to implement a number of generic interfaces
2872 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2873 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2874 * We collect the types needed to build the
2875 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2876 * the generic interfaces needed to implement.
2878 nifaces = generic_ireadonlylist_class ? 5 : 3;
2879 if (eclass->valuetype) {
2880 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2882 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2883 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2884 if (internal_enumerator) {
2886 if (valuetype_types [1])
2890 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2891 interfaces [0] = valuetype_types [0];
2892 if (valuetype_types [1])
2893 interfaces [nifaces] = valuetype_types [1];
2895 eclass_is_valuetype = TRUE;
2898 int idepth = eclass->idepth;
2899 if (!internal_enumerator)
2902 // FIXME: This doesn't seem to work/required for generic params
2903 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
2904 mono_class_setup_interface_offsets (eclass);
2906 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2907 /* we add object for interfaces and the supertypes for the other
2908 * types. The last of the supertypes is the element class itself which we
2909 * already created the explicit interfaces for (so we include it for IEnumerator
2910 * and exclude it for arrays).
2912 if (MONO_CLASS_IS_INTERFACE (eclass))
2915 interface_count += idepth;
2916 if (eclass->rank && eclass->element_class->valuetype) {
2917 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2918 if (valuetype_types [1])
2921 /* IList, ICollection, IEnumerable, IReadOnlyList */
2922 interface_count *= nifaces;
2923 real_count = interface_count;
2924 if (internal_enumerator) {
2925 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2926 if (valuetype_types [1])
2929 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2930 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2931 interfaces [0] = mono_defaults.object_class;
2935 for (i = 0; i < idepth; i++) {
2936 mono_class_init (eclass->supertypes [i]);
2937 interfaces [j] = eclass->supertypes [i];
2941 if (all_interfaces) {
2942 for (i = 0; i < eclass->interface_offsets_count; i++) {
2943 interfaces [j] = eclass->interfaces_packed [i];
2947 for (i = 0; i < eclass->interface_count; i++) {
2948 interfaces [j] = eclass->interfaces [i];
2952 if (valuetype_types [1]) {
2953 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
2958 /* instantiate the generic interfaces */
2959 for (i = 0; i < interface_count; i += nifaces) {
2960 MonoClass *iface = interfaces [i];
2962 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
2963 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
2964 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
2965 if (generic_ireadonlylist_class) {
2966 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
2967 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
2970 if (internal_enumerator) {
2972 /* instantiate IEnumerator<iface> */
2973 for (i = 0; i < interface_count; i++) {
2974 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
2976 j = interface_count;
2977 if (!eclass_is_valuetype) {
2978 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2979 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
2982 for (i = 0; i < eclass->idepth; i++) {
2983 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
2987 for (i = 0; i < eclass->interface_offsets_count; i++) {
2988 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
2992 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
2994 if (valuetype_types [1])
2995 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
2999 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3000 for (i = 0; i < real_count; ++i) {
3001 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3002 g_print ("%s implements %s\n", type_name, name);
3013 find_array_interface (MonoClass *klass, const char *name)
3016 for (i = 0; i < klass->interface_count; ++i) {
3017 if (strcmp (klass->interfaces [i]->name, name) == 0)
3024 * Return the number of virtual methods.
3025 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3026 * Return -1 on failure.
3027 * FIXME It would be nice if this information could be cached somewhere.
3030 count_virtual_methods (MonoClass *class)
3034 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3036 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3037 mono_class_setup_methods (class);
3038 if (class->exception_type)
3041 for (i = 0; i < class->method.count; ++i) {
3042 flags = class->methods [i]->flags;
3043 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3047 for (i = 0; i < class->method.count; ++i) {
3048 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3050 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3058 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3066 m = (l + num_ifaces) / 2;
3067 if (interfaces_full [m] == ic)
3069 if (l == num_ifaces)
3071 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3080 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3082 int i = find_interface (num_ifaces, interfaces_full, ic);
3084 return interface_offsets_full [i];
3089 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3091 int i = find_interface (num_ifaces, interfaces_full, ic);
3095 interface_offsets_full [i] = offset;
3098 for (i = 0; i < num_ifaces; ++i) {
3099 if (interfaces_full [i]) {
3101 if (interfaces_full [i]->interface_id < ic->interface_id)
3104 while (end < num_ifaces && interfaces_full [end]) end++;
3105 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3106 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3108 interfaces_full [i] = ic;
3109 interface_offsets_full [i] = offset;
3115 #ifdef COMPRESSED_INTERFACE_BITMAP
3118 * Compressed interface bitmap design.
3120 * Interface bitmaps take a large amount of memory, because their size is
3121 * linear with the maximum interface id assigned in the process (each interface
3122 * is assigned a unique id as it is loaded). The number of interface classes
3123 * is high because of the many implicit interfaces implemented by arrays (we'll
3124 * need to lazy-load them in the future).
3125 * Most classes implement a very small number of interfaces, so the bitmap is
3126 * sparse. This bitmap needs to be checked by interface casts, so access to the
3127 * needed bit must be fast and doable with few jit instructions.
3129 * The current compression format is as follows:
3130 * *) it is a sequence of one or more two-byte elements
3131 * *) the first byte in the element is the count of empty bitmap bytes
3132 * at the current bitmap position
3133 * *) the second byte in the element is an actual bitmap byte at the current
3136 * As an example, the following compressed bitmap bytes:
3137 * 0x07 0x01 0x00 0x7
3138 * correspond to the following bitmap:
3139 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3141 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3142 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3143 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3147 * mono_compress_bitmap:
3148 * @dest: destination buffer
3149 * @bitmap: bitmap buffer
3150 * @size: size of @bitmap in bytes
3152 * This is a mono internal function.
3153 * The @bitmap data is compressed into a format that is small but
3154 * still searchable in few instructions by the JIT and runtime.
3155 * The compressed data is stored in the buffer pointed to by the
3156 * @dest array. Passing a #NULL value for @dest allows to just compute
3157 * the size of the buffer.
3158 * This compression algorithm assumes the bits set in the bitmap are
3159 * few and far between, like in interface bitmaps.
3160 * Returns: the size of the compressed bitmap in bytes.
3163 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3167 const uint8_t *end = bitmap + size;
3168 while (bitmap < end) {
3169 if (*bitmap || numz == 255) {
3193 * mono_class_interface_match:
3194 * @bitmap: a compressed bitmap buffer
3195 * @id: the index to check in the bitmap
3197 * This is a mono internal function.
3198 * Checks if a bit is set in a compressed interface bitmap. @id must
3199 * be already checked for being smaller than the maximum id encoded in the
3202 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3206 mono_class_interface_match (const uint8_t *bitmap, int id)
3209 id -= bitmap [0] * 8;
3213 return bitmap [1] & (1 << id);
3222 * LOCKING: this is supposed to be called with the loader lock held.
3223 * Return -1 on failure and set exception_type
3226 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3230 int i, j, max_iid, num_ifaces;
3231 MonoClass **interfaces_full = NULL;
3232 int *interface_offsets_full = NULL;
3234 GPtrArray **ifaces_array = NULL;
3235 int interface_offsets_count;
3236 MonoClass **array_interfaces = NULL;
3237 int num_array_interfaces;
3238 int is_enumerator = FALSE;
3240 mono_class_setup_supertypes (class);
3242 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3243 * implicit interfaces have the property that they are assigned the same slot in the
3244 * vtables for compatible interfaces
3246 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3248 /* compute maximum number of slots and maximum interface id */
3250 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3251 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3252 for (j = 0; j < class->idepth; j++) {
3253 k = class->supertypes [j];
3254 num_ifaces += k->interface_count;
3255 for (i = 0; i < k->interface_count; i++) {
3256 ic = k->interfaces [i];
3259 mono_class_init (ic);
3261 if (max_iid < ic->interface_id)
3262 max_iid = ic->interface_id;
3264 ifaces = mono_class_get_implemented_interfaces (k, &error);
3265 if (!mono_error_ok (&error)) {
3266 char *name = mono_type_get_full_name (k);
3267 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)));
3269 mono_error_cleanup (&error);
3274 num_ifaces += ifaces->len;
3275 for (i = 0; i < ifaces->len; ++i) {
3276 ic = g_ptr_array_index (ifaces, i);
3277 if (max_iid < ic->interface_id)
3278 max_iid = ic->interface_id;
3280 ifaces_array [j] = ifaces;
3284 for (i = 0; i < num_array_interfaces; ++i) {
3285 ic = array_interfaces [i];
3286 mono_class_init (ic);
3287 if (max_iid < ic->interface_id)
3288 max_iid = ic->interface_id;
3291 if (MONO_CLASS_IS_INTERFACE (class)) {
3293 if (max_iid < class->interface_id)
3294 max_iid = class->interface_id;
3296 class->max_interface_id = max_iid;
3297 /* compute vtable offset for interfaces */
3298 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3299 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3301 for (i = 0; i < num_ifaces; i++) {
3302 interface_offsets_full [i] = -1;
3305 /* skip the current class */
3306 for (j = 0; j < class->idepth - 1; j++) {
3307 k = class->supertypes [j];
3308 ifaces = ifaces_array [j];
3311 for (i = 0; i < ifaces->len; ++i) {
3313 ic = g_ptr_array_index (ifaces, i);
3315 /*Force the sharing of interface offsets between parent and subtypes.*/
3316 io = mono_class_interface_offset (k, ic);
3318 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3323 g_assert (class == class->supertypes [class->idepth - 1]);
3324 ifaces = ifaces_array [class->idepth - 1];
3326 for (i = 0; i < ifaces->len; ++i) {
3328 ic = g_ptr_array_index (ifaces, i);
3329 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3331 count = count_virtual_methods (ic);
3333 char *name = mono_type_get_full_name (ic);
3334 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3343 if (MONO_CLASS_IS_INTERFACE (class))
3344 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3346 if (num_array_interfaces) {
3347 if (is_enumerator) {
3348 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3349 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3350 g_assert (ienumerator_offset >= 0);
3351 for (i = 0; i < num_array_interfaces; ++i) {
3352 ic = array_interfaces [i];
3353 if (strcmp (ic->name, "IEnumerator`1") == 0)
3354 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3356 g_assert_not_reached ();
3357 /*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);*/
3360 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3361 int ilist_iface_idx = find_array_interface (class, "IList`1");
3362 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3363 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3364 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3365 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3366 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3367 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3368 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3369 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3370 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3371 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3372 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3373 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3374 for (i = 0; i < num_array_interfaces; ++i) {
3376 ic = array_interfaces [i];
3377 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3378 offset = ilist_offset;
3379 else if (strcmp (ic->name, "ICollection`1") == 0)
3380 offset = icollection_offset;
3381 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3382 offset = ienumerable_offset;
3383 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3384 offset = ireadonlylist_offset;
3385 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3386 offset = ireadonlycollection_offset;
3388 g_assert_not_reached ();
3389 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3390 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3395 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3396 if (interface_offsets_full [i] != -1) {
3397 interface_offsets_count ++;
3402 * We might get called multiple times:
3403 * - mono_class_init ()
3404 * - mono_class_setup_vtable ().
3405 * - mono_class_setup_interface_offsets ().
3406 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3407 * means we have to overwrite those when called from other places (#4440).
3409 if (class->interfaces_packed && !overwrite) {
3410 g_assert (class->interface_offsets_count == interface_offsets_count);
3414 class->interface_offsets_count = interface_offsets_count;
3415 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3416 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3417 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3418 #ifdef COMPRESSED_INTERFACE_BITMAP
3419 bitmap = g_malloc0 (bsize);
3421 bitmap = mono_class_alloc0 (class, bsize);
3423 for (i = 0; i < interface_offsets_count; i++) {
3424 int id = interfaces_full [i]->interface_id;
3425 bitmap [id >> 3] |= (1 << (id & 7));
3426 class->interfaces_packed [i] = interfaces_full [i];
3427 class->interface_offsets_packed [i] = interface_offsets_full [i];
3428 /*if (num_array_interfaces)
3429 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]);*/
3431 #ifdef COMPRESSED_INTERFACE_BITMAP
3432 i = mono_compress_bitmap (NULL, bitmap, bsize);
3433 class->interface_bitmap = mono_class_alloc0 (class, i);
3434 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3437 class->interface_bitmap = bitmap;
3442 g_free (interfaces_full);
3443 g_free (interface_offsets_full);
3444 g_free (array_interfaces);
3445 for (i = 0; i < class->idepth; i++) {
3446 ifaces = ifaces_array [i];
3448 g_ptr_array_free (ifaces, TRUE);
3450 g_free (ifaces_array);
3452 //printf ("JUST DONE: ");
3453 //print_implemented_interfaces (class);
3459 * Setup interface offsets for interfaces.
3461 * - class->max_interface_id
3462 * - class->interface_offsets_count
3463 * - class->interfaces_packed
3464 * - class->interface_offsets_packed
3465 * - class->interface_bitmap
3467 * This function can fail @class.
3470 mono_class_setup_interface_offsets (MonoClass *class)
3472 mono_loader_lock ();
3474 setup_interface_offsets (class, 0, FALSE);
3476 mono_loader_unlock ();
3479 /*Checks if @klass has @parent as one of it's parents type gtd
3483 * Bar<T> : Foo<Bar<Bar<T>>>
3487 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3489 klass = mono_class_get_generic_type_definition (klass);
3490 parent = mono_class_get_generic_type_definition (parent);
3491 mono_class_setup_supertypes (klass);
3492 mono_class_setup_supertypes (parent);
3494 return klass->idepth >= parent->idepth &&
3495 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3499 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3501 MonoGenericInst *ginst;
3503 if (!class->generic_class) {
3504 mono_class_setup_vtable_full (class, in_setup);
3505 return class->exception_type == 0;
3508 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3509 if (class->generic_class->container_class->exception_type) {
3510 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3514 ginst = class->generic_class->context.class_inst;
3515 for (i = 0; i < ginst->type_argc; ++i) {
3517 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3519 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3520 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3521 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3523 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3524 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3532 * mono_class_setup_vtable:
3534 * Creates the generic vtable of CLASS.
3535 * Initializes the following fields in MonoClass:
3538 * Plus all the fields initialized by setup_interface_offsets ().
3539 * If there is an error during vtable construction, class->exception_type is set.
3541 * LOCKING: Acquires the loader lock.
3544 mono_class_setup_vtable (MonoClass *class)
3546 mono_class_setup_vtable_full (class, NULL);
3550 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3552 MonoMethod **overrides;
3553 MonoGenericContext *context;
3561 if (mono_debug_using_mono_debugger ())
3562 /* The debugger currently depends on this */
3563 mono_class_setup_methods (class);
3565 if (MONO_CLASS_IS_INTERFACE (class)) {
3566 /* This sets method->slot for all methods if this is an interface */
3567 mono_class_setup_methods (class);
3571 if (class->exception_type)
3574 if (g_list_find (in_setup, class))
3577 mono_loader_lock ();
3579 if (class->vtable) {
3580 mono_loader_unlock ();
3584 mono_stats.generic_vtable_count ++;
3585 in_setup = g_list_prepend (in_setup, class);
3587 if (class->generic_class) {
3588 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3589 mono_loader_unlock ();
3590 g_list_remove (in_setup, class);
3594 context = mono_class_get_context (class);
3595 type_token = class->generic_class->container_class->type_token;
3597 context = (MonoGenericContext *) class->generic_container;
3598 type_token = class->type_token;
3601 if (class->image->dynamic) {
3602 /* Generic instances can have zero method overrides without causing any harm.
3603 * This is true since we don't do layout all over again for them, we simply inflate
3604 * the layout of the parent.
3606 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3608 /* The following call fails if there are missing methods in the type */
3609 /* FIXME it's probably a good idea to avoid this for generic instances. */
3610 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3614 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3616 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3620 mono_loader_unlock ();
3621 g_list_remove (in_setup, class);
3626 #define DEBUG_INTERFACE_VTABLE_CODE 0
3627 #define TRACE_INTERFACE_VTABLE_CODE 0
3628 #define VERIFY_INTERFACE_VTABLE_CODE 0
3629 #define VTABLE_SELECTOR (1)
3631 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3632 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3633 if (!(VTABLE_SELECTOR)) break; \
3637 #define DEBUG_INTERFACE_VTABLE(stmt)
3640 #if TRACE_INTERFACE_VTABLE_CODE
3641 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3642 if (!(VTABLE_SELECTOR)) break; \
3646 #define TRACE_INTERFACE_VTABLE(stmt)
3649 #if VERIFY_INTERFACE_VTABLE_CODE
3650 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3651 if (!(VTABLE_SELECTOR)) break; \
3655 #define VERIFY_INTERFACE_VTABLE(stmt)
3659 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3661 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3665 GString *res = g_string_new ("");
3667 g_string_append_c (res, '(');
3668 for (i = 0; i < sig->param_count; ++i) {
3670 g_string_append_c (res, ',');
3671 mono_type_get_desc (res, sig->params [i], include_namespace);
3673 g_string_append (res, ")=>");
3674 if (sig->ret != NULL) {
3675 mono_type_get_desc (res, sig->ret, include_namespace);
3677 g_string_append (res, "NULL");
3680 g_string_free (res, FALSE);
3684 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3685 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3686 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3687 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3695 is_wcf_hack_disabled (void)
3697 static gboolean disabled;
3698 static gboolean inited = FALSE;
3700 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3707 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) {
3708 MonoMethodSignature *cmsig, *imsig;
3709 if (strcmp (im->name, cm->name) == 0) {
3710 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3711 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3714 if (! slot_is_empty) {
3715 if (require_newslot) {
3716 if (! interface_is_explicitly_implemented_by_class) {
3717 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3720 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3721 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3725 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3728 cmsig = mono_method_signature (cm);
3729 imsig = mono_method_signature (im);
3730 if (!cmsig || !imsig) {
3731 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3735 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3736 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3737 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3738 TRACE_INTERFACE_VTABLE (printf ("]"));
3741 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3742 /* CAS - SecurityAction.InheritanceDemand on interface */
3743 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3744 mono_secman_inheritancedemand_method (cm, im);
3747 if (mono_security_core_clr_enabled ())
3748 mono_security_core_clr_check_override (class, cm, im);
3750 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3751 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3752 char *body_name = mono_method_full_name (cm, TRUE);
3753 char *decl_name = mono_method_full_name (im, TRUE);
3754 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));
3762 MonoClass *ic = im->klass;
3763 const char *ic_name_space = ic->name_space;
3764 const char *ic_name = ic->name;
3767 if (! require_newslot) {
3768 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3771 if (cm->klass->rank == 0) {
3772 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
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 ("[(INJECTED) SIGNATURE CHECK FAILED "));
3784 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3785 TRACE_INTERFACE_VTABLE (printf ("]"));
3788 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3789 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3792 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3793 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3796 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))) {
3797 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3801 subname = strstr (cm->name, ic_name_space);
3802 if (subname != cm->name) {
3803 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3806 subname += strlen (ic_name_space);
3807 if (subname [0] != '.') {
3808 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3812 if (strstr (subname, ic_name) != subname) {
3813 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3816 subname += strlen (ic_name);
3817 if (subname [0] != '.') {
3818 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3822 if (strcmp (subname, im->name) != 0) {
3823 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3827 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3828 /* CAS - SecurityAction.InheritanceDemand on interface */
3829 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3830 mono_secman_inheritancedemand_method (cm, im);
3833 if (mono_security_core_clr_enabled ())
3834 mono_security_core_clr_check_override (class, cm, im);
3836 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3837 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3838 char *body_name = mono_method_full_name (cm, TRUE);
3839 char *decl_name = mono_method_full_name (im, TRUE);
3840 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));
3850 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3852 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3853 MonoMethod *method = key;
3854 MonoMethod *override = value;
3855 MonoClass *method_class = mono_method_get_class (method);
3856 MonoClass *override_class = mono_method_get_class (override);
3858 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3859 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3860 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3863 print_overrides (GHashTable *override_map, const char *message) {
3865 printf ("Override map \"%s\" START:\n", message);
3866 g_hash_table_foreach (override_map, foreach_override, NULL);
3867 printf ("Override map \"%s\" END.\n", message);
3869 printf ("Override map \"%s\" EMPTY.\n", message);
3873 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3874 char *full_name = mono_type_full_name (&class->byval_arg);
3878 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3880 if (print_interfaces) {
3881 print_implemented_interfaces (class);
3882 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3885 if (class->parent) {
3886 parent_size = class->parent->vtable_size;
3890 for (i = 0; i < size; ++i) {
3891 MonoMethod *cm = vtable [i];
3892 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3893 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3895 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3903 #if VERIFY_INTERFACE_VTABLE_CODE
3905 mono_method_try_get_vtable_index (MonoMethod *method)
3907 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3908 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3909 if (imethod->declaring->is_generic)
3910 return imethod->declaring->slot;
3912 return method->slot;
3916 mono_class_verify_vtable (MonoClass *class)
3919 char *full_name = mono_type_full_name (&class->byval_arg);
3921 printf ("*** Verifying VTable of class '%s' \n", full_name);
3925 if (!class->methods)
3928 for (i = 0; i < class->method.count; ++i) {
3929 MonoMethod *cm = class->methods [i];
3932 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3936 full_name = mono_method_full_name (cm, TRUE);
3938 slot = mono_method_try_get_vtable_index (cm);
3940 if (slot >= class->vtable_size) {
3941 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
3945 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
3946 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
3947 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3948 g_free (other_name);
3951 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3958 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
3960 char *method_signature;
3963 for (index = 0; index < onum; ++index) {
3964 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
3965 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3967 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3968 type_name = mono_type_full_name (&class->byval_arg);
3969 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
3970 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3971 g_free (method_signature);
3973 mono_class_setup_methods (class);
3974 if (class->exception_type) {
3975 char *name = mono_type_get_full_name (class);
3976 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
3980 for (index = 0; index < class->method.count; ++index) {
3981 MonoMethod *cm = class->methods [index];
3982 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3984 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
3985 g_free (method_signature);
3990 mono_method_get_method_definition (MonoMethod *method)
3992 while (method->is_inflated)
3993 method = ((MonoMethodInflated*)method)->declaring;
3998 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4002 for (i = 0; i < onum; ++i) {
4003 MonoMethod *decl = overrides [i * 2];
4004 MonoMethod *body = overrides [i * 2 + 1];
4006 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4007 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4011 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4012 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4013 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4015 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4019 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4020 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4021 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4023 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4027 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4028 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4032 body = mono_method_get_method_definition (body);
4033 decl = mono_method_get_method_definition (decl);
4035 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4036 char *body_name = mono_method_full_name (body, TRUE);
4037 char *decl_name = mono_method_full_name (decl, TRUE);
4038 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));
4048 mono_class_need_stelemref_method (MonoClass *class)
4050 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4054 * LOCKING: this is supposed to be called with the loader lock held.
4057 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4061 MonoMethod **vtable;
4062 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4063 GPtrArray *ifaces = NULL;
4064 GHashTable *override_map = NULL;
4065 gboolean security_enabled = mono_security_enabled ();
4067 gpointer class_iter;
4068 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4069 int first_non_interface_slot;
4071 GSList *virt_methods = NULL, *l;
4072 int stelemref_slot = 0;
4077 if (overrides && !verify_class_overrides (class, overrides, onum))
4080 ifaces = mono_class_get_implemented_interfaces (class, &error);
4081 if (!mono_error_ok (&error)) {
4082 char *name = mono_type_get_full_name (class);
4083 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)));
4085 mono_error_cleanup (&error);
4087 } else if (ifaces) {
4088 for (i = 0; i < ifaces->len; i++) {
4089 MonoClass *ic = g_ptr_array_index (ifaces, i);
4090 max_vtsize += ic->method.count;
4092 g_ptr_array_free (ifaces, TRUE);
4096 if (class->parent) {
4097 mono_class_init (class->parent);
4098 mono_class_setup_vtable_full (class->parent, in_setup);
4100 if (class->parent->exception_type) {
4101 char *name = mono_type_get_full_name (class->parent);
4102 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4107 max_vtsize += class->parent->vtable_size;
4108 cur_slot = class->parent->vtable_size;
4111 max_vtsize += class->method.count;
4113 /*Array have a slot for stelemref*/
4114 if (mono_class_need_stelemref_method (class)) {
4115 stelemref_slot = cur_slot;
4120 vtable = alloca (sizeof (gpointer) * max_vtsize);
4121 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4123 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4125 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4126 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4129 max_iid = class->max_interface_id;
4130 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4132 /* Optimized version for generic instances */
4133 if (class->generic_class) {
4135 MonoClass *gklass = class->generic_class->container_class;
4138 mono_class_setup_vtable_full (gklass, in_setup);
4139 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4140 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4144 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4145 class->vtable_size = gklass->vtable_size;
4146 for (i = 0; i < gklass->vtable_size; ++i)
4147 if (gklass->vtable [i]) {
4148 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4149 if (!mono_error_ok (&error)) {
4150 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4151 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4153 mono_error_cleanup (&error);
4157 tmp [i]->slot = gklass->vtable [i]->slot;
4159 mono_memory_barrier ();
4160 class->vtable = tmp;
4162 /* Have to set method->slot for abstract virtual methods */
4163 if (class->methods && gklass->methods) {
4164 for (i = 0; i < class->method.count; ++i)
4165 if (class->methods [i]->slot == -1)
4166 class->methods [i]->slot = gklass->methods [i]->slot;
4172 if (class->parent && class->parent->vtable_size) {
4173 MonoClass *parent = class->parent;
4176 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4178 // Also inherit parent interface vtables, just as a starting point.
4179 // This is needed otherwise bug-77127.exe fails when the property methods
4180 // have different names in the iterface and the class, because for child
4181 // classes the ".override" information is not used anymore.
4182 for (i = 0; i < parent->interface_offsets_count; i++) {
4183 MonoClass *parent_interface = parent->interfaces_packed [i];
4184 int interface_offset = mono_class_interface_offset (class, parent_interface);
4185 /*FIXME this is now dead code as this condition will never hold true.
4186 Since interface offsets are inherited then the offset of an interface implemented
4187 by a parent will never be the out of it's vtable boundary.
4189 if (interface_offset >= parent->vtable_size) {
4190 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4193 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4194 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4195 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4196 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4197 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4198 parent_interface_offset + j, parent_interface_offset, j,
4199 interface_offset + j, interface_offset, j));
4206 /*Array have a slot for stelemref*/
4207 if (mono_class_need_stelemref_method (class)) {
4208 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4210 method->slot = stelemref_slot;
4212 g_assert (method->slot == stelemref_slot);
4214 vtable [stelemref_slot] = method;
4217 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4218 /* override interface methods */
4219 for (i = 0; i < onum; i++) {
4220 MonoMethod *decl = overrides [i*2];
4221 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4223 dslot = mono_method_get_vtable_slot (decl);
4225 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4229 dslot += mono_class_interface_offset (class, decl->klass);
4230 vtable [dslot] = overrides [i*2 + 1];
4231 vtable [dslot]->slot = dslot;
4233 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4235 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4237 if (mono_security_core_clr_enabled ())
4238 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4241 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4242 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4245 * Create a list of virtual methods to avoid calling
4246 * mono_class_get_virtual_methods () which is slow because of the metadata
4250 gpointer iter = NULL;
4253 virt_methods = NULL;
4254 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4255 virt_methods = g_slist_prepend (virt_methods, cm);
4257 if (class->exception_type)
4261 // Loop on all implemented interfaces...
4262 for (i = 0; i < class->interface_offsets_count; i++) {
4263 MonoClass *parent = class->parent;
4265 gboolean interface_is_explicitly_implemented_by_class;
4268 ic = class->interfaces_packed [i];
4269 ic_offset = mono_class_interface_offset (class, ic);
4271 mono_class_setup_methods (ic);
4272 if (ic->exception_type)
4275 // Check if this interface is explicitly implemented (instead of just inherited)
4276 if (parent != NULL) {
4277 int implemented_interfaces_index;
4278 interface_is_explicitly_implemented_by_class = FALSE;
4279 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4280 if (ic == class->interfaces [implemented_interfaces_index]) {
4281 interface_is_explicitly_implemented_by_class = TRUE;
4286 interface_is_explicitly_implemented_by_class = TRUE;
4289 // Loop on all interface methods...
4290 for (im_index = 0; im_index < ic->method.count; im_index++) {
4291 MonoMethod *im = ic->methods [im_index];
4292 int im_slot = ic_offset + im->slot;
4293 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4295 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4298 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4300 // If there is an explicit implementation, just use it right away,
4301 // otherwise look for a matching method
4302 if (override_im == NULL) {
4307 // First look for a suitable method among the class methods
4309 for (l = virt_methods; l; l = l->next) {
4311 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)));
4312 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4313 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4314 vtable [im_slot] = cm;
4315 /* Why do we need this? */
4320 TRACE_INTERFACE_VTABLE (printf ("\n"));
4321 if (class->exception_type) /*Might be set by check_interface_method_override*/
4325 // If the slot is still empty, look in all the inherited virtual methods...
4326 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4327 MonoClass *parent = class->parent;
4328 // Reverse order, so that last added methods are preferred
4329 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4330 MonoMethod *cm = parent->vtable [cm_index];
4332 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));
4333 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4334 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4335 vtable [im_slot] = cm;
4336 /* Why do we need this? */
4342 if (class->exception_type) /*Might be set by check_interface_method_override*/
4344 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4348 g_assert (vtable [im_slot] == override_im);
4353 // If the class is not abstract, check that all its interface slots are full.
4354 // The check is done here and not directly at the end of the loop above because
4355 // it can happen (for injected generic array interfaces) that the same slot is
4356 // processed multiple times (those interfaces have overlapping slots), and it
4357 // will not always be the first pass the one that fills the slot.
4358 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4359 for (i = 0; i < class->interface_offsets_count; i++) {
4363 ic = class->interfaces_packed [i];
4364 ic_offset = mono_class_interface_offset (class, ic);
4366 for (im_index = 0; im_index < ic->method.count; im_index++) {
4367 MonoMethod *im = ic->methods [im_index];
4368 int im_slot = ic_offset + im->slot;
4370 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4373 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4374 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4375 if (vtable [im_slot] == NULL) {
4376 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4383 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4385 for (l = virt_methods; l; l = l->next) {
4388 * If the method is REUSE_SLOT, we must check in the
4389 * base class for a method to override.
4391 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4393 for (k = class->parent; k ; k = k->parent) {
4398 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4399 MonoMethodSignature *cmsig, *m1sig;
4401 cmsig = mono_method_signature (cm);
4402 m1sig = mono_method_signature (m1);
4404 if (!cmsig || !m1sig) {
4405 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4409 if (!strcmp(cm->name, m1->name) &&
4410 mono_metadata_signature_equal (cmsig, m1sig)) {
4412 /* CAS - SecurityAction.InheritanceDemand */
4413 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4414 mono_secman_inheritancedemand_method (cm, m1);
4417 if (mono_security_core_clr_enabled ())
4418 mono_security_core_clr_check_override (class, cm, m1);
4420 slot = mono_method_get_vtable_slot (m1);
4424 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4425 char *body_name = mono_method_full_name (cm, TRUE);
4426 char *decl_name = mono_method_full_name (m1, TRUE);
4427 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));
4433 g_assert (cm->slot < max_vtsize);
4435 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4436 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4437 mono_method_full_name (m1, 1), m1,
4438 mono_method_full_name (cm, 1), cm));
4439 g_hash_table_insert (override_map, m1, cm);
4443 if (k->exception_type)
4453 /*Non final newslot methods must be given a non-interface vtable slot*/
4454 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4458 cm->slot = cur_slot++;
4460 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4461 vtable [cm->slot] = cm;
4464 /* override non interface methods */
4465 for (i = 0; i < onum; i++) {
4466 MonoMethod *decl = overrides [i*2];
4467 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4468 g_assert (decl->slot != -1);
4469 vtable [decl->slot] = overrides [i*2 + 1];
4470 overrides [i * 2 + 1]->slot = decl->slot;
4472 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4473 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4474 mono_method_full_name (decl, 1), decl,
4475 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4476 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4478 if (mono_security_core_clr_enabled ())
4479 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4484 * If a method occupies more than one place in the vtable, and it is
4485 * overriden, then change the other occurances too.
4490 for (i = 0; i < max_vtsize; ++i)
4492 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4494 cm = g_hash_table_lookup (override_map, vtable [i]);
4499 g_hash_table_destroy (override_map);
4500 override_map = NULL;
4503 g_slist_free (virt_methods);
4504 virt_methods = NULL;
4506 /* Ensure that all vtable slots are filled with concrete instance methods */
4507 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4508 for (i = 0; i < cur_slot; ++i) {
4509 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4510 char *type_name = mono_type_get_full_name (class);
4511 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4512 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));
4514 g_free (method_name);
4520 if (class->generic_class) {
4521 MonoClass *gklass = class->generic_class->container_class;
4523 mono_class_init (gklass);
4525 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4527 /* Check that the vtable_size value computed in mono_class_init () is correct */
4528 if (class->vtable_size)
4529 g_assert (cur_slot == class->vtable_size);
4530 class->vtable_size = cur_slot;
4533 /* Try to share the vtable with our parent. */
4534 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4535 mono_memory_barrier ();
4536 class->vtable = class->parent->vtable;
4538 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4539 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4540 mono_memory_barrier ();
4541 class->vtable = tmp;
4544 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4545 if (mono_print_vtable) {
4548 print_implemented_interfaces (class);
4550 for (i = 0; i <= max_iid; i++)
4551 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4554 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4555 class->vtable_size, icount);
4557 for (i = 0; i < cur_slot; ++i) {
4562 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4563 mono_method_full_name (cm, TRUE));
4569 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4570 class->name, max_iid);
4572 for (i = 0; i < class->interface_count; i++) {
4573 ic = class->interfaces [i];
4574 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4575 mono_class_interface_offset (class, ic),
4576 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4579 for (k = class->parent; k ; k = k->parent) {
4580 for (i = 0; i < k->interface_count; i++) {
4581 ic = k->interfaces [i];
4582 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4583 mono_class_interface_offset (class, ic),
4584 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4590 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4595 char *name = mono_type_get_full_name (class);
4596 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4599 g_hash_table_destroy (override_map);
4601 g_slist_free (virt_methods);
4606 * mono_method_get_vtable_slot:
4608 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4609 * LOCKING: Acquires the loader lock.
4611 * FIXME Use proper MonoError machinery here.
4614 mono_method_get_vtable_slot (MonoMethod *method)
4616 if (method->slot == -1) {
4617 mono_class_setup_vtable (method->klass);
4618 if (method->klass->exception_type)
4620 if (method->slot == -1) {
4624 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4625 g_assert (method->klass->generic_class);
4626 gklass = method->klass->generic_class->container_class;
4627 mono_class_setup_methods (method->klass);
4628 g_assert (method->klass->methods);
4629 for (i = 0; i < method->klass->method.count; ++i) {
4630 if (method->klass->methods [i] == method)
4633 g_assert (i < method->klass->method.count);
4634 g_assert (gklass->methods);
4635 method->slot = gklass->methods [i]->slot;
4637 g_assert (method->slot != -1);
4639 return method->slot;
4643 * mono_method_get_vtable_index:
4646 * Returns the index into the runtime vtable to access the method or,
4647 * in the case of a virtual generic method, the virtual generic method
4648 * thunk. Returns -1 on failure.
4650 * FIXME Use proper MonoError machinery here.
4653 mono_method_get_vtable_index (MonoMethod *method)
4655 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4656 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4657 if (imethod->declaring->is_generic)
4658 return mono_method_get_vtable_slot (imethod->declaring);
4660 return mono_method_get_vtable_slot (method);
4663 static MonoMethod *default_ghc = NULL;
4664 static MonoMethod *default_finalize = NULL;
4665 static int finalize_slot = -1;
4666 static int ghc_slot = -1;
4669 initialize_object_slots (MonoClass *class)
4674 if (class == mono_defaults.object_class) {
4675 mono_class_setup_vtable (class);
4676 for (i = 0; i < class->vtable_size; ++i) {
4677 MonoMethod *cm = class->vtable [i];
4679 if (!strcmp (cm->name, "GetHashCode"))
4681 else if (!strcmp (cm->name, "Finalize"))
4685 g_assert (ghc_slot > 0);
4686 default_ghc = class->vtable [ghc_slot];
4688 g_assert (finalize_slot > 0);
4689 default_finalize = class->vtable [finalize_slot];
4694 MonoMethod *array_method;
4696 } GenericArrayMethodInfo;
4698 static int generic_array_method_num = 0;
4699 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4702 generic_array_methods (MonoClass *class)
4704 int i, count_generic = 0;
4705 GList *list = NULL, *tmp;
4706 if (generic_array_method_num)
4707 return generic_array_method_num;
4708 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4709 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4710 for (i = 0; i < class->parent->method.count; i++) {
4711 MonoMethod *m = class->parent->methods [i];
4712 if (!strncmp (m->name, "InternalArray__", 15)) {
4714 list = g_list_prepend (list, m);
4717 list = g_list_reverse (list);
4718 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4720 for (tmp = list; tmp; tmp = tmp->next) {
4721 const char *mname, *iname;
4723 MonoMethod *m = tmp->data;
4724 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4725 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4727 generic_array_method_info [i].array_method = m;
4728 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4729 iname = "System.Collections.Generic.ICollection`1.";
4730 mname = m->name + 27;
4731 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4732 iname = "System.Collections.Generic.IEnumerable`1.";
4733 mname = m->name + 27;
4734 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4735 iname = "System.Collections.Generic.IReadOnlyList`1.";
4736 mname = m->name + strlen (ireadonlylist_prefix);
4737 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4738 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4739 mname = m->name + strlen (ireadonlycollection_prefix);
4740 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4741 iname = "System.Collections.Generic.IList`1.";
4742 mname = m->name + 15;
4744 g_assert_not_reached ();
4747 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4748 strcpy (name, iname);
4749 strcpy (name + strlen (iname), mname);
4750 generic_array_method_info [i].name = name;
4753 /*g_print ("array generic methods: %d\n", count_generic);*/
4755 generic_array_method_num = count_generic;
4757 return generic_array_method_num;
4761 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4763 MonoGenericContext tmp_context;
4766 tmp_context.class_inst = NULL;
4767 tmp_context.method_inst = iface->generic_class->context.class_inst;
4768 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4770 for (i = 0; i < generic_array_method_num; i++) {
4771 MonoMethod *m = generic_array_method_info [i].array_method;
4772 MonoMethod *inflated;
4774 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4775 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4780 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4782 int null_length = strlen ("(null)");
4783 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4784 char *s = mono_image_alloc (image, len);
4787 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4788 g_assert (result == len - 1);
4794 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4796 gpointer exception_data = NULL;
4798 switch (error->exception_type) {
4799 case MONO_EXCEPTION_TYPE_LOAD:
4800 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4803 case MONO_EXCEPTION_MISSING_METHOD:
4804 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4807 case MONO_EXCEPTION_MISSING_FIELD: {
4808 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4809 const char *class_name;
4812 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4814 class_name = error->klass->name;
4816 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4819 g_free ((void*)class_name);
4823 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4826 if (error->ref_only)
4827 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.";
4829 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4831 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4835 case MONO_EXCEPTION_BAD_IMAGE:
4836 exception_data = error->msg;
4840 g_assert_not_reached ();
4843 mono_class_set_failure (class, error->exception_type, exception_data);
4848 * @class: the class to initialize
4850 * Compute the instance_size, class_size and other infos that cannot be
4851 * computed at mono_class_get() time. Also compute vtable_size if possible.
4852 * Returns TRUE on success or FALSE if there was a problem in loading
4853 * the type (incorrect assemblies, missing assemblies, methods, etc).
4855 * LOCKING: Acquires the loader lock.
4858 mono_class_init (MonoClass *class)
4861 MonoCachedClassInfo cached_info;
4862 gboolean has_cached_info;
4866 /* Double-checking locking pattern */
4867 if (class->inited || class->exception_type)
4868 return class->exception_type == MONO_EXCEPTION_NONE;
4870 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4872 /* We do everything inside the lock to prevent races */
4873 mono_loader_lock ();
4875 if (class->inited || class->exception_type) {
4876 mono_loader_unlock ();
4877 /* Somebody might have gotten in before us */
4878 return class->exception_type == MONO_EXCEPTION_NONE;
4881 if (class->init_pending) {
4882 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4886 class->init_pending = 1;
4888 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4889 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4894 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4895 MonoClass *element_class = class->element_class;
4896 if (!element_class->inited)
4897 mono_class_init (element_class);
4898 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4899 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4904 /* CAS - SecurityAction.InheritanceDemand */
4905 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4906 mono_secman_inheritancedemand_class (class, class->parent);
4909 mono_stats.initialized_class_count++;
4911 if (class->generic_class && !class->generic_class->is_dynamic) {
4912 MonoClass *gklass = class->generic_class->container_class;
4914 mono_stats.generic_class_count++;
4916 class->method = gklass->method;
4917 class->field = gklass->field;
4919 mono_class_init (gklass);
4920 // FIXME: Why is this needed ?
4921 if (!gklass->exception_type)
4922 mono_class_setup_methods (gklass);
4923 if (gklass->exception_type) {
4924 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4928 if (MONO_CLASS_IS_INTERFACE (class))
4929 class->interface_id = mono_get_unique_iid (class);
4932 if (class->parent && !class->parent->inited)
4933 mono_class_init (class->parent);
4935 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
4937 if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
4938 class->nested_classes_inited = TRUE;
4941 * Computes the size used by the fields, and their locations
4943 if (has_cached_info) {
4944 class->instance_size = cached_info.instance_size;
4945 class->sizes.class_size = cached_info.class_size;
4946 class->packing_size = cached_info.packing_size;
4947 class->min_align = cached_info.min_align;
4948 class->blittable = cached_info.blittable;
4949 class->has_references = cached_info.has_references;
4950 class->has_static_refs = cached_info.has_static_refs;
4951 class->no_special_static_fields = cached_info.no_special_static_fields;
4954 if (!class->size_inited){
4955 mono_class_setup_fields (class);
4956 if (class->exception_type || mono_loader_get_last_error ())
4960 /* Initialize arrays */
4962 class->method.count = 3 + (class->rank > 1? 2: 1);
4964 if (class->interface_count) {
4965 int count_generic = generic_array_methods (class);
4966 class->method.count += class->interface_count * count_generic;
4970 mono_class_setup_supertypes (class);
4973 initialize_object_slots (class);
4976 * Initialize the rest of the data without creating a generic vtable if possible.
4977 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4978 * also avoid computing a generic vtable.
4980 if (has_cached_info) {
4982 class->vtable_size = cached_info.vtable_size;
4983 class->has_finalize = cached_info.has_finalize;
4984 class->has_finalize_inited = TRUE;
4985 class->ghcimpl = cached_info.ghcimpl;
4986 class->has_cctor = cached_info.has_cctor;
4987 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
4988 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4989 * The first slot if for array with.
4991 static int szarray_vtable_size[2] = { 0 };
4993 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
4996 if (!szarray_vtable_size [slot]) {
4997 mono_class_setup_vtable (class);
4998 szarray_vtable_size [slot] = class->vtable_size;
5000 class->vtable_size = szarray_vtable_size[slot];
5002 class->has_finalize_inited = TRUE;
5003 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5004 MonoClass *gklass = class->generic_class->container_class;
5006 /* Generic instance case */
5007 class->ghcimpl = gklass->ghcimpl;
5008 class->has_finalize = mono_class_has_finalizer (gklass);
5009 class->has_finalize_inited = TRUE;
5010 class->has_cctor = gklass->has_cctor;
5012 mono_class_setup_vtable (gklass);
5013 if (gklass->exception_type) {
5014 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5018 class->vtable_size = gklass->vtable_size;
5022 /* ghcimpl is not currently used
5024 if (class->parent) {
5025 MonoMethod *cmethod = class->vtable [ghc_slot];
5026 if (cmethod->is_inflated)
5027 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5028 if (cmethod == default_ghc) {
5034 /* C# doesn't allow interfaces to have cctors */
5035 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5036 MonoMethod *cmethod = NULL;
5038 if (class->type_token) {
5039 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5040 /* The find_method function ignores the 'flags' argument */
5041 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5042 class->has_cctor = 1;
5044 mono_class_setup_methods (class);
5045 if (class->exception_type)
5048 for (i = 0; i < class->method.count; ++i) {
5049 MonoMethod *method = class->methods [i];
5050 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5051 (strcmp (".cctor", method->name) == 0)) {
5052 class->has_cctor = 1;
5060 if (class->parent) {
5061 int first_iface_slot;
5062 /* This will compute class->parent->vtable_size for some classes */
5063 mono_class_init (class->parent);
5064 if (class->parent->exception_type) {
5065 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5068 if (mono_loader_get_last_error ())
5070 if (!class->parent->vtable_size) {
5071 /* FIXME: Get rid of this somehow */
5072 mono_class_setup_vtable (class->parent);
5073 if (class->parent->exception_type) {
5074 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5077 if (mono_loader_get_last_error ())
5080 first_iface_slot = class->parent->vtable_size;
5081 if (mono_class_need_stelemref_method (class))
5083 setup_interface_offsets (class, first_iface_slot, TRUE);
5085 setup_interface_offsets (class, 0, TRUE);
5088 if (mono_security_core_clr_enabled ())
5089 mono_security_core_clr_check_inheritance (class);
5091 if (mono_loader_get_last_error ()) {
5092 if (class->exception_type == MONO_EXCEPTION_NONE) {
5093 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5095 mono_loader_clear_error ();
5098 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5099 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5104 /* Because of the double-checking locking pattern */
5105 mono_memory_barrier ();
5107 class->init_pending = 0;
5109 mono_loader_unlock ();
5111 if (mono_debugger_class_init_func)
5112 mono_debugger_class_init_func (class);
5114 return class->exception_type == MONO_EXCEPTION_NONE;
5118 * mono_class_has_finalizer:
5120 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5124 mono_class_has_finalizer (MonoClass *klass)
5126 if (!klass->has_finalize_inited) {
5127 MonoClass *class = klass;
5129 mono_loader_lock ();
5131 /* Interfaces and valuetypes are not supposed to have finalizers */
5132 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5133 MonoMethod *cmethod = NULL;
5135 if (class->parent && class->parent->has_finalize) {
5136 class->has_finalize = 1;
5138 if (class->parent) {
5140 * Can't search in metadata for a method named Finalize, because that
5141 * ignores overrides.
5143 mono_class_setup_vtable (class);
5144 if (class->exception_type || mono_loader_get_last_error ())
5146 cmethod = class->vtable [finalize_slot];
5150 g_assert (class->vtable_size > finalize_slot);
5152 class->has_finalize = 0;
5153 if (class->parent) {
5154 if (cmethod->is_inflated)
5155 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5156 if (cmethod != default_finalize) {
5157 class->has_finalize = 1;
5164 mono_memory_barrier ();
5165 klass->has_finalize_inited = TRUE;
5167 mono_loader_unlock ();
5170 return klass->has_finalize;
5173 mono_loader_unlock ();
5178 mono_is_corlib_image (MonoImage *image)
5180 /* FIXME: allow the dynamic case for our compilers and with full trust */
5182 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5184 return image == mono_defaults.corlib;
5188 * LOCKING: this assumes the loader lock is held
5191 mono_class_setup_mono_type (MonoClass *class)
5193 const char *name = class->name;
5194 const char *nspace = class->name_space;
5195 gboolean is_corlib = mono_is_corlib_image (class->image);
5197 class->this_arg.byref = 1;
5198 class->this_arg.data.klass = class;
5199 class->this_arg.type = MONO_TYPE_CLASS;
5200 class->byval_arg.data.klass = class;
5201 class->byval_arg.type = MONO_TYPE_CLASS;
5203 if (is_corlib && !strcmp (nspace, "System")) {
5204 if (!strcmp (name, "ValueType")) {
5206 * do not set the valuetype bit for System.ValueType.
5207 * class->valuetype = 1;
5209 class->blittable = TRUE;
5210 } else if (!strcmp (name, "Enum")) {
5212 * do not set the valuetype bit for System.Enum.
5213 * class->valuetype = 1;
5215 class->valuetype = 0;
5216 class->enumtype = 0;
5217 } else if (!strcmp (name, "Object")) {
5218 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5219 } else if (!strcmp (name, "String")) {
5220 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5221 } else if (!strcmp (name, "TypedReference")) {
5222 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5226 if (class->valuetype) {
5227 int t = MONO_TYPE_VALUETYPE;
5229 if (is_corlib && !strcmp (nspace, "System")) {
5232 if (!strcmp (name, "Boolean")) {
5233 t = MONO_TYPE_BOOLEAN;
5234 } else if (!strcmp(name, "Byte")) {
5236 class->blittable = TRUE;
5240 if (!strcmp (name, "Char")) {
5245 if (!strcmp (name, "Double")) {
5247 class->blittable = TRUE;
5251 if (!strcmp (name, "Int32")) {
5253 class->blittable = TRUE;
5254 } else if (!strcmp(name, "Int16")) {
5256 class->blittable = TRUE;
5257 } else if (!strcmp(name, "Int64")) {
5259 class->blittable = TRUE;
5260 } else if (!strcmp(name, "IntPtr")) {
5262 class->blittable = TRUE;
5266 if (!strcmp (name, "Single")) {
5268 class->blittable = TRUE;
5269 } else if (!strcmp(name, "SByte")) {
5271 class->blittable = TRUE;
5275 if (!strcmp (name, "UInt32")) {
5277 class->blittable = TRUE;
5278 } else if (!strcmp(name, "UInt16")) {
5280 class->blittable = TRUE;
5281 } else if (!strcmp(name, "UInt64")) {
5283 class->blittable = TRUE;
5284 } else if (!strcmp(name, "UIntPtr")) {
5286 class->blittable = TRUE;
5290 if (!strcmp (name, "TypedReference")) {
5291 t = MONO_TYPE_TYPEDBYREF;
5292 class->blittable = TRUE;
5296 if (!strcmp (name, "Void")) {
5304 class->this_arg.type = class->byval_arg.type = t;
5307 if (MONO_CLASS_IS_INTERFACE (class))
5308 class->interface_id = mono_get_unique_iid (class);
5314 * COM initialization (using mono_init_com_types) is delayed until needed.
5315 * However when a [ComImport] attribute is present on a type it will trigger
5316 * the initialization. This is not a problem unless the BCL being executed
5317 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5320 init_com_from_comimport (MonoClass *class)
5322 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5323 if (mono_security_core_clr_enabled ()) {
5324 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5325 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5326 /* but it can not be made available for application (i.e. user code) since all COM calls
5327 * are considered native calls. In this case we fail with a TypeLoadException (just like
5328 * Silverlight 2 does */
5329 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5334 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5335 mono_init_com_types ();
5337 #endif /*DISABLE_COM*/
5340 * LOCKING: this assumes the loader lock is held
5343 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5345 gboolean system_namespace;
5346 gboolean is_corlib = mono_is_corlib_image (class->image);
5348 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5350 /* if root of the hierarchy */
5351 if (system_namespace && !strcmp (class->name, "Object")) {
5352 class->parent = NULL;
5353 class->instance_size = sizeof (MonoObject);
5356 if (!strcmp (class->name, "<Module>")) {
5357 class->parent = NULL;
5358 class->instance_size = 0;
5362 if (!MONO_CLASS_IS_INTERFACE (class)) {
5363 /* Imported COM Objects always derive from __ComObject. */
5365 if (MONO_CLASS_IS_IMPORT (class)) {
5366 init_com_from_comimport (class);
5367 if (parent == mono_defaults.object_class)
5368 parent = mono_defaults.com_object_class;
5372 /* set the parent to something useful and safe, but mark the type as broken */
5373 parent = mono_defaults.object_class;
5374 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5377 class->parent = parent;
5379 if (parent->generic_class && !parent->name) {
5381 * If the parent is a generic instance, we may get
5382 * called before it is fully initialized, especially
5383 * before it has its name.
5388 #ifndef DISABLE_REMOTING
5389 class->marshalbyref = parent->marshalbyref;
5390 class->contextbound = parent->contextbound;
5393 class->delegate = parent->delegate;
5395 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5396 mono_class_set_is_com_object (class);
5398 if (system_namespace) {
5399 #ifndef DISABLE_REMOTING
5400 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5401 class->marshalbyref = 1;
5403 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5404 class->contextbound = 1;
5406 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5407 class->delegate = 1;
5410 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5411 (strcmp (class->parent->name_space, "System") == 0)))
5412 class->valuetype = 1;
5413 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5414 class->valuetype = class->enumtype = 1;
5416 /*class->enumtype = class->parent->enumtype; */
5418 /* initialize com types if COM interfaces are present */
5420 if (MONO_CLASS_IS_IMPORT (class))
5421 init_com_from_comimport (class);
5423 class->parent = NULL;
5429 * mono_class_setup_supertypes:
5432 * Build the data structure needed to make fast type checks work.
5433 * This currently sets two fields in @class:
5434 * - idepth: distance between @class and System.Object in the type
5436 * - supertypes: array of classes: each element has a class in the hierarchy
5437 * starting from @class up to System.Object
5439 * LOCKING: this assumes the loader lock is held
5442 mono_class_setup_supertypes (MonoClass *class)
5445 MonoClass **supertypes;
5447 if (class->supertypes)
5450 if (class->parent && !class->parent->supertypes)
5451 mono_class_setup_supertypes (class->parent);
5453 class->idepth = class->parent->idepth + 1;
5457 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5458 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5460 if (class->parent) {
5461 supertypes [class->idepth - 1] = class;
5462 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5464 supertypes [0] = class;
5467 mono_atomic_store_release (&class->supertypes, supertypes);
5471 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5473 MonoClass *gtd = (MonoClass*)user_data;
5474 /* Only try to fix generic instances of @gtd */
5475 if (gclass->generic_class->container_class != gtd)
5478 /* Check if the generic instance has no parent. */
5479 if (gtd->parent && !gclass->parent)
5480 mono_generic_class_setup_parent (gclass, gtd);
5486 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5488 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5489 mono_error_set_type_load_class (error, class, msg);
5493 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5495 MonoLoaderError *lerror = mono_loader_get_last_error ();
5498 set_failure_from_loader_error (class, lerror);
5499 mono_error_set_from_loader_error (error);
5503 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5504 mono_error_set_type_load_class (error, class, msg);
5509 * mono_class_create_from_typedef:
5510 * @image: image where the token is valid
5511 * @type_token: typedef token
5512 * @error: used to return any error found while creating the type
5514 * Create the MonoClass* representing the specified type token.
5515 * @type_token must be a TypeDef token.
5517 * FIXME: don't return NULL on failure, just the the caller figure it out.
5520 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5522 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5523 MonoClass *class, *parent = NULL;
5524 guint32 cols [MONO_TYPEDEF_SIZE];
5525 guint32 cols_next [MONO_TYPEDEF_SIZE];
5526 guint tidx = mono_metadata_token_index (type_token);
5527 MonoGenericContext *context = NULL;
5528 const char *name, *nspace;
5530 MonoClass **interfaces;
5531 guint32 field_last, method_last;
5532 guint32 nesting_tokeen;
5534 mono_error_init (error);
5536 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5537 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5538 g_assert (!mono_loader_get_last_error ());
5542 mono_loader_lock ();
5544 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5545 mono_loader_unlock ();
5546 g_assert (!mono_loader_get_last_error ());
5550 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5552 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5553 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5555 class = mono_image_alloc0 (image, sizeof (MonoClass));
5558 class->name_space = nspace;
5560 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5562 class->image = image;
5563 class->type_token = type_token;
5564 class->flags = cols [MONO_TYPEDEF_FLAGS];
5566 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5568 classes_size += sizeof (MonoClass);
5571 * Check whether we're a generic type definition.
5573 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5574 if (class->generic_container) {
5575 class->is_generic = 1;
5576 class->generic_container->owner.klass = class;
5577 context = &class->generic_container->context;
5580 if (class->generic_container)
5581 enable_gclass_recording ();
5583 if (cols [MONO_TYPEDEF_EXTENDS]) {
5585 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5587 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5588 /*WARNING: this must satisfy mono_metadata_type_hash*/
5589 class->this_arg.byref = 1;
5590 class->this_arg.data.klass = class;
5591 class->this_arg.type = MONO_TYPE_CLASS;
5592 class->byval_arg.data.klass = class;
5593 class->byval_arg.type = MONO_TYPE_CLASS;
5595 parent = mono_class_get_full (image, parent_token, context);
5597 if (parent == NULL) {
5598 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5599 goto parent_failure;
5602 for (tmp = parent; tmp; tmp = tmp->parent) {
5604 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5605 goto parent_failure;
5607 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5608 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5609 goto parent_failure;
5614 mono_class_setup_parent (class, parent);
5616 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5617 mono_class_setup_mono_type (class);
5619 if (class->generic_container)
5620 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5623 * This might access class->byval_arg for recursion generated by generic constraints,
5624 * so it has to come after setup_mono_type ().
5626 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5627 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5628 if (!mono_error_ok (error)) {
5629 /*FIXME implement a mono_class_set_failure_from_mono_error */
5630 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5631 mono_loader_unlock ();
5632 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5633 g_assert (!mono_loader_get_last_error ());
5638 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5642 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5646 class->cast_class = class->element_class = class;
5648 if (!class->enumtype) {
5649 if (!mono_metadata_interfaces_from_typedef_full (
5650 image, type_token, &interfaces, &icount, FALSE, context)){
5651 mono_class_set_failure_and_error (class, error, g_strdup ("Could not load interfaces"));
5652 mono_loader_unlock ();
5653 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5654 g_assert (!mono_loader_get_last_error ());
5658 class->interfaces = interfaces;
5659 class->interface_count = icount;
5660 class->interfaces_inited = 1;
5663 /*g_print ("Load class %s\n", name);*/
5666 * Compute the field and method lists
5668 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5669 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5671 if (tt->rows > tidx){
5672 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5673 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5674 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5676 field_last = image->tables [MONO_TABLE_FIELD].rows;
5677 method_last = image->tables [MONO_TABLE_METHOD].rows;
5680 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5681 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5682 class->field.count = field_last - class->field.first;
5684 class->field.count = 0;
5686 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5687 class->method.count = method_last - class->method.first;
5689 class->method.count = 0;
5691 /* reserve space to store vector pointer in arrays */
5692 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5693 class->instance_size += 2 * sizeof (gpointer);
5694 g_assert (class->field.count == 0);
5697 if (class->enumtype) {
5698 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5699 if (!enum_basetype) {
5700 /*set it to a default value as the whole runtime can't handle this to be null*/
5701 class->cast_class = class->element_class = mono_defaults.int32_class;
5702 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5703 mono_loader_unlock ();
5704 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5705 g_assert (!mono_loader_get_last_error ());
5708 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5712 * If we're a generic type definition, load the constraints.
5713 * We must do this after the class has been constructed to make certain recursive scenarios
5716 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5717 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5718 mono_loader_unlock ();
5719 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5720 g_assert (!mono_loader_get_last_error ());
5724 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5725 if (!strncmp (name, "Vector", 6))
5726 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");
5729 mono_loader_unlock ();
5731 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5732 g_assert (!mono_loader_get_last_error ());
5737 mono_class_setup_mono_type (class);
5738 mono_loader_unlock ();
5739 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5740 g_assert (!mono_loader_get_last_error ());
5744 /** is klass Nullable<T>? */
5746 mono_class_is_nullable (MonoClass *klass)
5748 return klass->generic_class != NULL &&
5749 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5753 /** if klass is T? return T */
5755 mono_class_get_nullable_param (MonoClass *klass)
5757 g_assert (mono_class_is_nullable (klass));
5758 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5762 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5766 MonoGenericClass *gclass = klass->generic_class;
5768 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5769 if (!mono_error_ok (&error)) {
5770 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5771 klass->parent = mono_defaults.object_class;
5772 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5773 mono_error_cleanup (&error);
5777 mono_class_setup_parent (klass, klass->parent);
5779 if (klass->enumtype) {
5780 klass->cast_class = gtd->cast_class;
5781 klass->element_class = gtd->element_class;
5787 * Create the `MonoClass' for an instantiation of a generic type.
5788 * We only do this if we actually need it.
5791 mono_generic_class_get_class (MonoGenericClass *gclass)
5793 MonoClass *klass, *gklass;
5795 if (gclass->cached_class)
5796 return gclass->cached_class;
5798 mono_loader_lock ();
5799 if (gclass->cached_class) {
5800 mono_loader_unlock ();
5801 return gclass->cached_class;
5804 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5806 gklass = gclass->container_class;
5808 if (record_gclass_instantiation > 0)
5809 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5811 if (gklass->nested_in) {
5812 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5813 klass->nested_in = gklass->nested_in;
5816 klass->name = gklass->name;
5817 klass->name_space = gklass->name_space;
5819 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5821 klass->image = gklass->image;
5822 klass->flags = gklass->flags;
5823 klass->type_token = gklass->type_token;
5824 klass->field.count = gklass->field.count;
5826 klass->is_inflated = 1;
5827 klass->generic_class = gclass;
5829 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5830 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5831 klass->this_arg.byref = TRUE;
5832 klass->enumtype = gklass->enumtype;
5833 klass->valuetype = gklass->valuetype;
5835 klass->cast_class = klass->element_class = klass;
5837 if (mono_class_is_nullable (klass))
5838 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5841 * We're not interested in the nested classes of a generic instance.
5842 * We use the generic type definition to look for nested classes.
5845 mono_generic_class_setup_parent (klass, gklass);
5847 if (gclass->is_dynamic) {
5850 mono_class_setup_supertypes (klass);
5852 if (klass->enumtype) {
5854 * For enums, gklass->fields might not been set, but instance_size etc. is
5855 * already set in mono_reflection_create_internal_class (). For non-enums,
5856 * these will be computed normally in mono_class_layout_fields ().
5858 klass->instance_size = gklass->instance_size;
5859 klass->sizes.class_size = gklass->sizes.class_size;
5860 mono_memory_barrier ();
5861 klass->size_inited = 1;
5865 mono_memory_barrier ();
5866 gclass->cached_class = klass;
5868 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5870 inflated_classes ++;
5871 inflated_classes_size += sizeof (MonoClass);
5873 mono_loader_unlock ();
5879 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5881 MonoClass *klass, **ptr;
5883 MonoGenericContainer *container = mono_generic_param_owner (param);
5887 image = mono_defaults.corlib;
5889 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5890 classes_size += sizeof (MonoClass);
5893 klass->name = pinfo->name;
5895 int n = mono_generic_param_num (param);
5896 klass->name = mono_image_alloc0 (image, 16);
5897 sprintf ((char*)klass->name, "%d", n);
5902 MonoMethod *omethod = container->owner.method;
5903 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5905 MonoClass *oklass = container->owner.klass;
5906 klass->name_space = oklass ? oklass->name_space : "";
5909 klass->name_space = "";
5912 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5916 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5920 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5921 klass->parent = pinfo->constraints [0];
5923 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5924 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5926 klass->parent = mono_defaults.object_class;
5929 if (count - pos > 0) {
5930 klass->interface_count = count - pos;
5931 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5932 klass->interfaces_inited = TRUE;
5933 for (i = pos; i < count; i++)
5934 klass->interfaces [i - pos] = pinfo->constraints [i];
5937 klass->image = image;
5939 klass->inited = TRUE;
5940 klass->cast_class = klass->element_class = klass;
5941 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5943 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5944 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5945 klass->this_arg.byref = TRUE;
5947 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5948 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5950 /*Init these fields to sane values*/
5951 klass->min_align = 1;
5952 klass->instance_size = sizeof (gpointer);
5953 mono_memory_barrier ();
5954 klass->size_inited = 1;
5956 mono_class_setup_supertypes (klass);
5958 if (count - pos > 0) {
5959 mono_class_setup_vtable (klass->parent);
5960 if (klass->parent->exception_type)
5961 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
5963 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
5969 #define FAST_CACHE_SIZE 16
5972 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
5974 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
5975 MonoImage *image = param->image;
5980 if (n < FAST_CACHE_SIZE) {
5982 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
5984 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
5986 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
5987 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
5992 * LOCKING: Acquires the loader lock.
5995 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
5997 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
5998 MonoImage *image = param->image;
6003 if (n < FAST_CACHE_SIZE) {
6005 /* No locking needed */
6006 if (!image->mvar_cache_fast)
6007 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6008 image->mvar_cache_fast [n] = klass;
6010 if (!image->var_cache_fast)
6011 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6012 image->var_cache_fast [n] = klass;
6016 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6018 mono_loader_lock ();
6019 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6021 ht = g_hash_table_new (NULL, NULL);
6022 mono_memory_barrier ();
6024 image->mvar_cache_slow = ht;
6026 image->var_cache_slow = ht;
6028 mono_loader_unlock ();
6031 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6035 * LOCKING: Acquires the loader lock.
6038 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6040 MonoGenericContainer *container = mono_generic_param_owner (param);
6041 MonoGenericParamInfo *pinfo;
6044 mono_loader_lock ();
6047 pinfo = mono_generic_param_info (param);
6048 if (pinfo->pklass) {
6049 mono_loader_unlock ();
6050 return pinfo->pklass;
6056 klass = get_anon_gparam_class (param, is_mvar);
6058 mono_loader_unlock ();
6063 if (!image && container) {
6065 MonoMethod *method = container->owner.method;
6066 image = (method && method->klass) ? method->klass->image : NULL;
6068 MonoClass *klass = container->owner.klass;
6069 // FIXME: 'klass' should not be null
6070 // But, monodis creates GenericContainers without associating a owner to it
6071 image = klass ? klass->image : NULL;
6075 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6077 mono_memory_barrier ();
6080 pinfo->pklass = klass;
6082 set_anon_gparam_class (param, is_mvar, klass);
6084 mono_loader_unlock ();
6086 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6087 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6093 mono_ptr_class_get (MonoType *type)
6096 MonoClass *el_class;
6100 el_class = mono_class_from_mono_type (type);
6101 image = el_class->image;
6103 mono_loader_lock ();
6105 if (!image->ptr_cache)
6106 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6108 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6109 mono_loader_unlock ();
6112 result = mono_image_alloc0 (image, sizeof (MonoClass));
6114 classes_size += sizeof (MonoClass);
6116 result->parent = NULL; /* no parent for PTR types */
6117 result->name_space = el_class->name_space;
6118 name = g_strdup_printf ("%s*", el_class->name);
6119 result->name = mono_image_strdup (image, name);
6122 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6124 result->image = el_class->image;
6125 result->inited = TRUE;
6126 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6127 /* Can pointers get boxed? */
6128 result->instance_size = sizeof (gpointer);
6129 result->cast_class = result->element_class = el_class;
6130 result->blittable = TRUE;
6132 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6133 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6134 result->this_arg.byref = TRUE;
6136 mono_class_setup_supertypes (result);
6138 g_hash_table_insert (image->ptr_cache, el_class, result);
6140 mono_loader_unlock ();
6142 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6148 mono_fnptr_class_get (MonoMethodSignature *sig)
6151 static GHashTable *ptr_hash = NULL;
6153 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6155 mono_loader_lock ();
6158 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6160 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6161 mono_loader_unlock ();
6164 result = g_new0 (MonoClass, 1);
6166 result->parent = NULL; /* no parent for PTR types */
6167 result->name_space = "System";
6168 result->name = "MonoFNPtrFakeClass";
6170 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6172 result->image = mono_defaults.corlib; /* need to fix... */
6173 result->inited = TRUE;
6174 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6175 /* Can pointers get boxed? */
6176 result->instance_size = sizeof (gpointer);
6177 result->cast_class = result->element_class = result;
6178 result->blittable = TRUE;
6180 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6181 result->this_arg.data.method = result->byval_arg.data.method = sig;
6182 result->this_arg.byref = TRUE;
6183 result->blittable = TRUE;
6185 mono_class_setup_supertypes (result);
6187 g_hash_table_insert (ptr_hash, sig, result);
6189 mono_loader_unlock ();
6191 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6197 mono_class_from_mono_type (MonoType *type)
6199 switch (type->type) {
6200 case MONO_TYPE_OBJECT:
6201 return type->data.klass? type->data.klass: mono_defaults.object_class;
6202 case MONO_TYPE_VOID:
6203 return type->data.klass? type->data.klass: mono_defaults.void_class;
6204 case MONO_TYPE_BOOLEAN:
6205 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6206 case MONO_TYPE_CHAR:
6207 return type->data.klass? type->data.klass: mono_defaults.char_class;
6209 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6211 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6213 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6215 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6217 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6219 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6221 return type->data.klass? type->data.klass: mono_defaults.int_class;
6223 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6225 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6227 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6229 return type->data.klass? type->data.klass: mono_defaults.single_class;
6231 return type->data.klass? type->data.klass: mono_defaults.double_class;
6232 case MONO_TYPE_STRING:
6233 return type->data.klass? type->data.klass: mono_defaults.string_class;
6234 case MONO_TYPE_TYPEDBYREF:
6235 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6236 case MONO_TYPE_ARRAY:
6237 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6239 return mono_ptr_class_get (type->data.type);
6240 case MONO_TYPE_FNPTR:
6241 return mono_fnptr_class_get (type->data.method);
6242 case MONO_TYPE_SZARRAY:
6243 return mono_array_class_get (type->data.klass, 1);
6244 case MONO_TYPE_CLASS:
6245 case MONO_TYPE_VALUETYPE:
6246 return type->data.klass;
6247 case MONO_TYPE_GENERICINST:
6248 return mono_generic_class_get_class (type->data.generic_class);
6250 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6251 case MONO_TYPE_MVAR:
6252 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6254 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6255 g_assert_not_reached ();
6262 * mono_type_retrieve_from_typespec
6263 * @image: context where the image is created
6264 * @type_spec: typespec token
6265 * @context: the generic context used to evaluate generic instantiations in
6268 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6270 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6272 mono_error_init (error);
6273 *did_inflate = FALSE;
6276 char *name = mono_class_name_from_token (image, type_spec);
6277 char *assembly = mono_assembly_name_from_token (image, type_spec);
6278 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6282 if (context && (context->class_inst || context->method_inst)) {
6283 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6285 if (!mono_error_ok (error))
6290 *did_inflate = TRUE;
6297 * mono_class_create_from_typespec
6298 * @image: context where the image is created
6299 * @type_spec: typespec token
6300 * @context: the generic context used to evaluate generic instantiations in
6303 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6306 gboolean inflated = FALSE;
6307 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6308 if (!mono_error_ok (error))
6310 ret = mono_class_from_mono_type (t);
6312 mono_metadata_free_type (t);
6317 * mono_bounded_array_class_get:
6318 * @element_class: element class
6319 * @rank: the dimension of the array class
6320 * @bounded: whenever the array has non-zero bounds
6322 * Returns: a class object describing the array with element type @element_type and
6326 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6330 MonoClass *parent = NULL;
6331 GSList *list, *rootlist = NULL;
6334 gboolean corlib_type = FALSE;
6336 g_assert (rank <= 255);
6339 /* bounded only matters for one-dimensional arrays */
6342 image = eclass->image;
6344 if (rank == 1 && !bounded) {
6346 * This case is very frequent not just during compilation because of calls
6347 * from mono_class_from_mono_type (), mono_array_new (),
6348 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6350 EnterCriticalSection (&image->szarray_cache_lock);
6351 if (!image->szarray_cache)
6352 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6353 class = g_hash_table_lookup (image->szarray_cache, eclass);
6354 LeaveCriticalSection (&image->szarray_cache_lock);
6358 mono_loader_lock ();
6360 mono_loader_lock ();
6362 if (!image->array_cache)
6363 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6365 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6366 for (; list; list = list->next) {
6368 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6369 mono_loader_unlock ();
6376 /* for the building corlib use System.Array from it */
6377 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6378 parent = mono_class_from_name (image, "System", "Array");
6381 parent = mono_defaults.array_class;
6382 if (!parent->inited)
6383 mono_class_init (parent);
6386 class = mono_image_alloc0 (image, sizeof (MonoClass));
6388 class->image = image;
6389 class->name_space = eclass->name_space;
6390 nsize = strlen (eclass->name);
6391 name = g_malloc (nsize + 2 + rank + 1);
6392 memcpy (name, eclass->name, nsize);
6395 memset (name + nsize + 1, ',', rank - 1);
6397 name [nsize + rank] = '*';
6398 name [nsize + rank + bounded] = ']';
6399 name [nsize + rank + bounded + 1] = 0;
6400 class->name = mono_image_strdup (image, name);
6403 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6405 classes_size += sizeof (MonoClass);
6407 class->type_token = 0;
6408 /* all arrays are marked serializable and sealed, bug #42779 */
6409 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6410 class->parent = parent;
6411 class->instance_size = mono_class_instance_size (class->parent);
6413 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6414 /*Arrays of those two types are invalid.*/
6415 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6416 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6417 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6418 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6419 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6421 /* element_size -1 is ok as this is not an instantitable type*/
6422 class->sizes.element_size = -1;
6424 class->sizes.element_size = mono_class_array_element_size (eclass);
6426 mono_class_setup_supertypes (class);
6428 if (eclass->generic_class)
6429 mono_class_init (eclass);
6430 if (!eclass->size_inited)
6431 mono_class_setup_fields (eclass);
6432 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6433 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6435 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6439 if (eclass->enumtype)
6440 class->cast_class = eclass->element_class;
6442 class->cast_class = eclass;
6444 switch (class->cast_class->byval_arg.type) {
6446 class->cast_class = mono_defaults.byte_class;
6449 class->cast_class = mono_defaults.int16_class;
6452 #if SIZEOF_VOID_P == 4
6456 class->cast_class = mono_defaults.int32_class;
6459 #if SIZEOF_VOID_P == 8
6463 class->cast_class = mono_defaults.int64_class;
6467 class->element_class = eclass;
6469 if ((rank > 1) || bounded) {
6470 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6471 class->byval_arg.type = MONO_TYPE_ARRAY;
6472 class->byval_arg.data.array = at;
6473 at->eklass = eclass;
6475 /* FIXME: complete.... */
6477 class->byval_arg.type = MONO_TYPE_SZARRAY;
6478 class->byval_arg.data.klass = eclass;
6480 class->this_arg = class->byval_arg;
6481 class->this_arg.byref = 1;
6486 class->generic_container = eclass->generic_container;
6488 if (rank == 1 && !bounded) {
6489 MonoClass *prev_class;
6491 EnterCriticalSection (&image->szarray_cache_lock);
6492 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6494 /* Someone got in before us */
6497 g_hash_table_insert (image->szarray_cache, eclass, class);
6498 LeaveCriticalSection (&image->szarray_cache_lock);
6500 list = g_slist_append (rootlist, class);
6501 g_hash_table_insert (image->array_cache, eclass, list);
6504 mono_loader_unlock ();
6506 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6512 * mono_array_class_get:
6513 * @element_class: element class
6514 * @rank: the dimension of the array class
6516 * Returns: a class object describing the array with element type @element_type and
6520 mono_array_class_get (MonoClass *eclass, guint32 rank)
6522 return mono_bounded_array_class_get (eclass, rank, FALSE);
6526 * mono_class_instance_size:
6529 * Returns: the size of an object instance
6532 mono_class_instance_size (MonoClass *klass)
6534 if (!klass->size_inited)
6535 mono_class_init (klass);
6537 return klass->instance_size;
6541 * mono_class_min_align:
6544 * Returns: minimm alignment requirements
6547 mono_class_min_align (MonoClass *klass)
6549 if (!klass->size_inited)
6550 mono_class_init (klass);
6552 return klass->min_align;
6556 * mono_class_value_size:
6559 * This function is used for value types, and return the
6560 * space and the alignment to store that kind of value object.
6562 * Returns: the size of a value of kind @klass
6565 mono_class_value_size (MonoClass *klass, guint32 *align)
6569 /* fixme: check disable, because we still have external revereces to
6570 * mscorlib and Dummy Objects
6572 /*g_assert (klass->valuetype);*/
6574 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6577 *align = klass->min_align;
6583 * mono_class_data_size:
6586 * Returns: the size of the static class data
6589 mono_class_data_size (MonoClass *klass)
6592 mono_class_init (klass);
6594 /* in arrays, sizes.class_size is unioned with element_size
6595 * and arrays have no static fields
6599 return klass->sizes.class_size;
6603 * Auxiliary routine to mono_class_get_field
6605 * Takes a field index instead of a field token.
6607 static MonoClassField *
6608 mono_class_get_field_idx (MonoClass *class, int idx)
6610 mono_class_setup_fields_locking (class);
6611 if (class->exception_type)
6615 if (class->image->uncompressed_metadata) {
6617 * class->field.first points to the FieldPtr table, while idx points into the
6618 * Field table, so we have to do a search.
6620 /*FIXME this is broken for types with multiple fields with the same name.*/
6621 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6624 for (i = 0; i < class->field.count; ++i)
6625 if (mono_field_get_name (&class->fields [i]) == name)
6626 return &class->fields [i];
6627 g_assert_not_reached ();
6629 if (class->field.count) {
6630 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6631 return &class->fields [idx - class->field.first];
6635 class = class->parent;
6641 * mono_class_get_field:
6642 * @class: the class to lookup the field.
6643 * @field_token: the field token
6645 * Returns: A MonoClassField representing the type and offset of
6646 * the field, or a NULL value if the field does not belong to this
6650 mono_class_get_field (MonoClass *class, guint32 field_token)
6652 int idx = mono_metadata_token_index (field_token);
6654 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6656 return mono_class_get_field_idx (class, idx - 1);
6660 * mono_class_get_field_from_name:
6661 * @klass: the class to lookup the field.
6662 * @name: the field name
6664 * Search the class @klass and it's parents for a field with the name @name.
6666 * Returns: the MonoClassField pointer of the named field or NULL
6669 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6671 return mono_class_get_field_from_name_full (klass, name, NULL);
6675 * mono_class_get_field_from_name_full:
6676 * @klass: the class to lookup the field.
6677 * @name: the field name
6678 * @type: the type of the fields. This optional.
6680 * Search the class @klass and it's parents for a field with the name @name and type @type.
6682 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6683 * of its generic type definition.
6685 * Returns: the MonoClassField pointer of the named field or NULL
6688 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6692 mono_class_setup_fields_locking (klass);
6693 if (klass->exception_type)
6697 for (i = 0; i < klass->field.count; ++i) {
6698 MonoClassField *field = &klass->fields [i];
6700 if (strcmp (name, mono_field_get_name (field)) != 0)
6704 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6705 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6710 klass = klass->parent;
6716 * mono_class_get_field_token:
6717 * @field: the field we need the token of
6719 * Get the token of a field. Note that the tokesn is only valid for the image
6720 * the field was loaded from. Don't use this function for fields in dynamic types.
6722 * Returns: the token representing the field in the image it was loaded from.
6725 mono_class_get_field_token (MonoClassField *field)
6727 MonoClass *klass = field->parent;
6730 mono_class_setup_fields_locking (klass);
6735 for (i = 0; i < klass->field.count; ++i) {
6736 if (&klass->fields [i] == field) {
6737 int idx = klass->field.first + i + 1;
6739 if (klass->image->uncompressed_metadata)
6740 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6741 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6744 klass = klass->parent;
6747 g_assert_not_reached ();
6752 mono_field_get_index (MonoClassField *field)
6754 int index = field - field->parent->fields;
6756 g_assert (index >= 0 && index < field->parent->field.count);
6762 * mono_class_get_field_default_value:
6764 * Return the default value of the field as a pointer into the metadata blob.
6767 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6770 guint32 constant_cols [MONO_CONSTANT_SIZE];
6772 MonoClass *klass = field->parent;
6774 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6776 if (!klass->ext || !klass->ext->field_def_values) {
6777 mono_loader_lock ();
6778 mono_class_alloc_ext (klass);
6779 if (!klass->ext->field_def_values)
6780 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6781 mono_loader_unlock ();
6784 field_index = mono_field_get_index (field);
6786 if (!klass->ext->field_def_values [field_index].data) {
6787 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6791 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6793 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6794 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6795 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6798 *def_type = klass->ext->field_def_values [field_index].def_type;
6799 return klass->ext->field_def_values [field_index].data;
6803 mono_property_get_index (MonoProperty *prop)
6805 int index = prop - prop->parent->ext->properties;
6807 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6813 * mono_class_get_property_default_value:
6815 * Return the default value of the field as a pointer into the metadata blob.
6818 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6821 guint32 constant_cols [MONO_CONSTANT_SIZE];
6822 MonoClass *klass = property->parent;
6824 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6826 * We don't cache here because it is not used by C# so it's quite rare, but
6827 * we still do the lookup in klass->ext because that is where the data
6828 * is stored for dynamic assemblies.
6831 if (klass->image->dynamic) {
6832 int prop_index = mono_property_get_index (property);
6833 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6834 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6835 return klass->ext->prop_def_values [prop_index].data;
6839 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6843 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6844 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6845 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6849 mono_class_get_event_token (MonoEvent *event)
6851 MonoClass *klass = event->parent;
6856 for (i = 0; i < klass->ext->event.count; ++i) {
6857 if (&klass->ext->events [i] == event)
6858 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6861 klass = klass->parent;
6864 g_assert_not_reached ();
6869 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6873 gpointer iter = NULL;
6874 while ((p = mono_class_get_properties (klass, &iter))) {
6875 if (! strcmp (name, p->name))
6878 klass = klass->parent;
6884 mono_class_get_property_token (MonoProperty *prop)
6886 MonoClass *klass = prop->parent;
6890 gpointer iter = NULL;
6891 while ((p = mono_class_get_properties (klass, &iter))) {
6892 if (&klass->ext->properties [i] == prop)
6893 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6897 klass = klass->parent;
6900 g_assert_not_reached ();
6905 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6907 const char *name, *nspace;
6909 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6911 switch (type_token & 0xff000000){
6912 case MONO_TOKEN_TYPE_DEF: {
6913 guint32 cols [MONO_TYPEDEF_SIZE];
6914 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6915 guint tidx = mono_metadata_token_index (type_token);
6917 if (tidx > tt->rows)
6918 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6920 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6921 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6922 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6923 if (strlen (nspace) == 0)
6924 return g_strdup_printf ("%s", name);
6926 return g_strdup_printf ("%s.%s", nspace, name);
6929 case MONO_TOKEN_TYPE_REF: {
6931 guint32 cols [MONO_TYPEREF_SIZE];
6932 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6933 guint tidx = mono_metadata_token_index (type_token);
6936 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6938 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6939 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6940 mono_error_cleanup (&error);
6944 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
6945 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
6946 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
6947 if (strlen (nspace) == 0)
6948 return g_strdup_printf ("%s", name);
6950 return g_strdup_printf ("%s.%s", nspace, name);
6953 case MONO_TOKEN_TYPE_SPEC:
6954 return g_strdup_printf ("Typespec 0x%08x", type_token);
6956 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6961 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
6964 return g_strdup_printf ("DynamicAssembly %s", image->name);
6966 switch (type_token & 0xff000000){
6967 case MONO_TOKEN_TYPE_DEF:
6968 if (image->assembly)
6969 return mono_stringify_assembly_name (&image->assembly->aname);
6970 else if (image->assembly_name)
6971 return g_strdup (image->assembly_name);
6972 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
6973 case MONO_TOKEN_TYPE_REF: {
6975 MonoAssemblyName aname;
6976 guint32 cols [MONO_TYPEREF_SIZE];
6977 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6978 guint32 idx = 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, idx - 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);
6988 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
6990 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
6991 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
6992 case MONO_RESOLTION_SCOPE_MODULE:
6994 return g_strdup ("");
6995 case MONO_RESOLTION_SCOPE_MODULEREF:
6997 return g_strdup ("");
6998 case MONO_RESOLTION_SCOPE_TYPEREF:
7000 return g_strdup ("");
7001 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7002 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7003 return mono_stringify_assembly_name (&aname);
7005 g_assert_not_reached ();
7009 case MONO_TOKEN_TYPE_SPEC:
7011 return g_strdup ("");
7013 g_assert_not_reached ();
7020 * mono_class_get_full:
7021 * @image: the image where the class resides
7022 * @type_token: the token for the class
7023 * @context: the generic context used to evaluate generic instantiations in
7025 * Returns: the MonoClass that represents @type_token in @image
7028 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7031 MonoClass *class = NULL;
7033 if (image->dynamic) {
7034 int table = mono_metadata_token_table (type_token);
7036 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7037 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7040 return mono_lookup_dynamic_token (image, type_token, context);
7043 switch (type_token & 0xff000000){
7044 case MONO_TOKEN_TYPE_DEF:
7045 class = mono_class_create_from_typedef (image, type_token, &error);
7046 if (!mono_error_ok (&error)) {
7047 mono_loader_set_error_from_mono_error (&error);
7048 /*FIXME don't swallow the error message*/
7049 mono_error_cleanup (&error);
7053 case MONO_TOKEN_TYPE_REF:
7054 class = mono_class_from_typeref (image, type_token);
7056 case MONO_TOKEN_TYPE_SPEC:
7057 class = mono_class_create_from_typespec (image, type_token, context, &error);
7058 if (!mono_error_ok (&error)) {
7059 /*FIXME don't swallow the error message*/
7060 mono_error_cleanup (&error);
7064 g_warning ("unknown token type %x", type_token & 0xff000000);
7065 g_assert_not_reached ();
7069 char *name = mono_class_name_from_token (image, type_token);
7070 char *assembly = mono_assembly_name_from_token (image, type_token);
7071 mono_loader_set_error_type_load (name, assembly);
7081 * mono_type_get_full:
7082 * @image: the image where the type resides
7083 * @type_token: the token for the type
7084 * @context: the generic context used to evaluate generic instantiations in
7086 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7088 * Returns: the MonoType that represents @type_token in @image
7091 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7094 MonoType *type = NULL;
7095 gboolean inflated = FALSE;
7097 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7099 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7101 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7102 MonoClass *class = mono_class_get_full (image, type_token, context);
7103 return class ? mono_class_get_type (class) : NULL;
7106 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7108 if (!mono_error_ok (&error)) {
7109 /*FIXME don't swalloc the error message.*/
7110 char *name = mono_class_name_from_token (image, type_token);
7111 char *assembly = mono_assembly_name_from_token (image, type_token);
7113 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7115 mono_error_cleanup (&error);
7116 mono_loader_set_error_type_load (name, assembly);
7121 MonoType *tmp = type;
7122 type = mono_class_get_type (mono_class_from_mono_type (type));
7123 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7124 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7125 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7127 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7129 if (type->type != tmp->type)
7132 mono_metadata_free_type (tmp);
7139 mono_class_get (MonoImage *image, guint32 type_token)
7141 return mono_class_get_full (image, type_token, NULL);
7145 * mono_image_init_name_cache:
7147 * Initializes the class name cache stored in image->name_cache.
7149 * LOCKING: Acquires the corresponding image lock.
7152 mono_image_init_name_cache (MonoImage *image)
7154 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7155 guint32 cols [MONO_TYPEDEF_SIZE];
7158 guint32 i, visib, nspace_index;
7159 GHashTable *name_cache2, *nspace_table;
7161 mono_image_lock (image);
7163 if (image->name_cache) {
7164 mono_image_unlock (image);
7168 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7170 if (image->dynamic) {
7171 mono_image_unlock (image);
7175 /* Temporary hash table to avoid lookups in the nspace_table */
7176 name_cache2 = g_hash_table_new (NULL, NULL);
7178 for (i = 1; i <= t->rows; ++i) {
7179 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7180 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7182 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7183 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7185 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7187 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7188 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7190 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7191 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7192 if (!nspace_table) {
7193 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7194 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7195 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7198 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7201 /* Load type names from EXPORTEDTYPES table */
7203 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7204 guint32 cols [MONO_EXP_TYPE_SIZE];
7207 for (i = 0; i < t->rows; ++i) {
7208 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7209 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7210 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7212 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7213 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7214 if (!nspace_table) {
7215 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7216 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7217 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7220 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7224 g_hash_table_destroy (name_cache2);
7225 mono_image_unlock (image);
7228 /*FIXME Only dynamic assemblies should allow this operation.*/
7230 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7231 const char *name, guint32 index)
7233 GHashTable *nspace_table;
7234 GHashTable *name_cache;
7237 mono_image_lock (image);
7239 if (!image->name_cache)
7240 mono_image_init_name_cache (image);
7242 name_cache = image->name_cache;
7243 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7244 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7245 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7248 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7249 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7251 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7253 mono_image_unlock (image);
7262 find_nocase (gpointer key, gpointer value, gpointer user_data)
7264 char *name = (char*)key;
7265 FindUserData *data = (FindUserData*)user_data;
7267 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7268 data->value = value;
7272 * mono_class_from_name_case:
7273 * @image: The MonoImage where the type is looked up in
7274 * @name_space: the type namespace
7275 * @name: the type short name.
7277 * Obtains a MonoClass with a given namespace and a given name which
7278 * is located in the given MonoImage. The namespace and name
7279 * lookups are case insensitive.
7282 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7284 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7285 guint32 cols [MONO_TYPEDEF_SIZE];
7290 if (image->dynamic) {
7292 FindUserData user_data;
7294 mono_image_lock (image);
7296 if (!image->name_cache)
7297 mono_image_init_name_cache (image);
7299 user_data.key = name_space;
7300 user_data.value = NULL;
7301 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7303 if (user_data.value) {
7304 GHashTable *nspace_table = (GHashTable*)user_data.value;
7306 user_data.key = name;
7307 user_data.value = NULL;
7309 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7311 if (user_data.value)
7312 token = GPOINTER_TO_UINT (user_data.value);
7315 mono_image_unlock (image);
7318 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7324 /* add a cache if needed */
7325 for (i = 1; i <= t->rows; ++i) {
7326 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7327 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7329 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7330 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7332 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7334 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7335 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7336 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7337 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7343 return_nested_in (MonoClass *class, char *nested)
7346 char *s = strchr (nested, '/');
7347 gpointer iter = NULL;
7354 while ((found = mono_class_get_nested_types (class, &iter))) {
7355 if (strcmp (found->name, nested) == 0) {
7357 return return_nested_in (found, s);
7365 search_modules (MonoImage *image, const char *name_space, const char *name)
7367 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7368 MonoImage *file_image;
7373 * The EXPORTEDTYPES table only contains public types, so have to search the
7375 * Note: image->modules contains the contents of the MODULEREF table, while
7376 * the real module list is in the FILE table.
7378 for (i = 0; i < file_table->rows; i++) {
7379 guint32 cols [MONO_FILE_SIZE];
7380 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7381 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7384 file_image = mono_image_load_file_for_image (image, i + 1);
7386 class = mono_class_from_name (file_image, name_space, name);
7396 * mono_class_from_name:
7397 * @image: The MonoImage where the type is looked up in
7398 * @name_space: the type namespace
7399 * @name: the type short name.
7401 * Obtains a MonoClass with a given namespace and a given name which
7402 * is located in the given MonoImage.
7405 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7407 GHashTable *nspace_table;
7408 MonoImage *loaded_image;
7415 if ((nested = strchr (name, '/'))) {
7416 int pos = nested - name;
7417 int len = strlen (name);
7420 memcpy (buf, name, len + 1);
7422 nested = buf + pos + 1;
7426 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7427 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7428 gboolean res = get_class_from_name (image, name_space, name, &class);
7431 class = search_modules (image, name_space, name);
7433 return class ? return_nested_in (class, nested) : NULL;
7439 mono_image_lock (image);
7441 if (!image->name_cache)
7442 mono_image_init_name_cache (image);
7444 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7447 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7449 mono_image_unlock (image);
7451 if (!token && image->dynamic && image->modules) {
7452 /* Search modules as well */
7453 for (i = 0; i < image->module_count; ++i) {
7454 MonoImage *module = image->modules [i];
7456 class = mono_class_from_name (module, name_space, name);
7463 class = search_modules (image, name_space, name);
7471 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7472 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7473 guint32 cols [MONO_EXP_TYPE_SIZE];
7476 idx = mono_metadata_token_index (token);
7478 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7480 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7481 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7482 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7485 class = mono_class_from_name (loaded_image, name_space, name);
7487 return return_nested_in (class, nested);
7489 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7490 guint32 assembly_idx;
7492 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7494 mono_assembly_load_reference (image, assembly_idx - 1);
7495 g_assert (image->references [assembly_idx - 1]);
7496 if (image->references [assembly_idx - 1] == (gpointer)-1)
7499 /* FIXME: Cycle detection */
7500 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7502 g_error ("not yet implemented");
7506 token = MONO_TOKEN_TYPE_DEF | token;
7508 class = mono_class_get (image, token);
7510 return return_nested_in (class, nested);
7514 /*FIXME test for interfaces with variant generic arguments*/
7516 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7517 gboolean check_interfaces)
7519 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7520 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7522 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7525 for (i = 0; i < klass->interface_count; i ++) {
7526 MonoClass *ic = klass->interfaces [i];
7531 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7536 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7539 if (klassc == mono_defaults.object_class)
7546 mono_type_is_generic_argument (MonoType *type)
7548 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7552 mono_class_has_variant_generic_params (MonoClass *klass)
7555 MonoGenericContainer *container;
7557 if (!klass->generic_class)
7560 container = klass->generic_class->container_class->generic_container;
7562 for (i = 0; i < container->type_argc; ++i)
7563 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7570 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7572 if (target == candidate)
7575 if (check_for_reference_conv &&
7576 mono_type_is_generic_argument (&target->byval_arg) &&
7577 mono_type_is_generic_argument (&candidate->byval_arg)) {
7578 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7579 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7581 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7584 if (!mono_class_is_assignable_from (target, candidate))
7590 * @container the generic container from the GTD
7591 * @klass: the class to be assigned to
7592 * @oklass: the source class
7594 * Both klass and oklass must be instances of the same generic interface.
7595 * Return true if @klass can be assigned to a @klass variable
7598 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7601 MonoType **klass_argv, **oklass_argv;
7602 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7603 MonoGenericContainer *container = klass_gtd->generic_container;
7605 if (klass == oklass)
7608 /*Viable candidates are instances of the same generic interface*/
7609 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7612 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7613 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7615 for (j = 0; j < container->type_argc; ++j) {
7616 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7617 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7619 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7623 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7624 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7626 if (param1_class != param2_class) {
7627 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7628 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7630 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7631 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7641 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7643 MonoGenericParam *gparam, *ogparam;
7644 MonoGenericParamInfo *tinfo, *cinfo;
7645 MonoClass **candidate_class;
7646 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7649 if (target == candidate)
7651 if (target->byval_arg.type != candidate->byval_arg.type)
7654 gparam = target->byval_arg.data.generic_param;
7655 ogparam = candidate->byval_arg.data.generic_param;
7656 tinfo = mono_generic_param_info (gparam);
7657 cinfo = mono_generic_param_info (ogparam);
7659 class_constraint_satisfied = FALSE;
7660 valuetype_constraint_satisfied = FALSE;
7662 /*candidate must have a super set of target's special constraints*/
7663 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7664 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7666 if (cinfo->constraints) {
7667 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7668 MonoClass *cc = *candidate_class;
7670 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7671 class_constraint_satisfied = TRUE;
7672 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7673 valuetype_constraint_satisfied = TRUE;
7676 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7677 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7679 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7681 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7683 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7684 valuetype_constraint_satisfied)) {
7689 /*candidate type constraints must be a superset of target's*/
7690 if (tinfo->constraints) {
7691 MonoClass **target_class;
7692 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7693 MonoClass *tc = *target_class;
7696 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7697 * check it's constraints since it satisfy the constraint by itself.
7699 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7702 if (!cinfo->constraints)
7705 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7706 MonoClass *cc = *candidate_class;
7708 if (mono_class_is_assignable_from (tc, cc))
7712 * This happens when we have the following:
7714 * Bar<K> where K : IFace
7715 * Foo<T, U> where T : U where U : IFace
7717 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7720 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7721 if (mono_gparam_is_assignable_from (target, cc))
7725 if (!*candidate_class)
7730 /*candidate itself must have a constraint that satisfy target*/
7731 if (cinfo->constraints) {
7732 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7733 MonoClass *cc = *candidate_class;
7734 if (mono_class_is_assignable_from (target, cc))
7742 * mono_class_is_assignable_from:
7743 * @klass: the class to be assigned to
7744 * @oklass: the source class
7746 * Return: true if an instance of object oklass can be assigned to an
7747 * instance of object @klass
7750 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7752 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7754 mono_class_init (klass);
7756 if (!oklass->inited)
7757 mono_class_init (oklass);
7759 if (klass->exception_type || oklass->exception_type)
7762 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7763 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7765 return mono_gparam_is_assignable_from (klass, oklass);
7768 if (MONO_CLASS_IS_INTERFACE (klass)) {
7769 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7770 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7771 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7775 for (i = 0; constraints [i]; ++i) {
7776 if (mono_class_is_assignable_from (klass, constraints [i]))
7784 /* interface_offsets might not be set for dynamic classes */
7785 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7787 * oklass might be a generic type parameter but they have
7788 * interface_offsets set.
7790 return mono_reflection_call_is_assignable_to (oklass, klass);
7791 if (!oklass->interface_bitmap)
7792 /* Happens with generic instances of not-yet created dynamic types */
7794 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7797 if (mono_class_has_variant_generic_params (klass)) {
7800 mono_class_setup_interfaces (oklass, &error);
7801 if (!mono_error_ok (&error)) {
7802 mono_error_cleanup (&error);
7806 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7807 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7808 MonoClass *iface = oklass->interfaces_packed [i];
7810 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7815 } else if (klass->delegate) {
7816 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7818 }else if (klass->rank) {
7819 MonoClass *eclass, *eoclass;
7821 if (oklass->rank != klass->rank)
7824 /* vectors vs. one dimensional arrays */
7825 if (oklass->byval_arg.type != klass->byval_arg.type)
7828 eclass = klass->cast_class;
7829 eoclass = oklass->cast_class;
7832 * a is b does not imply a[] is b[] when a is a valuetype, and
7833 * b is a reference type.
7836 if (eoclass->valuetype) {
7837 if ((eclass == mono_defaults.enum_class) ||
7838 (eclass == mono_defaults.enum_class->parent) ||
7839 (eclass == mono_defaults.object_class))
7843 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7844 } else if (mono_class_is_nullable (klass)) {
7845 if (mono_class_is_nullable (oklass))
7846 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7848 return mono_class_is_assignable_from (klass->cast_class, oklass);
7849 } else if (klass == mono_defaults.object_class)
7852 return mono_class_has_parent (oklass, klass);
7855 /*Check if @oklass is variant compatible with @klass.*/
7857 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7860 MonoType **klass_argv, **oklass_argv;
7861 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7862 MonoGenericContainer *container = klass_gtd->generic_container;
7864 /*Viable candidates are instances of the same generic interface*/
7865 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7868 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7869 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7871 for (j = 0; j < container->type_argc; ++j) {
7872 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7873 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7875 if (param1_class->valuetype != param2_class->valuetype)
7879 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7880 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7882 if (param1_class != param2_class) {
7883 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7884 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7886 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7887 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7895 /*Check if @candidate implements the interface @target*/
7897 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7901 gboolean is_variant = mono_class_has_variant_generic_params (target);
7903 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7904 if (mono_class_is_variant_compatible_slow (target, candidate))
7909 if (candidate == target)
7912 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7913 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7914 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7916 if (tb && tb->interfaces) {
7917 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7918 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7919 MonoClass *iface_class;
7921 /* we can't realize the type here since it can do pretty much anything. */
7924 iface_class = mono_class_from_mono_type (iface->type);
7925 if (iface_class == target)
7927 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
7929 if (mono_class_implement_interface_slow (target, iface_class))
7934 /*setup_interfaces don't mono_class_init anything*/
7935 mono_class_setup_interfaces (candidate, &error);
7936 if (!mono_error_ok (&error)) {
7937 mono_error_cleanup (&error);
7941 for (i = 0; i < candidate->interface_count; ++i) {
7942 if (candidate->interfaces [i] == target)
7945 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
7948 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
7952 candidate = candidate->parent;
7953 } while (candidate);
7959 * Check if @oklass can be assigned to @klass.
7960 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
7963 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
7965 if (candidate == target)
7967 if (target == mono_defaults.object_class)
7970 if (mono_class_has_parent (candidate, target))
7973 /*If target is not an interface there is no need to check them.*/
7974 if (MONO_CLASS_IS_INTERFACE (target))
7975 return mono_class_implement_interface_slow (target, candidate);
7977 if (target->delegate && mono_class_has_variant_generic_params (target))
7978 return mono_class_is_variant_compatible (target, candidate, FALSE);
7980 /*FIXME properly handle nullables and arrays */
7981 /*FIXME properly handle (M)VAR */
7986 * mono_class_get_cctor:
7987 * @klass: A MonoClass pointer
7989 * Returns: the static constructor of @klass if it exists, NULL otherwise.
7992 mono_class_get_cctor (MonoClass *klass)
7994 MonoCachedClassInfo cached_info;
7996 if (klass->image->dynamic) {
7998 * has_cctor is not set for these classes because mono_class_init () is
8001 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8004 if (!klass->has_cctor)
8007 if (mono_class_get_cached_class_info (klass, &cached_info))
8008 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8010 if (klass->generic_class && !klass->methods)
8011 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8013 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8017 * mono_class_get_finalizer:
8018 * @klass: The MonoClass pointer
8020 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8023 mono_class_get_finalizer (MonoClass *klass)
8025 MonoCachedClassInfo cached_info;
8028 mono_class_init (klass);
8029 if (!mono_class_has_finalizer (klass))
8032 if (mono_class_get_cached_class_info (klass, &cached_info))
8033 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8035 mono_class_setup_vtable (klass);
8036 return klass->vtable [finalize_slot];
8041 * mono_class_needs_cctor_run:
8042 * @klass: the MonoClass pointer
8043 * @caller: a MonoMethod describing the caller
8045 * Determines whenever the class has a static constructor and whenever it
8046 * needs to be called when executing CALLER.
8049 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8053 method = mono_class_get_cctor (klass);
8055 return (method == caller) ? FALSE : TRUE;
8061 * mono_class_array_element_size:
8064 * Returns: the number of bytes an element of type @klass
8065 * uses when stored into an array.
8068 mono_class_array_element_size (MonoClass *klass)
8070 MonoType *type = &klass->byval_arg;
8073 switch (type->type) {
8076 case MONO_TYPE_BOOLEAN:
8080 case MONO_TYPE_CHAR:
8089 case MONO_TYPE_CLASS:
8090 case MONO_TYPE_STRING:
8091 case MONO_TYPE_OBJECT:
8092 case MONO_TYPE_SZARRAY:
8093 case MONO_TYPE_ARRAY:
8095 case MONO_TYPE_MVAR:
8096 return sizeof (gpointer);
8101 case MONO_TYPE_VALUETYPE:
8102 if (type->data.klass->enumtype) {
8103 type = mono_class_enum_basetype (type->data.klass);
8104 klass = klass->element_class;
8107 return mono_class_instance_size (klass) - sizeof (MonoObject);
8108 case MONO_TYPE_GENERICINST:
8109 type = &type->data.generic_class->container_class->byval_arg;
8112 case MONO_TYPE_VOID:
8116 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8122 * mono_array_element_size:
8123 * @ac: pointer to a #MonoArrayClass
8125 * Returns: the size of single array element.
8128 mono_array_element_size (MonoClass *ac)
8130 g_assert (ac->rank);
8131 return ac->sizes.element_size;
8135 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8136 MonoGenericContext *context)
8138 if (image->dynamic) {
8139 MonoClass *tmp_handle_class;
8140 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8142 g_assert (tmp_handle_class);
8144 *handle_class = tmp_handle_class;
8146 if (tmp_handle_class == mono_defaults.typehandle_class)
8147 return &((MonoClass*)obj)->byval_arg;
8152 switch (token & 0xff000000) {
8153 case MONO_TOKEN_TYPE_DEF:
8154 case MONO_TOKEN_TYPE_REF:
8155 case MONO_TOKEN_TYPE_SPEC: {
8158 *handle_class = mono_defaults.typehandle_class;
8159 type = mono_type_get_full (image, token, context);
8162 mono_class_init (mono_class_from_mono_type (type));
8163 /* We return a MonoType* as handle */
8166 case MONO_TOKEN_FIELD_DEF: {
8168 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8172 *handle_class = mono_defaults.fieldhandle_class;
8173 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8176 mono_class_init (class);
8177 return mono_class_get_field (class, token);
8179 case MONO_TOKEN_METHOD_DEF:
8180 case MONO_TOKEN_METHOD_SPEC: {
8182 meth = mono_get_method_full (image, token, NULL, context);
8184 *handle_class = mono_defaults.methodhandle_class;
8187 case MONO_TOKEN_MEMBER_REF: {
8188 guint32 cols [MONO_MEMBERREF_SIZE];
8190 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8191 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8192 mono_metadata_decode_blob_size (sig, &sig);
8193 if (*sig == 0x6) { /* it's a field */
8195 MonoClassField *field;
8196 field = mono_field_from_token (image, token, &klass, context);
8198 *handle_class = mono_defaults.fieldhandle_class;
8202 meth = mono_get_method_full (image, token, NULL, context);
8204 *handle_class = mono_defaults.methodhandle_class;
8209 g_warning ("Unknown token 0x%08x in ldtoken", token);
8216 * This function might need to call runtime functions so it can't be part
8217 * of the metadata library.
8219 static MonoLookupDynamicToken lookup_dynamic = NULL;
8222 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8224 lookup_dynamic = func;
8228 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8230 MonoClass *handle_class;
8232 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8236 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8238 return lookup_dynamic (image, token, valid_token, handle_class, context);
8241 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8244 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8246 get_cached_class_info = func;
8250 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8252 if (!get_cached_class_info)
8255 return get_cached_class_info (klass, res);
8259 mono_install_get_class_from_name (MonoGetClassFromName func)
8261 get_class_from_name = func;
8265 mono_class_get_image (MonoClass *klass)
8267 return klass->image;
8271 * mono_class_get_element_class:
8272 * @klass: the MonoClass to act on
8274 * Returns: the element class of an array or an enumeration.
8277 mono_class_get_element_class (MonoClass *klass)
8279 return klass->element_class;
8283 * mono_class_is_valuetype:
8284 * @klass: the MonoClass to act on
8286 * Returns: true if the MonoClass represents a ValueType.
8289 mono_class_is_valuetype (MonoClass *klass)
8291 return klass->valuetype;
8295 * mono_class_is_enum:
8296 * @klass: the MonoClass to act on
8298 * Returns: true if the MonoClass represents an enumeration.
8301 mono_class_is_enum (MonoClass *klass)
8303 return klass->enumtype;
8307 * mono_class_enum_basetype:
8308 * @klass: the MonoClass to act on
8310 * Returns: the underlying type representation for an enumeration.
8313 mono_class_enum_basetype (MonoClass *klass)
8315 if (klass->element_class == klass)
8316 /* SRE or broken types */
8319 return &klass->element_class->byval_arg;
8323 * mono_class_get_parent
8324 * @klass: the MonoClass to act on
8326 * Returns: the parent class for this class.
8329 mono_class_get_parent (MonoClass *klass)
8331 return klass->parent;
8335 * mono_class_get_nesting_type;
8336 * @klass: the MonoClass to act on
8338 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8341 mono_class_get_nesting_type (MonoClass *klass)
8343 return klass->nested_in;
8347 * mono_class_get_rank:
8348 * @klass: the MonoClass to act on
8350 * Returns: the rank for the array (the number of dimensions).
8353 mono_class_get_rank (MonoClass *klass)
8359 * mono_class_get_flags:
8360 * @klass: the MonoClass to act on
8362 * The type flags from the TypeDef table from the metadata.
8363 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8366 * Returns: the flags from the TypeDef table.
8369 mono_class_get_flags (MonoClass *klass)
8371 return klass->flags;
8375 * mono_class_get_name
8376 * @klass: the MonoClass to act on
8378 * Returns: the name of the class.
8381 mono_class_get_name (MonoClass *klass)
8387 * mono_class_get_namespace:
8388 * @klass: the MonoClass to act on
8390 * Returns: the namespace of the class.
8393 mono_class_get_namespace (MonoClass *klass)
8395 return klass->name_space;
8399 * mono_class_get_type:
8400 * @klass: the MonoClass to act on
8402 * This method returns the internal Type representation for the class.
8404 * Returns: the MonoType from the class.
8407 mono_class_get_type (MonoClass *klass)
8409 return &klass->byval_arg;
8413 * mono_class_get_type_token
8414 * @klass: the MonoClass to act on
8416 * This method returns type token for the class.
8418 * Returns: the type token for the class.
8421 mono_class_get_type_token (MonoClass *klass)
8423 return klass->type_token;
8427 * mono_class_get_byref_type:
8428 * @klass: the MonoClass to act on
8433 mono_class_get_byref_type (MonoClass *klass)
8435 return &klass->this_arg;
8439 * mono_class_num_fields:
8440 * @klass: the MonoClass to act on
8442 * Returns: the number of static and instance fields in the class.
8445 mono_class_num_fields (MonoClass *klass)
8447 return klass->field.count;
8451 * mono_class_num_methods:
8452 * @klass: the MonoClass to act on
8454 * Returns: the number of methods in the class.
8457 mono_class_num_methods (MonoClass *klass)
8459 return klass->method.count;
8463 * mono_class_num_properties
8464 * @klass: the MonoClass to act on
8466 * Returns: the number of properties in the class.
8469 mono_class_num_properties (MonoClass *klass)
8471 mono_class_setup_properties (klass);
8473 return klass->ext->property.count;
8477 * mono_class_num_events:
8478 * @klass: the MonoClass to act on
8480 * Returns: the number of events in the class.
8483 mono_class_num_events (MonoClass *klass)
8485 mono_class_setup_events (klass);
8487 return klass->ext->event.count;
8491 * mono_class_get_fields:
8492 * @klass: the MonoClass to act on
8494 * This routine is an iterator routine for retrieving the fields in a class.
8496 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8497 * iterate over all of the elements. When no more values are
8498 * available, the return value is NULL.
8500 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8503 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8505 MonoClassField* field;
8509 mono_class_setup_fields_locking (klass);
8510 if (klass->exception_type)
8512 /* start from the first */
8513 if (klass->field.count) {
8514 return *iter = &klass->fields [0];
8522 if (field < &klass->fields [klass->field.count]) {
8523 return *iter = field;
8529 * mono_class_get_methods
8530 * @klass: the MonoClass to act on
8532 * This routine is an iterator routine for retrieving the fields in a class.
8534 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8535 * iterate over all of the elements. When no more values are
8536 * available, the return value is NULL.
8538 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8541 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8543 MonoMethod** method;
8547 mono_class_setup_methods (klass);
8550 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8551 * FIXME we should better report this error to the caller
8553 if (!klass->methods)
8555 /* start from the first */
8556 if (klass->method.count) {
8557 *iter = &klass->methods [0];
8558 return klass->methods [0];
8566 if (method < &klass->methods [klass->method.count]) {
8574 * mono_class_get_virtual_methods:
8576 * Iterate over the virtual methods of KLASS.
8578 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8581 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8583 MonoMethod** method;
8586 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
8588 mono_class_setup_methods (klass);
8590 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8591 * FIXME we should better report this error to the caller
8593 if (!klass->methods)
8595 /* start from the first */
8596 method = &klass->methods [0];
8601 while (method < &klass->methods [klass->method.count]) {
8602 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8606 if (method < &klass->methods [klass->method.count]) {
8613 /* Search directly in metadata to avoid calling setup_methods () */
8614 MonoMethod *res = NULL;
8620 start_index = GPOINTER_TO_UINT (*iter);
8623 for (i = start_index; i < klass->method.count; ++i) {
8626 /* class->method.first points into the methodptr table */
8627 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8629 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8633 if (i < klass->method.count) {
8634 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8635 /* Add 1 here so the if (*iter) check fails */
8636 *iter = GUINT_TO_POINTER (i + 1);
8645 * mono_class_get_properties:
8646 * @klass: the MonoClass to act on
8648 * This routine is an iterator routine for retrieving the properties in a class.
8650 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8651 * iterate over all of the elements. When no more values are
8652 * available, the return value is NULL.
8654 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8657 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8659 MonoProperty* property;
8663 mono_class_setup_properties (klass);
8664 /* start from the first */
8665 if (klass->ext->property.count) {
8666 return *iter = &klass->ext->properties [0];
8674 if (property < &klass->ext->properties [klass->ext->property.count]) {
8675 return *iter = property;
8681 * mono_class_get_events:
8682 * @klass: the MonoClass to act on
8684 * This routine is an iterator routine for retrieving the properties in a class.
8686 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8687 * iterate over all of the elements. When no more values are
8688 * available, the return value is NULL.
8690 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8693 mono_class_get_events (MonoClass* klass, gpointer *iter)
8699 mono_class_setup_events (klass);
8700 /* start from the first */
8701 if (klass->ext->event.count) {
8702 return *iter = &klass->ext->events [0];
8710 if (event < &klass->ext->events [klass->ext->event.count]) {
8711 return *iter = event;
8717 * mono_class_get_interfaces
8718 * @klass: the MonoClass to act on
8720 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8722 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8723 * iterate over all of the elements. When no more values are
8724 * available, the return value is NULL.
8726 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8729 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8737 mono_class_init (klass);
8738 if (!klass->interfaces_inited) {
8739 mono_class_setup_interfaces (klass, &error);
8740 if (!mono_error_ok (&error)) {
8741 mono_error_cleanup (&error);
8745 /* start from the first */
8746 if (klass->interface_count) {
8747 *iter = &klass->interfaces [0];
8748 return klass->interfaces [0];
8756 if (iface < &klass->interfaces [klass->interface_count]) {
8764 * mono_class_get_nested_types
8765 * @klass: the MonoClass to act on
8767 * This routine is an iterator routine for retrieving the nested types of a class.
8768 * This works only if @klass is non-generic, or a generic type definition.
8770 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8771 * iterate over all of the elements. When no more values are
8772 * available, the return value is NULL.
8774 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8777 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8785 if (!klass->nested_classes_inited) {
8786 if (!klass->type_token)
8787 klass->nested_classes_inited = TRUE;
8788 mono_loader_lock ();
8789 if (!klass->nested_classes_inited) {
8790 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8793 guint32 cols [MONO_NESTED_CLASS_SIZE];
8794 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8795 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8796 if (!mono_error_ok (&error)) {
8797 /*FIXME don't swallow the error message*/
8798 mono_error_cleanup (&error);
8800 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8803 mono_class_alloc_ext (klass);
8804 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8806 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8809 mono_memory_barrier ();
8810 klass->nested_classes_inited = TRUE;
8811 mono_loader_unlock ();
8815 /* start from the first */
8816 if (klass->ext && klass->ext->nested_classes) {
8817 *iter = klass->ext->nested_classes;
8818 return klass->ext->nested_classes->data;
8820 /* no nested types */
8834 * mono_field_get_name:
8835 * @field: the MonoClassField to act on
8837 * Returns: the name of the field.
8840 mono_field_get_name (MonoClassField *field)
8846 * mono_field_get_type:
8847 * @field: the MonoClassField to act on
8849 * Returns: MonoType of the field.
8852 mono_field_get_type (MonoClassField *field)
8855 MonoType *type = mono_field_get_type_checked (field, &error);
8856 if (!mono_error_ok (&error)) {
8857 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8858 mono_error_cleanup (&error);
8865 * mono_field_get_type_checked:
8866 * @field: the MonoClassField to act on
8867 * @error: used to return any erro found while retrieving @field type
8869 * Returns: MonoType of the field.
8872 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
8874 mono_error_init (error);
8876 mono_field_resolve_type (field, error);
8881 * mono_field_get_parent:
8882 * @field: the MonoClassField to act on
8884 * Returns: MonoClass where the field was defined.
8887 mono_field_get_parent (MonoClassField *field)
8889 return field->parent;
8893 * mono_field_get_flags;
8894 * @field: the MonoClassField to act on
8896 * The metadata flags for a field are encoded using the
8897 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
8899 * Returns: the flags for the field.
8902 mono_field_get_flags (MonoClassField *field)
8905 return mono_field_resolve_flags (field);
8906 return field->type->attrs;
8910 * mono_field_get_offset;
8911 * @field: the MonoClassField to act on
8913 * Returns: the field offset.
8916 mono_field_get_offset (MonoClassField *field)
8918 return field->offset;
8922 mono_field_get_rva (MonoClassField *field)
8926 MonoClass *klass = field->parent;
8928 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
8930 if (!klass->ext || !klass->ext->field_def_values) {
8931 mono_loader_lock ();
8932 mono_class_alloc_ext (klass);
8933 if (!klass->ext->field_def_values)
8934 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
8935 mono_loader_unlock ();
8938 field_index = mono_field_get_index (field);
8940 if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
8941 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
8943 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
8944 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
8947 return klass->ext->field_def_values [field_index].data;
8951 * mono_field_get_data;
8952 * @field: the MonoClassField to act on
8954 * Returns: pointer to the metadata constant value or to the field
8955 * data if it has an RVA flag.
8958 mono_field_get_data (MonoClassField *field)
8960 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
8961 MonoTypeEnum def_type;
8963 return mono_class_get_field_default_value (field, &def_type);
8964 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
8965 return mono_field_get_rva (field);
8972 * mono_property_get_name:
8973 * @prop: the MonoProperty to act on
8975 * Returns: the name of the property
8978 mono_property_get_name (MonoProperty *prop)
8984 * mono_property_get_set_method
8985 * @prop: the MonoProperty to act on.
8987 * Returns: the setter method of the property (A MonoMethod)
8990 mono_property_get_set_method (MonoProperty *prop)
8996 * mono_property_get_get_method
8997 * @prop: the MonoProperty to act on.
8999 * Returns: the setter method of the property (A MonoMethod)
9002 mono_property_get_get_method (MonoProperty *prop)
9008 * mono_property_get_parent:
9009 * @prop: the MonoProperty to act on.
9011 * Returns: the MonoClass where the property was defined.
9014 mono_property_get_parent (MonoProperty *prop)
9016 return prop->parent;
9020 * mono_property_get_flags:
9021 * @prop: the MonoProperty to act on.
9023 * The metadata flags for a property are encoded using the
9024 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9026 * Returns: the flags for the property.
9029 mono_property_get_flags (MonoProperty *prop)
9035 * mono_event_get_name:
9036 * @event: the MonoEvent to act on
9038 * Returns: the name of the event.
9041 mono_event_get_name (MonoEvent *event)
9047 * mono_event_get_add_method:
9048 * @event: The MonoEvent to act on.
9050 * Returns: the @add' method for the event (a MonoMethod).
9053 mono_event_get_add_method (MonoEvent *event)
9059 * mono_event_get_remove_method:
9060 * @event: The MonoEvent to act on.
9062 * Returns: the @remove method for the event (a MonoMethod).
9065 mono_event_get_remove_method (MonoEvent *event)
9067 return event->remove;
9071 * mono_event_get_raise_method:
9072 * @event: The MonoEvent to act on.
9074 * Returns: the @raise method for the event (a MonoMethod).
9077 mono_event_get_raise_method (MonoEvent *event)
9079 return event->raise;
9083 * mono_event_get_parent:
9084 * @event: the MonoEvent to act on.
9086 * Returns: the MonoClass where the event is defined.
9089 mono_event_get_parent (MonoEvent *event)
9091 return event->parent;
9095 * mono_event_get_flags
9096 * @event: the MonoEvent to act on.
9098 * The metadata flags for an event are encoded using the
9099 * EVENT_* constants. See the tabledefs.h file for details.
9101 * Returns: the flags for the event.
9104 mono_event_get_flags (MonoEvent *event)
9106 return event->attrs;
9110 * mono_class_get_method_from_name:
9111 * @klass: where to look for the method
9112 * @name_space: name of the method
9113 * @param_count: number of parameters. -1 for any number.
9115 * Obtains a MonoMethod with a given name and number of parameters.
9116 * It only works if there are no multiple signatures for any given method name.
9119 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9121 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9125 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9127 MonoMethod *res = NULL;
9130 /* Search directly in the metadata to avoid calling setup_methods () */
9131 for (i = 0; i < klass->method.count; ++i) {
9132 guint32 cols [MONO_METHOD_SIZE];
9134 MonoMethodSignature *sig;
9136 /* class->method.first points into the methodptr table */
9137 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9139 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9140 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9141 if (param_count == -1) {
9145 sig = mono_method_signature (method);
9146 if (sig && sig->param_count == param_count) {
9157 * mono_class_get_method_from_name_flags:
9158 * @klass: where to look for the method
9159 * @name_space: name of the method
9160 * @param_count: number of parameters. -1 for any number.
9161 * @flags: flags which must be set in the method
9163 * Obtains a MonoMethod with a given name and number of parameters.
9164 * It only works if there are no multiple signatures for any given method name.
9167 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9169 MonoMethod *res = NULL;
9172 mono_class_init (klass);
9174 if (klass->generic_class && !klass->methods) {
9175 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9177 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9181 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9182 mono_class_setup_methods (klass);
9184 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9185 See mono/tests/array_load_exception.il
9186 FIXME we should better report this error to the caller
9188 if (!klass->methods)
9190 for (i = 0; i < klass->method.count; ++i) {
9191 MonoMethod *method = klass->methods [i];
9193 if (method->name[0] == name [0] &&
9194 !strcmp (name, method->name) &&
9195 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9196 ((method->flags & flags) == flags)) {
9203 res = find_method_in_metadata (klass, name, param_count, flags);
9210 * mono_class_set_failure:
9211 * @klass: class in which the failure was detected
9212 * @ex_type: the kind of exception/error to be thrown (later)
9213 * @ex_data: exception data (specific to each type of exception/error)
9215 * Keep a detected failure informations in the class for later processing.
9216 * Note that only the first failure is kept.
9218 * LOCKING: Acquires the loader lock.
9221 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9223 if (klass->exception_type)
9226 mono_loader_lock ();
9227 klass->exception_type = ex_type;
9229 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9230 mono_loader_unlock ();
9236 * mono_class_get_exception_data:
9238 * Return the exception_data property of KLASS.
9240 * LOCKING: Acquires the loader lock.
9243 mono_class_get_exception_data (MonoClass *klass)
9245 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9249 * mono_classes_init:
9251 * Initialize the resources used by this module.
9254 mono_classes_init (void)
9256 mono_counters_register ("Inflated methods size",
9257 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9258 mono_counters_register ("Inflated classes",
9259 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9260 mono_counters_register ("Inflated classes size",
9261 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9262 mono_counters_register ("MonoClass size",
9263 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9264 mono_counters_register ("MonoClassExt size",
9265 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9269 * mono_classes_cleanup:
9271 * Free the resources used by this module.
9274 mono_classes_cleanup (void)
9276 if (global_interface_bitset)
9277 mono_bitset_free (global_interface_bitset);
9278 global_interface_bitset = NULL;
9282 * mono_class_get_exception_for_failure:
9283 * @klass: class in which the failure was detected
9285 * Return a constructed MonoException than the caller can then throw
9286 * using mono_raise_exception - or NULL if no failure is present (or
9287 * doesn't result in an exception).
9290 mono_class_get_exception_for_failure (MonoClass *klass)
9292 gpointer exception_data = mono_class_get_exception_data (klass);
9294 switch (klass->exception_type) {
9295 #ifndef DISABLE_SECURITY
9296 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9297 MonoDomain *domain = mono_domain_get ();
9298 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9299 MonoMethod *method = exception_data;
9300 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9301 MonoObject *exc = NULL;
9305 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9306 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9307 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9309 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9310 return (MonoException*) exc;
9313 case MONO_EXCEPTION_TYPE_LOAD: {
9316 char *str = mono_type_get_full_name (klass);
9317 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9318 name = mono_string_new (mono_domain_get (), str);
9320 ex = mono_get_exception_type_load (name, astr);
9324 case MONO_EXCEPTION_MISSING_METHOD: {
9325 char *class_name = exception_data;
9326 char *assembly_name = class_name + strlen (class_name) + 1;
9328 return mono_get_exception_missing_method (class_name, assembly_name);
9330 case MONO_EXCEPTION_MISSING_FIELD: {
9331 char *class_name = exception_data;
9332 char *member_name = class_name + strlen (class_name) + 1;
9334 return mono_get_exception_missing_field (class_name, member_name);
9336 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9337 char *msg_format = exception_data;
9338 char *assembly_name = msg_format + strlen (msg_format) + 1;
9339 char *msg = g_strdup_printf (msg_format, assembly_name);
9342 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9348 case MONO_EXCEPTION_BAD_IMAGE: {
9349 return mono_get_exception_bad_image_format (exception_data);
9352 MonoLoaderError *error;
9355 error = mono_loader_get_last_error ();
9357 ex = mono_loader_error_prepare_exception (error);
9361 /* TODO - handle other class related failures */
9368 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9370 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9371 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9373 if (outer_klass == inner_klass)
9375 inner_klass = inner_klass->nested_in;
9376 } while (inner_klass);
9381 mono_class_get_generic_type_definition (MonoClass *klass)
9383 return klass->generic_class ? klass->generic_class->container_class : klass;
9387 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9389 * Generic instantiations are ignored for all super types of @klass.
9391 * Visibility checks ignoring generic instantiations.
9394 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9397 klass = mono_class_get_generic_type_definition (klass);
9398 parent = mono_class_get_generic_type_definition (parent);
9399 mono_class_setup_supertypes (klass);
9401 for (i = 0; i < klass->idepth; ++i) {
9402 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9408 * Subtype can only access parent members with family protection if the site object
9409 * is subclass of Subtype. For example:
9410 * class A { protected int x; }
9412 * void valid_access () {
9416 * void invalid_access () {
9423 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9425 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9428 if (context_klass == NULL)
9430 /*if access_klass is not member_klass context_klass must be type compat*/
9431 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9437 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9440 if (accessing == accessed)
9442 if (!accessed || !accessing)
9445 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9446 * anywhere so untrusted friends are not safe to access platform's code internals */
9447 if (mono_security_core_clr_enabled ()) {
9448 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9452 mono_assembly_load_friends (accessed);
9453 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9454 MonoAssemblyName *friend = tmp->data;
9455 /* Be conservative with checks */
9458 if (strcmp (accessing->aname.name, friend->name))
9460 if (friend->public_key_token [0]) {
9461 if (!accessing->aname.public_key_token [0])
9463 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9472 * If klass is a generic type or if it is derived from a generic type, return the
9473 * MonoClass of the generic definition
9474 * Returns NULL if not found
9477 get_generic_definition_class (MonoClass *klass)
9480 if (klass->generic_class && klass->generic_class->container_class)
9481 return klass->generic_class->container_class;
9482 klass = klass->parent;
9488 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9491 for (i = 0; i < ginst->type_argc; ++i) {
9492 MonoType *type = ginst->type_argv[i];
9493 switch (type->type) {
9494 case MONO_TYPE_SZARRAY:
9495 if (!can_access_type (access_klass, type->data.klass))
9498 case MONO_TYPE_ARRAY:
9499 if (!can_access_type (access_klass, type->data.array->eklass))
9503 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9506 case MONO_TYPE_CLASS:
9507 case MONO_TYPE_VALUETYPE:
9508 case MONO_TYPE_GENERICINST:
9509 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9517 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9521 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9524 if (access_klass->element_class && !access_klass->enumtype)
9525 access_klass = access_klass->element_class;
9527 if (member_klass->element_class && !member_klass->enumtype)
9528 member_klass = member_klass->element_class;
9530 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9532 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9535 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9538 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9541 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9544 /*Non nested type with nested visibility. We just fail it.*/
9545 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9548 switch (access_level) {
9549 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9550 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9552 case TYPE_ATTRIBUTE_PUBLIC:
9555 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9558 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9559 return is_nesting_type (member_klass, access_klass);
9561 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9562 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9564 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9565 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9567 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9568 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9569 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9571 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9572 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9573 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9578 /* FIXME: check visibility of type, too */
9580 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9582 MonoClass *member_generic_def;
9583 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9586 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9587 access_klass->generic_container) &&
9588 (member_generic_def = get_generic_definition_class (member_klass))) {
9589 MonoClass *access_container;
9591 if (access_klass->generic_container)
9592 access_container = access_klass;
9594 access_container = access_klass->generic_class->container_class;
9596 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9600 /* Partition I 8.5.3.2 */
9601 /* the access level values are the same for fields and methods */
9602 switch (access_level) {
9603 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9604 /* same compilation unit */
9605 return access_klass->image == member_klass->image;
9606 case FIELD_ATTRIBUTE_PRIVATE:
9607 return access_klass == member_klass;
9608 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9609 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9610 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9613 case FIELD_ATTRIBUTE_ASSEMBLY:
9614 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9615 case FIELD_ATTRIBUTE_FAMILY:
9616 if (is_valid_family_access (access_klass, member_klass, context_klass))
9619 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9620 if (is_valid_family_access (access_klass, member_klass, context_klass))
9622 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9623 case FIELD_ATTRIBUTE_PUBLIC:
9630 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9632 /* FIXME: check all overlapping fields */
9633 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9635 MonoClass *nested = method->klass->nested_in;
9637 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9640 nested = nested->nested_in;
9647 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9649 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9651 MonoClass *nested = method->klass->nested_in;
9653 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9656 nested = nested->nested_in;
9661 * with generics calls to explicit interface implementations can be expressed
9662 * directly: the method is private, but we must allow it. This may be opening
9663 * a hole or the generics code should handle this differently.
9664 * Maybe just ensure the interface type is public.
9666 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9672 * mono_method_can_access_method_full:
9673 * @method: The caller method
9674 * @called: The called method
9675 * @context_klass: The static type on stack of the owner @called object used
9677 * This function must be used with instance calls, as they have more strict family accessibility.
9678 * It can be used with static methods, but context_klass should be NULL.
9680 * Returns: TRUE if caller have proper visibility and acessibility to @called
9683 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9685 MonoClass *access_class = method->klass;
9686 MonoClass *member_class = called->klass;
9687 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9689 MonoClass *nested = access_class->nested_in;
9691 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9694 nested = nested->nested_in;
9701 can = can_access_type (access_class, member_class);
9703 MonoClass *nested = access_class->nested_in;
9705 can = can_access_type (nested, member_class);
9708 nested = nested->nested_in;
9715 if (called->is_inflated) {
9716 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9717 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9726 * mono_method_can_access_field_full:
9727 * @method: The caller method
9728 * @field: The accessed field
9729 * @context_klass: The static type on stack of the owner @field object used
9731 * This function must be used with instance fields, as they have more strict family accessibility.
9732 * It can be used with static fields, but context_klass should be NULL.
9734 * Returns: TRUE if caller have proper visibility and acessibility to @field
9737 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9739 MonoClass *access_class = method->klass;
9740 MonoClass *member_class = field->parent;
9741 /* FIXME: check all overlapping fields */
9742 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9744 MonoClass *nested = access_class->nested_in;
9746 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9749 nested = nested->nested_in;
9756 can = can_access_type (access_class, member_class);
9758 MonoClass *nested = access_class->nested_in;
9760 can = can_access_type (nested, member_class);
9763 nested = nested->nested_in;
9773 * mono_class_can_access_class:
9774 * @source_class: The source class
9775 * @target_class: The accessed class
9777 * This function returns is @target_class is visible to @source_class
9779 * Returns: TRUE if source have proper visibility and acessibility to target
9782 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9784 return can_access_type (source_class, target_class);
9788 * mono_type_is_valid_enum_basetype:
9789 * @type: The MonoType to check
9791 * Returns: TRUE if the type can be used as the basetype of an enum
9793 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9794 switch (type->type) {
9797 case MONO_TYPE_BOOLEAN:
9800 case MONO_TYPE_CHAR:
9813 * mono_class_is_valid_enum:
9814 * @klass: An enum class to be validated
9816 * This method verify the required properties an enum should have.
9818 * Returns: TRUE if the informed enum class is valid
9820 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9821 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9822 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9824 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9825 MonoClassField * field;
9826 gpointer iter = NULL;
9827 gboolean found_base_field = FALSE;
9829 g_assert (klass->enumtype);
9830 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9831 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9835 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9838 while ((field = mono_class_get_fields (klass, &iter))) {
9839 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9840 if (found_base_field)
9842 found_base_field = TRUE;
9843 if (!mono_type_is_valid_enum_basetype (field->type))
9848 if (!found_base_field)
9851 if (klass->method.count > 0)
9858 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9860 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
9864 * mono_class_setup_interface_id:
9866 * Initializes MonoClass::interface_id if required.
9868 * LOCKING: Acquires the loader lock.
9871 mono_class_setup_interface_id (MonoClass *class)
9873 mono_loader_lock ();
9874 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
9875 class->interface_id = mono_get_unique_iid (class);
9876 mono_loader_unlock ();
9880 * mono_class_alloc_ext:
9882 * Allocate klass->ext if not already done.
9883 * LOCKING: Assumes the loader lock is held.
9886 mono_class_alloc_ext (MonoClass *klass)
9889 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
9890 class_ext_size += sizeof (MonoClassExt);
9895 * mono_class_setup_interfaces:
9897 * Initialize class->interfaces/interfaces_count.
9898 * LOCKING: Acquires the loader lock.
9899 * This function can fail the type.
9902 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
9906 mono_error_init (error);
9908 if (klass->interfaces_inited)
9911 mono_loader_lock ();
9913 if (klass->interfaces_inited) {
9914 mono_loader_unlock ();
9918 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
9921 /* generic IList, ICollection, IEnumerable */
9922 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
9923 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
9925 args [0] = &klass->element_class->byval_arg;
9926 klass->interfaces [0] = mono_class_bind_generic_parameters (
9927 mono_defaults.generic_ilist_class, 1, args, FALSE);
9928 if (klass->interface_count > 1)
9929 klass->interfaces [1] = mono_class_bind_generic_parameters (
9930 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
9931 } else if (klass->generic_class) {
9932 MonoClass *gklass = klass->generic_class->container_class;
9934 klass->interface_count = gklass->interface_count;
9935 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
9936 for (i = 0; i < klass->interface_count; i++) {
9937 klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
9938 if (!mono_error_ok (error)) {
9939 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
9940 klass->interfaces = NULL;
9946 mono_memory_barrier ();
9948 klass->interfaces_inited = TRUE;
9950 mono_loader_unlock ();
9954 mono_field_resolve_type (MonoClassField *field, MonoError *error)
9956 MonoClass *class = field->parent;
9957 MonoImage *image = class->image;
9958 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
9959 int field_idx = field - class->fields;
9961 mono_error_init (error);
9964 MonoClassField *gfield = >d->fields [field_idx];
9965 MonoType *gtype = mono_field_get_type_checked (gfield, error);
9966 if (!mono_error_ok (error)) {
9967 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
9968 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
9972 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
9973 if (!mono_error_ok (error)) {
9974 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
9975 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
9980 guint32 cols [MONO_FIELD_SIZE];
9981 MonoGenericContainer *container = NULL;
9982 int idx = class->field.first + field_idx;
9984 /*FIXME, in theory we do not lazy load SRE fields*/
9985 g_assert (!image->dynamic);
9987 if (class->generic_container) {
9988 container = class->generic_container;
9990 container = gtd->generic_container;
9991 g_assert (container);
9994 /* class->field.first and idx points into the fieldptr table */
9995 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
9997 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
9998 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
9999 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10003 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10005 mono_metadata_decode_value (sig, &sig);
10006 /* FIELD signature == 0x06 */
10007 g_assert (*sig == 0x06);
10008 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10010 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10015 mono_field_resolve_flags (MonoClassField *field)
10017 MonoClass *class = field->parent;
10018 MonoImage *image = class->image;
10019 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10020 int field_idx = field - class->fields;
10024 MonoClassField *gfield = >d->fields [field_idx];
10025 return mono_field_get_flags (gfield);
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 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10037 * mono_class_setup_basic_field_info:
10038 * @class: The class to initialize
10040 * Initializes the class->fields array of fields.
10041 * Aquires the loader lock.
10044 mono_class_setup_basic_field_info_locking (MonoClass *class)
10046 mono_loader_lock ();
10047 mono_class_setup_basic_field_info (class);
10048 mono_loader_unlock ();
10052 * mono_class_get_fields_lazy:
10053 * @klass: the MonoClass to act on
10055 * This routine is an iterator routine for retrieving the fields in a class.
10056 * Only minimal information about fields are loaded. Accessors must be used
10057 * for all MonoClassField returned.
10059 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10060 * iterate over all of the elements. When no more values are
10061 * available, the return value is NULL.
10063 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10066 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10068 MonoClassField* field;
10072 mono_class_setup_basic_field_info_locking (klass);
10073 if (!klass->fields)
10075 /* start from the first */
10076 if (klass->field.count) {
10077 return *iter = &klass->fields [0];
10085 if (field < &klass->fields [klass->field.count]) {
10086 return *iter = field;
10092 mono_class_full_name (MonoClass *klass)
10094 return mono_type_full_name (&klass->byval_arg);