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 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 */
5336 #endif /*DISABLE_COM*/
5339 * LOCKING: this assumes the loader lock is held
5342 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5344 gboolean system_namespace;
5345 gboolean is_corlib = mono_is_corlib_image (class->image);
5347 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5349 /* if root of the hierarchy */
5350 if (system_namespace && !strcmp (class->name, "Object")) {
5351 class->parent = NULL;
5352 class->instance_size = sizeof (MonoObject);
5355 if (!strcmp (class->name, "<Module>")) {
5356 class->parent = NULL;
5357 class->instance_size = 0;
5361 if (!MONO_CLASS_IS_INTERFACE (class)) {
5362 /* Imported COM Objects always derive from __ComObject. */
5364 if (MONO_CLASS_IS_IMPORT (class)) {
5365 init_com_from_comimport (class);
5366 if (parent == mono_defaults.object_class)
5367 parent = mono_class_get_com_object_class ();
5371 /* set the parent to something useful and safe, but mark the type as broken */
5372 parent = mono_defaults.object_class;
5373 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5376 class->parent = parent;
5378 if (parent->generic_class && !parent->name) {
5380 * If the parent is a generic instance, we may get
5381 * called before it is fully initialized, especially
5382 * before it has its name.
5387 #ifndef DISABLE_REMOTING
5388 class->marshalbyref = parent->marshalbyref;
5389 class->contextbound = parent->contextbound;
5392 class->delegate = parent->delegate;
5394 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5395 mono_class_set_is_com_object (class);
5397 if (system_namespace) {
5398 #ifndef DISABLE_REMOTING
5399 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5400 class->marshalbyref = 1;
5402 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5403 class->contextbound = 1;
5405 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5406 class->delegate = 1;
5409 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5410 (strcmp (class->parent->name_space, "System") == 0)))
5411 class->valuetype = 1;
5412 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5413 class->valuetype = class->enumtype = 1;
5415 /*class->enumtype = class->parent->enumtype; */
5417 /* initialize com types if COM interfaces are present */
5419 if (MONO_CLASS_IS_IMPORT (class))
5420 init_com_from_comimport (class);
5422 class->parent = NULL;
5428 * mono_class_setup_supertypes:
5431 * Build the data structure needed to make fast type checks work.
5432 * This currently sets two fields in @class:
5433 * - idepth: distance between @class and System.Object in the type
5435 * - supertypes: array of classes: each element has a class in the hierarchy
5436 * starting from @class up to System.Object
5438 * LOCKING: this assumes the loader lock is held
5441 mono_class_setup_supertypes (MonoClass *class)
5444 MonoClass **supertypes;
5446 if (class->supertypes)
5449 if (class->parent && !class->parent->supertypes)
5450 mono_class_setup_supertypes (class->parent);
5452 class->idepth = class->parent->idepth + 1;
5456 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5457 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5459 if (class->parent) {
5460 supertypes [class->idepth - 1] = class;
5461 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5463 supertypes [0] = class;
5466 mono_atomic_store_release (&class->supertypes, supertypes);
5470 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5472 MonoClass *gtd = (MonoClass*)user_data;
5473 /* Only try to fix generic instances of @gtd */
5474 if (gclass->generic_class->container_class != gtd)
5477 /* Check if the generic instance has no parent. */
5478 if (gtd->parent && !gclass->parent)
5479 mono_generic_class_setup_parent (gclass, gtd);
5485 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5487 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5488 mono_error_set_type_load_class (error, class, msg);
5492 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5494 MonoLoaderError *lerror = mono_loader_get_last_error ();
5497 set_failure_from_loader_error (class, lerror);
5498 mono_error_set_from_loader_error (error);
5502 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5503 mono_error_set_type_load_class (error, class, msg);
5508 * mono_class_create_from_typedef:
5509 * @image: image where the token is valid
5510 * @type_token: typedef token
5511 * @error: used to return any error found while creating the type
5513 * Create the MonoClass* representing the specified type token.
5514 * @type_token must be a TypeDef token.
5516 * FIXME: don't return NULL on failure, just the the caller figure it out.
5519 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5521 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5522 MonoClass *class, *parent = NULL;
5523 guint32 cols [MONO_TYPEDEF_SIZE];
5524 guint32 cols_next [MONO_TYPEDEF_SIZE];
5525 guint tidx = mono_metadata_token_index (type_token);
5526 MonoGenericContext *context = NULL;
5527 const char *name, *nspace;
5529 MonoClass **interfaces;
5530 guint32 field_last, method_last;
5531 guint32 nesting_tokeen;
5533 mono_error_init (error);
5535 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5536 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5537 g_assert (!mono_loader_get_last_error ());
5541 mono_loader_lock ();
5543 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5544 mono_loader_unlock ();
5545 g_assert (!mono_loader_get_last_error ());
5549 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5551 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5552 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5554 class = mono_image_alloc0 (image, sizeof (MonoClass));
5557 class->name_space = nspace;
5559 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5561 class->image = image;
5562 class->type_token = type_token;
5563 class->flags = cols [MONO_TYPEDEF_FLAGS];
5565 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5567 classes_size += sizeof (MonoClass);
5570 * Check whether we're a generic type definition.
5572 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5573 if (class->generic_container) {
5574 class->is_generic = 1;
5575 class->generic_container->owner.klass = class;
5576 context = &class->generic_container->context;
5579 if (class->generic_container)
5580 enable_gclass_recording ();
5582 if (cols [MONO_TYPEDEF_EXTENDS]) {
5584 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5586 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5587 /*WARNING: this must satisfy mono_metadata_type_hash*/
5588 class->this_arg.byref = 1;
5589 class->this_arg.data.klass = class;
5590 class->this_arg.type = MONO_TYPE_CLASS;
5591 class->byval_arg.data.klass = class;
5592 class->byval_arg.type = MONO_TYPE_CLASS;
5594 parent = mono_class_get_full (image, parent_token, context);
5596 if (parent == NULL) {
5597 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5598 goto parent_failure;
5601 for (tmp = parent; tmp; tmp = tmp->parent) {
5603 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5604 goto parent_failure;
5606 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5607 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5608 goto parent_failure;
5613 mono_class_setup_parent (class, parent);
5615 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5616 mono_class_setup_mono_type (class);
5618 if (class->generic_container)
5619 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5622 * This might access class->byval_arg for recursion generated by generic constraints,
5623 * so it has to come after setup_mono_type ().
5625 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5626 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5627 if (!mono_error_ok (error)) {
5628 /*FIXME implement a mono_class_set_failure_from_mono_error */
5629 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5630 mono_loader_unlock ();
5631 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5632 g_assert (!mono_loader_get_last_error ());
5637 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5641 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5645 class->cast_class = class->element_class = class;
5647 if (!class->enumtype) {
5648 if (!mono_metadata_interfaces_from_typedef_full (
5649 image, type_token, &interfaces, &icount, FALSE, context)){
5650 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5651 mono_loader_unlock ();
5652 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5656 class->interfaces = interfaces;
5657 class->interface_count = icount;
5658 class->interfaces_inited = 1;
5661 /*g_print ("Load class %s\n", name);*/
5664 * Compute the field and method lists
5666 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5667 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5669 if (tt->rows > tidx){
5670 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5671 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5672 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5674 field_last = image->tables [MONO_TABLE_FIELD].rows;
5675 method_last = image->tables [MONO_TABLE_METHOD].rows;
5678 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5679 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5680 class->field.count = field_last - class->field.first;
5682 class->field.count = 0;
5684 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5685 class->method.count = method_last - class->method.first;
5687 class->method.count = 0;
5689 /* reserve space to store vector pointer in arrays */
5690 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5691 class->instance_size += 2 * sizeof (gpointer);
5692 g_assert (class->field.count == 0);
5695 if (class->enumtype) {
5696 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5697 if (!enum_basetype) {
5698 /*set it to a default value as the whole runtime can't handle this to be null*/
5699 class->cast_class = class->element_class = mono_defaults.int32_class;
5700 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5701 mono_loader_unlock ();
5702 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5703 g_assert (!mono_loader_get_last_error ());
5706 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5710 * If we're a generic type definition, load the constraints.
5711 * We must do this after the class has been constructed to make certain recursive scenarios
5714 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5715 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5716 mono_loader_unlock ();
5717 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5718 g_assert (!mono_loader_get_last_error ());
5722 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5723 if (!strncmp (name, "Vector", 6))
5724 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");
5727 mono_loader_unlock ();
5729 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5730 g_assert (!mono_loader_get_last_error ());
5735 mono_class_setup_mono_type (class);
5736 mono_loader_unlock ();
5737 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5738 g_assert (!mono_loader_get_last_error ());
5742 /** is klass Nullable<T>? */
5744 mono_class_is_nullable (MonoClass *klass)
5746 return klass->generic_class != NULL &&
5747 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5751 /** if klass is T? return T */
5753 mono_class_get_nullable_param (MonoClass *klass)
5755 g_assert (mono_class_is_nullable (klass));
5756 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5760 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5764 MonoGenericClass *gclass = klass->generic_class;
5766 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5767 if (!mono_error_ok (&error)) {
5768 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5769 klass->parent = mono_defaults.object_class;
5770 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5771 mono_error_cleanup (&error);
5775 mono_class_setup_parent (klass, klass->parent);
5777 if (klass->enumtype) {
5778 klass->cast_class = gtd->cast_class;
5779 klass->element_class = gtd->element_class;
5785 * Create the `MonoClass' for an instantiation of a generic type.
5786 * We only do this if we actually need it.
5789 mono_generic_class_get_class (MonoGenericClass *gclass)
5791 MonoClass *klass, *gklass;
5793 if (gclass->cached_class)
5794 return gclass->cached_class;
5796 mono_loader_lock ();
5797 if (gclass->cached_class) {
5798 mono_loader_unlock ();
5799 return gclass->cached_class;
5802 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5804 gklass = gclass->container_class;
5806 if (record_gclass_instantiation > 0)
5807 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5809 if (gklass->nested_in) {
5810 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5811 klass->nested_in = gklass->nested_in;
5814 klass->name = gklass->name;
5815 klass->name_space = gklass->name_space;
5817 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5819 klass->image = gklass->image;
5820 klass->flags = gklass->flags;
5821 klass->type_token = gklass->type_token;
5822 klass->field.count = gklass->field.count;
5824 klass->is_inflated = 1;
5825 klass->generic_class = gclass;
5827 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5828 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5829 klass->this_arg.byref = TRUE;
5830 klass->enumtype = gklass->enumtype;
5831 klass->valuetype = gklass->valuetype;
5833 klass->cast_class = klass->element_class = klass;
5835 if (mono_class_is_nullable (klass))
5836 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5839 * We're not interested in the nested classes of a generic instance.
5840 * We use the generic type definition to look for nested classes.
5843 mono_generic_class_setup_parent (klass, gklass);
5845 if (gclass->is_dynamic) {
5848 mono_class_setup_supertypes (klass);
5850 if (klass->enumtype) {
5852 * For enums, gklass->fields might not been set, but instance_size etc. is
5853 * already set in mono_reflection_create_internal_class (). For non-enums,
5854 * these will be computed normally in mono_class_layout_fields ().
5856 klass->instance_size = gklass->instance_size;
5857 klass->sizes.class_size = gklass->sizes.class_size;
5858 mono_memory_barrier ();
5859 klass->size_inited = 1;
5863 mono_memory_barrier ();
5864 gclass->cached_class = klass;
5866 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5868 inflated_classes ++;
5869 inflated_classes_size += sizeof (MonoClass);
5871 mono_loader_unlock ();
5877 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5879 MonoClass *klass, **ptr;
5881 MonoGenericContainer *container = mono_generic_param_owner (param);
5885 image = mono_defaults.corlib;
5887 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5888 classes_size += sizeof (MonoClass);
5891 klass->name = pinfo->name;
5893 int n = mono_generic_param_num (param);
5894 klass->name = mono_image_alloc0 (image, 16);
5895 sprintf ((char*)klass->name, "%d", n);
5900 MonoMethod *omethod = container->owner.method;
5901 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5903 MonoClass *oklass = container->owner.klass;
5904 klass->name_space = oklass ? oklass->name_space : "";
5907 klass->name_space = "";
5910 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5914 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5918 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5919 klass->parent = pinfo->constraints [0];
5921 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5922 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5924 klass->parent = mono_defaults.object_class;
5927 if (count - pos > 0) {
5928 klass->interface_count = count - pos;
5929 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5930 klass->interfaces_inited = TRUE;
5931 for (i = pos; i < count; i++)
5932 klass->interfaces [i - pos] = pinfo->constraints [i];
5935 klass->image = image;
5937 klass->inited = TRUE;
5938 klass->cast_class = klass->element_class = klass;
5939 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5941 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5942 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5943 klass->this_arg.byref = TRUE;
5945 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5946 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5948 /*Init these fields to sane values*/
5949 klass->min_align = 1;
5950 klass->instance_size = sizeof (gpointer);
5951 mono_memory_barrier ();
5952 klass->size_inited = 1;
5954 mono_class_setup_supertypes (klass);
5956 if (count - pos > 0) {
5957 mono_class_setup_vtable (klass->parent);
5958 if (klass->parent->exception_type)
5959 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
5961 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
5967 #define FAST_CACHE_SIZE 16
5970 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
5972 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
5973 MonoImage *image = param->image;
5978 if (n < FAST_CACHE_SIZE) {
5980 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
5982 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
5984 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
5985 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
5990 * LOCKING: Acquires the loader lock.
5993 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
5995 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
5996 MonoImage *image = param->image;
6001 if (n < FAST_CACHE_SIZE) {
6003 /* No locking needed */
6004 if (!image->mvar_cache_fast)
6005 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6006 image->mvar_cache_fast [n] = klass;
6008 if (!image->var_cache_fast)
6009 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6010 image->var_cache_fast [n] = klass;
6014 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6016 mono_loader_lock ();
6017 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6019 ht = g_hash_table_new (NULL, NULL);
6020 mono_memory_barrier ();
6022 image->mvar_cache_slow = ht;
6024 image->var_cache_slow = ht;
6026 mono_loader_unlock ();
6029 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6033 * LOCKING: Acquires the loader lock.
6036 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6038 MonoGenericContainer *container = mono_generic_param_owner (param);
6039 MonoGenericParamInfo *pinfo;
6042 mono_loader_lock ();
6045 pinfo = mono_generic_param_info (param);
6046 if (pinfo->pklass) {
6047 mono_loader_unlock ();
6048 return pinfo->pklass;
6054 klass = get_anon_gparam_class (param, is_mvar);
6056 mono_loader_unlock ();
6061 if (!image && container) {
6063 MonoMethod *method = container->owner.method;
6064 image = (method && method->klass) ? method->klass->image : NULL;
6066 MonoClass *klass = container->owner.klass;
6067 // FIXME: 'klass' should not be null
6068 // But, monodis creates GenericContainers without associating a owner to it
6069 image = klass ? klass->image : NULL;
6073 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6075 mono_memory_barrier ();
6078 pinfo->pklass = klass;
6080 set_anon_gparam_class (param, is_mvar, klass);
6082 mono_loader_unlock ();
6084 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6085 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6091 mono_ptr_class_get (MonoType *type)
6094 MonoClass *el_class;
6098 el_class = mono_class_from_mono_type (type);
6099 image = el_class->image;
6101 mono_loader_lock ();
6103 if (!image->ptr_cache)
6104 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6106 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6107 mono_loader_unlock ();
6110 result = mono_image_alloc0 (image, sizeof (MonoClass));
6112 classes_size += sizeof (MonoClass);
6114 result->parent = NULL; /* no parent for PTR types */
6115 result->name_space = el_class->name_space;
6116 name = g_strdup_printf ("%s*", el_class->name);
6117 result->name = mono_image_strdup (image, name);
6120 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6122 result->image = el_class->image;
6123 result->inited = TRUE;
6124 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6125 /* Can pointers get boxed? */
6126 result->instance_size = sizeof (gpointer);
6127 result->cast_class = result->element_class = el_class;
6128 result->blittable = TRUE;
6130 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6131 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6132 result->this_arg.byref = TRUE;
6134 mono_class_setup_supertypes (result);
6136 g_hash_table_insert (image->ptr_cache, el_class, result);
6138 mono_loader_unlock ();
6140 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6146 mono_fnptr_class_get (MonoMethodSignature *sig)
6149 static GHashTable *ptr_hash = NULL;
6151 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6153 mono_loader_lock ();
6156 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6158 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6159 mono_loader_unlock ();
6162 result = g_new0 (MonoClass, 1);
6164 result->parent = NULL; /* no parent for PTR types */
6165 result->name_space = "System";
6166 result->name = "MonoFNPtrFakeClass";
6168 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6170 result->image = mono_defaults.corlib; /* need to fix... */
6171 result->inited = TRUE;
6172 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6173 /* Can pointers get boxed? */
6174 result->instance_size = sizeof (gpointer);
6175 result->cast_class = result->element_class = result;
6176 result->blittable = TRUE;
6178 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6179 result->this_arg.data.method = result->byval_arg.data.method = sig;
6180 result->this_arg.byref = TRUE;
6181 result->blittable = TRUE;
6183 mono_class_setup_supertypes (result);
6185 g_hash_table_insert (ptr_hash, sig, result);
6187 mono_loader_unlock ();
6189 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6195 mono_class_from_mono_type (MonoType *type)
6197 switch (type->type) {
6198 case MONO_TYPE_OBJECT:
6199 return type->data.klass? type->data.klass: mono_defaults.object_class;
6200 case MONO_TYPE_VOID:
6201 return type->data.klass? type->data.klass: mono_defaults.void_class;
6202 case MONO_TYPE_BOOLEAN:
6203 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6204 case MONO_TYPE_CHAR:
6205 return type->data.klass? type->data.klass: mono_defaults.char_class;
6207 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6209 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6211 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6213 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6215 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6217 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6219 return type->data.klass? type->data.klass: mono_defaults.int_class;
6221 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6223 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6225 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6227 return type->data.klass? type->data.klass: mono_defaults.single_class;
6229 return type->data.klass? type->data.klass: mono_defaults.double_class;
6230 case MONO_TYPE_STRING:
6231 return type->data.klass? type->data.klass: mono_defaults.string_class;
6232 case MONO_TYPE_TYPEDBYREF:
6233 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6234 case MONO_TYPE_ARRAY:
6235 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6237 return mono_ptr_class_get (type->data.type);
6238 case MONO_TYPE_FNPTR:
6239 return mono_fnptr_class_get (type->data.method);
6240 case MONO_TYPE_SZARRAY:
6241 return mono_array_class_get (type->data.klass, 1);
6242 case MONO_TYPE_CLASS:
6243 case MONO_TYPE_VALUETYPE:
6244 return type->data.klass;
6245 case MONO_TYPE_GENERICINST:
6246 return mono_generic_class_get_class (type->data.generic_class);
6248 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6249 case MONO_TYPE_MVAR:
6250 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6252 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6253 g_assert_not_reached ();
6260 * mono_type_retrieve_from_typespec
6261 * @image: context where the image is created
6262 * @type_spec: typespec token
6263 * @context: the generic context used to evaluate generic instantiations in
6266 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6268 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6270 mono_error_init (error);
6271 *did_inflate = FALSE;
6274 char *name = mono_class_name_from_token (image, type_spec);
6275 char *assembly = mono_assembly_name_from_token (image, type_spec);
6276 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6280 if (context && (context->class_inst || context->method_inst)) {
6281 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6283 if (!mono_error_ok (error))
6288 *did_inflate = TRUE;
6295 * mono_class_create_from_typespec
6296 * @image: context where the image is created
6297 * @type_spec: typespec token
6298 * @context: the generic context used to evaluate generic instantiations in
6301 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6304 gboolean inflated = FALSE;
6305 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6306 if (!mono_error_ok (error))
6308 ret = mono_class_from_mono_type (t);
6310 mono_metadata_free_type (t);
6315 * mono_bounded_array_class_get:
6316 * @element_class: element class
6317 * @rank: the dimension of the array class
6318 * @bounded: whenever the array has non-zero bounds
6320 * Returns: a class object describing the array with element type @element_type and
6324 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6328 MonoClass *parent = NULL;
6329 GSList *list, *rootlist = NULL;
6332 gboolean corlib_type = FALSE;
6334 g_assert (rank <= 255);
6337 /* bounded only matters for one-dimensional arrays */
6340 image = eclass->image;
6342 if (rank == 1 && !bounded) {
6344 * This case is very frequent not just during compilation because of calls
6345 * from mono_class_from_mono_type (), mono_array_new (),
6346 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6348 EnterCriticalSection (&image->szarray_cache_lock);
6349 if (!image->szarray_cache)
6350 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6351 class = g_hash_table_lookup (image->szarray_cache, eclass);
6352 LeaveCriticalSection (&image->szarray_cache_lock);
6356 mono_loader_lock ();
6358 mono_loader_lock ();
6360 if (!image->array_cache)
6361 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6363 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6364 for (; list; list = list->next) {
6366 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6367 mono_loader_unlock ();
6374 /* for the building corlib use System.Array from it */
6375 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6376 parent = mono_class_from_name (image, "System", "Array");
6379 parent = mono_defaults.array_class;
6380 if (!parent->inited)
6381 mono_class_init (parent);
6384 class = mono_image_alloc0 (image, sizeof (MonoClass));
6386 class->image = image;
6387 class->name_space = eclass->name_space;
6388 nsize = strlen (eclass->name);
6389 name = g_malloc (nsize + 2 + rank + 1);
6390 memcpy (name, eclass->name, nsize);
6393 memset (name + nsize + 1, ',', rank - 1);
6395 name [nsize + rank] = '*';
6396 name [nsize + rank + bounded] = ']';
6397 name [nsize + rank + bounded + 1] = 0;
6398 class->name = mono_image_strdup (image, name);
6401 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6403 classes_size += sizeof (MonoClass);
6405 class->type_token = 0;
6406 /* all arrays are marked serializable and sealed, bug #42779 */
6407 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6408 class->parent = parent;
6409 class->instance_size = mono_class_instance_size (class->parent);
6411 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6412 /*Arrays of those two types are invalid.*/
6413 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6414 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6415 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6416 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6417 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6419 /* element_size -1 is ok as this is not an instantitable type*/
6420 class->sizes.element_size = -1;
6422 class->sizes.element_size = mono_class_array_element_size (eclass);
6424 mono_class_setup_supertypes (class);
6426 if (eclass->generic_class)
6427 mono_class_init (eclass);
6428 if (!eclass->size_inited)
6429 mono_class_setup_fields (eclass);
6430 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6431 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6433 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6437 if (eclass->enumtype)
6438 class->cast_class = eclass->element_class;
6440 class->cast_class = eclass;
6442 switch (class->cast_class->byval_arg.type) {
6444 class->cast_class = mono_defaults.byte_class;
6447 class->cast_class = mono_defaults.int16_class;
6450 #if SIZEOF_VOID_P == 4
6454 class->cast_class = mono_defaults.int32_class;
6457 #if SIZEOF_VOID_P == 8
6461 class->cast_class = mono_defaults.int64_class;
6465 class->element_class = eclass;
6467 if ((rank > 1) || bounded) {
6468 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6469 class->byval_arg.type = MONO_TYPE_ARRAY;
6470 class->byval_arg.data.array = at;
6471 at->eklass = eclass;
6473 /* FIXME: complete.... */
6475 class->byval_arg.type = MONO_TYPE_SZARRAY;
6476 class->byval_arg.data.klass = eclass;
6478 class->this_arg = class->byval_arg;
6479 class->this_arg.byref = 1;
6484 class->generic_container = eclass->generic_container;
6486 if (rank == 1 && !bounded) {
6487 MonoClass *prev_class;
6489 EnterCriticalSection (&image->szarray_cache_lock);
6490 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6492 /* Someone got in before us */
6495 g_hash_table_insert (image->szarray_cache, eclass, class);
6496 LeaveCriticalSection (&image->szarray_cache_lock);
6498 list = g_slist_append (rootlist, class);
6499 g_hash_table_insert (image->array_cache, eclass, list);
6502 mono_loader_unlock ();
6504 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6510 * mono_array_class_get:
6511 * @element_class: element class
6512 * @rank: the dimension of the array class
6514 * Returns: a class object describing the array with element type @element_type and
6518 mono_array_class_get (MonoClass *eclass, guint32 rank)
6520 return mono_bounded_array_class_get (eclass, rank, FALSE);
6524 * mono_class_instance_size:
6527 * Returns: the size of an object instance
6530 mono_class_instance_size (MonoClass *klass)
6532 if (!klass->size_inited)
6533 mono_class_init (klass);
6535 return klass->instance_size;
6539 * mono_class_min_align:
6542 * Returns: minimm alignment requirements
6545 mono_class_min_align (MonoClass *klass)
6547 if (!klass->size_inited)
6548 mono_class_init (klass);
6550 return klass->min_align;
6554 * mono_class_value_size:
6557 * This function is used for value types, and return the
6558 * space and the alignment to store that kind of value object.
6560 * Returns: the size of a value of kind @klass
6563 mono_class_value_size (MonoClass *klass, guint32 *align)
6567 /* fixme: check disable, because we still have external revereces to
6568 * mscorlib and Dummy Objects
6570 /*g_assert (klass->valuetype);*/
6572 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6575 *align = klass->min_align;
6581 * mono_class_data_size:
6584 * Returns: the size of the static class data
6587 mono_class_data_size (MonoClass *klass)
6590 mono_class_init (klass);
6592 /* in arrays, sizes.class_size is unioned with element_size
6593 * and arrays have no static fields
6597 return klass->sizes.class_size;
6601 * Auxiliary routine to mono_class_get_field
6603 * Takes a field index instead of a field token.
6605 static MonoClassField *
6606 mono_class_get_field_idx (MonoClass *class, int idx)
6608 mono_class_setup_fields_locking (class);
6609 if (class->exception_type)
6613 if (class->image->uncompressed_metadata) {
6615 * class->field.first points to the FieldPtr table, while idx points into the
6616 * Field table, so we have to do a search.
6618 /*FIXME this is broken for types with multiple fields with the same name.*/
6619 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6622 for (i = 0; i < class->field.count; ++i)
6623 if (mono_field_get_name (&class->fields [i]) == name)
6624 return &class->fields [i];
6625 g_assert_not_reached ();
6627 if (class->field.count) {
6628 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6629 return &class->fields [idx - class->field.first];
6633 class = class->parent;
6639 * mono_class_get_field:
6640 * @class: the class to lookup the field.
6641 * @field_token: the field token
6643 * Returns: A MonoClassField representing the type and offset of
6644 * the field, or a NULL value if the field does not belong to this
6648 mono_class_get_field (MonoClass *class, guint32 field_token)
6650 int idx = mono_metadata_token_index (field_token);
6652 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6654 return mono_class_get_field_idx (class, idx - 1);
6658 * mono_class_get_field_from_name:
6659 * @klass: the class to lookup the field.
6660 * @name: the field name
6662 * Search the class @klass and it's parents for a field with the name @name.
6664 * Returns: the MonoClassField pointer of the named field or NULL
6667 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6669 return mono_class_get_field_from_name_full (klass, name, NULL);
6673 * mono_class_get_field_from_name_full:
6674 * @klass: the class to lookup the field.
6675 * @name: the field name
6676 * @type: the type of the fields. This optional.
6678 * Search the class @klass and it's parents for a field with the name @name and type @type.
6680 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6681 * of its generic type definition.
6683 * Returns: the MonoClassField pointer of the named field or NULL
6686 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6690 mono_class_setup_fields_locking (klass);
6691 if (klass->exception_type)
6695 for (i = 0; i < klass->field.count; ++i) {
6696 MonoClassField *field = &klass->fields [i];
6698 if (strcmp (name, mono_field_get_name (field)) != 0)
6702 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6703 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6708 klass = klass->parent;
6714 * mono_class_get_field_token:
6715 * @field: the field we need the token of
6717 * Get the token of a field. Note that the tokesn is only valid for the image
6718 * the field was loaded from. Don't use this function for fields in dynamic types.
6720 * Returns: the token representing the field in the image it was loaded from.
6723 mono_class_get_field_token (MonoClassField *field)
6725 MonoClass *klass = field->parent;
6728 mono_class_setup_fields_locking (klass);
6733 for (i = 0; i < klass->field.count; ++i) {
6734 if (&klass->fields [i] == field) {
6735 int idx = klass->field.first + i + 1;
6737 if (klass->image->uncompressed_metadata)
6738 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6739 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6742 klass = klass->parent;
6745 g_assert_not_reached ();
6750 mono_field_get_index (MonoClassField *field)
6752 int index = field - field->parent->fields;
6754 g_assert (index >= 0 && index < field->parent->field.count);
6760 * mono_class_get_field_default_value:
6762 * Return the default value of the field as a pointer into the metadata blob.
6765 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6768 guint32 constant_cols [MONO_CONSTANT_SIZE];
6770 MonoClass *klass = field->parent;
6772 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6774 if (!klass->ext || !klass->ext->field_def_values) {
6775 mono_loader_lock ();
6776 mono_class_alloc_ext (klass);
6777 if (!klass->ext->field_def_values)
6778 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6779 mono_loader_unlock ();
6782 field_index = mono_field_get_index (field);
6784 if (!klass->ext->field_def_values [field_index].data) {
6785 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6789 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6791 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6792 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6793 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6796 *def_type = klass->ext->field_def_values [field_index].def_type;
6797 return klass->ext->field_def_values [field_index].data;
6801 mono_property_get_index (MonoProperty *prop)
6803 int index = prop - prop->parent->ext->properties;
6805 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6811 * mono_class_get_property_default_value:
6813 * Return the default value of the field as a pointer into the metadata blob.
6816 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6819 guint32 constant_cols [MONO_CONSTANT_SIZE];
6820 MonoClass *klass = property->parent;
6822 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6824 * We don't cache here because it is not used by C# so it's quite rare, but
6825 * we still do the lookup in klass->ext because that is where the data
6826 * is stored for dynamic assemblies.
6829 if (klass->image->dynamic) {
6830 int prop_index = mono_property_get_index (property);
6831 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6832 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6833 return klass->ext->prop_def_values [prop_index].data;
6837 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6841 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6842 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6843 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6847 mono_class_get_event_token (MonoEvent *event)
6849 MonoClass *klass = event->parent;
6854 for (i = 0; i < klass->ext->event.count; ++i) {
6855 if (&klass->ext->events [i] == event)
6856 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6859 klass = klass->parent;
6862 g_assert_not_reached ();
6867 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6871 gpointer iter = NULL;
6872 while ((p = mono_class_get_properties (klass, &iter))) {
6873 if (! strcmp (name, p->name))
6876 klass = klass->parent;
6882 mono_class_get_property_token (MonoProperty *prop)
6884 MonoClass *klass = prop->parent;
6888 gpointer iter = NULL;
6889 while ((p = mono_class_get_properties (klass, &iter))) {
6890 if (&klass->ext->properties [i] == prop)
6891 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6895 klass = klass->parent;
6898 g_assert_not_reached ();
6903 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6905 const char *name, *nspace;
6907 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6909 switch (type_token & 0xff000000){
6910 case MONO_TOKEN_TYPE_DEF: {
6911 guint32 cols [MONO_TYPEDEF_SIZE];
6912 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6913 guint tidx = mono_metadata_token_index (type_token);
6915 if (tidx > tt->rows)
6916 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6918 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6919 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6920 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6921 if (strlen (nspace) == 0)
6922 return g_strdup_printf ("%s", name);
6924 return g_strdup_printf ("%s.%s", nspace, name);
6927 case MONO_TOKEN_TYPE_REF: {
6929 guint32 cols [MONO_TYPEREF_SIZE];
6930 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6931 guint tidx = mono_metadata_token_index (type_token);
6934 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6936 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6937 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6938 mono_error_cleanup (&error);
6942 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
6943 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
6944 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
6945 if (strlen (nspace) == 0)
6946 return g_strdup_printf ("%s", name);
6948 return g_strdup_printf ("%s.%s", nspace, name);
6951 case MONO_TOKEN_TYPE_SPEC:
6952 return g_strdup_printf ("Typespec 0x%08x", type_token);
6954 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6959 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
6962 return g_strdup_printf ("DynamicAssembly %s", image->name);
6964 switch (type_token & 0xff000000){
6965 case MONO_TOKEN_TYPE_DEF:
6966 if (image->assembly)
6967 return mono_stringify_assembly_name (&image->assembly->aname);
6968 else if (image->assembly_name)
6969 return g_strdup (image->assembly_name);
6970 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
6971 case MONO_TOKEN_TYPE_REF: {
6973 MonoAssemblyName aname;
6974 guint32 cols [MONO_TYPEREF_SIZE];
6975 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6976 guint32 idx = mono_metadata_token_index (type_token);
6979 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6981 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
6982 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6983 mono_error_cleanup (&error);
6986 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
6988 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
6989 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
6990 case MONO_RESOLTION_SCOPE_MODULE:
6992 return g_strdup ("");
6993 case MONO_RESOLTION_SCOPE_MODULEREF:
6995 return g_strdup ("");
6996 case MONO_RESOLTION_SCOPE_TYPEREF:
6998 return g_strdup ("");
6999 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7000 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7001 return mono_stringify_assembly_name (&aname);
7003 g_assert_not_reached ();
7007 case MONO_TOKEN_TYPE_SPEC:
7009 return g_strdup ("");
7011 g_assert_not_reached ();
7018 * mono_class_get_full:
7019 * @image: the image where the class resides
7020 * @type_token: the token for the class
7021 * @context: the generic context used to evaluate generic instantiations in
7023 * Returns: the MonoClass that represents @type_token in @image
7026 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7029 MonoClass *class = NULL;
7031 if (image->dynamic) {
7032 int table = mono_metadata_token_table (type_token);
7034 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7035 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7038 return mono_lookup_dynamic_token (image, type_token, context);
7041 switch (type_token & 0xff000000){
7042 case MONO_TOKEN_TYPE_DEF:
7043 class = mono_class_create_from_typedef (image, type_token, &error);
7044 if (!mono_error_ok (&error)) {
7045 mono_loader_set_error_from_mono_error (&error);
7046 /*FIXME don't swallow the error message*/
7047 mono_error_cleanup (&error);
7051 case MONO_TOKEN_TYPE_REF:
7052 class = mono_class_from_typeref (image, type_token);
7054 case MONO_TOKEN_TYPE_SPEC:
7055 class = mono_class_create_from_typespec (image, type_token, context, &error);
7056 if (!mono_error_ok (&error)) {
7057 /*FIXME don't swallow the error message*/
7058 mono_error_cleanup (&error);
7062 g_warning ("unknown token type %x", type_token & 0xff000000);
7063 g_assert_not_reached ();
7067 char *name = mono_class_name_from_token (image, type_token);
7068 char *assembly = mono_assembly_name_from_token (image, type_token);
7069 mono_loader_set_error_type_load (name, assembly);
7079 * mono_type_get_full:
7080 * @image: the image where the type resides
7081 * @type_token: the token for the type
7082 * @context: the generic context used to evaluate generic instantiations in
7084 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7086 * Returns: the MonoType that represents @type_token in @image
7089 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7092 MonoType *type = NULL;
7093 gboolean inflated = FALSE;
7095 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7097 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7099 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7100 MonoClass *class = mono_class_get_full (image, type_token, context);
7101 return class ? mono_class_get_type (class) : NULL;
7104 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7106 if (!mono_error_ok (&error)) {
7107 /*FIXME don't swalloc the error message.*/
7108 char *name = mono_class_name_from_token (image, type_token);
7109 char *assembly = mono_assembly_name_from_token (image, type_token);
7111 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7113 mono_error_cleanup (&error);
7114 mono_loader_set_error_type_load (name, assembly);
7119 MonoType *tmp = type;
7120 type = mono_class_get_type (mono_class_from_mono_type (type));
7121 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7122 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7123 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7125 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7127 if (type->type != tmp->type)
7130 mono_metadata_free_type (tmp);
7137 mono_class_get (MonoImage *image, guint32 type_token)
7139 return mono_class_get_full (image, type_token, NULL);
7143 * mono_image_init_name_cache:
7145 * Initializes the class name cache stored in image->name_cache.
7147 * LOCKING: Acquires the corresponding image lock.
7150 mono_image_init_name_cache (MonoImage *image)
7152 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7153 guint32 cols [MONO_TYPEDEF_SIZE];
7156 guint32 i, visib, nspace_index;
7157 GHashTable *name_cache2, *nspace_table;
7159 mono_image_lock (image);
7161 if (image->name_cache) {
7162 mono_image_unlock (image);
7166 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7168 if (image->dynamic) {
7169 mono_image_unlock (image);
7173 /* Temporary hash table to avoid lookups in the nspace_table */
7174 name_cache2 = g_hash_table_new (NULL, NULL);
7176 for (i = 1; i <= t->rows; ++i) {
7177 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7178 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7180 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7181 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7183 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7185 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7186 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7188 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7189 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7190 if (!nspace_table) {
7191 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7192 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7193 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7196 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7199 /* Load type names from EXPORTEDTYPES table */
7201 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7202 guint32 cols [MONO_EXP_TYPE_SIZE];
7205 for (i = 0; i < t->rows; ++i) {
7206 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7207 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7208 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7210 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7211 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7212 if (!nspace_table) {
7213 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7214 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7215 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7218 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7222 g_hash_table_destroy (name_cache2);
7223 mono_image_unlock (image);
7226 /*FIXME Only dynamic assemblies should allow this operation.*/
7228 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7229 const char *name, guint32 index)
7231 GHashTable *nspace_table;
7232 GHashTable *name_cache;
7235 mono_image_lock (image);
7237 if (!image->name_cache)
7238 mono_image_init_name_cache (image);
7240 name_cache = image->name_cache;
7241 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7242 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7243 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7246 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7247 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7249 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7251 mono_image_unlock (image);
7260 find_nocase (gpointer key, gpointer value, gpointer user_data)
7262 char *name = (char*)key;
7263 FindUserData *data = (FindUserData*)user_data;
7265 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7266 data->value = value;
7270 * mono_class_from_name_case:
7271 * @image: The MonoImage where the type is looked up in
7272 * @name_space: the type namespace
7273 * @name: the type short name.
7275 * Obtains a MonoClass with a given namespace and a given name which
7276 * is located in the given MonoImage. The namespace and name
7277 * lookups are case insensitive.
7280 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7282 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7283 guint32 cols [MONO_TYPEDEF_SIZE];
7288 if (image->dynamic) {
7290 FindUserData user_data;
7292 mono_image_lock (image);
7294 if (!image->name_cache)
7295 mono_image_init_name_cache (image);
7297 user_data.key = name_space;
7298 user_data.value = NULL;
7299 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7301 if (user_data.value) {
7302 GHashTable *nspace_table = (GHashTable*)user_data.value;
7304 user_data.key = name;
7305 user_data.value = NULL;
7307 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7309 if (user_data.value)
7310 token = GPOINTER_TO_UINT (user_data.value);
7313 mono_image_unlock (image);
7316 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7322 /* add a cache if needed */
7323 for (i = 1; i <= t->rows; ++i) {
7324 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7325 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7327 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7328 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7330 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7332 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7333 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7334 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7335 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7341 return_nested_in (MonoClass *class, char *nested)
7344 char *s = strchr (nested, '/');
7345 gpointer iter = NULL;
7352 while ((found = mono_class_get_nested_types (class, &iter))) {
7353 if (strcmp (found->name, nested) == 0) {
7355 return return_nested_in (found, s);
7363 search_modules (MonoImage *image, const char *name_space, const char *name)
7365 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7366 MonoImage *file_image;
7371 * The EXPORTEDTYPES table only contains public types, so have to search the
7373 * Note: image->modules contains the contents of the MODULEREF table, while
7374 * the real module list is in the FILE table.
7376 for (i = 0; i < file_table->rows; i++) {
7377 guint32 cols [MONO_FILE_SIZE];
7378 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7379 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7382 file_image = mono_image_load_file_for_image (image, i + 1);
7384 class = mono_class_from_name (file_image, name_space, name);
7394 * mono_class_from_name:
7395 * @image: The MonoImage where the type is looked up in
7396 * @name_space: the type namespace
7397 * @name: the type short name.
7399 * Obtains a MonoClass with a given namespace and a given name which
7400 * is located in the given MonoImage.
7403 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7405 GHashTable *nspace_table;
7406 MonoImage *loaded_image;
7413 if ((nested = strchr (name, '/'))) {
7414 int pos = nested - name;
7415 int len = strlen (name);
7418 memcpy (buf, name, len + 1);
7420 nested = buf + pos + 1;
7424 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7425 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7426 gboolean res = get_class_from_name (image, name_space, name, &class);
7429 class = search_modules (image, name_space, name);
7431 return class ? return_nested_in (class, nested) : NULL;
7437 mono_image_lock (image);
7439 if (!image->name_cache)
7440 mono_image_init_name_cache (image);
7442 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7445 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7447 mono_image_unlock (image);
7449 if (!token && image->dynamic && image->modules) {
7450 /* Search modules as well */
7451 for (i = 0; i < image->module_count; ++i) {
7452 MonoImage *module = image->modules [i];
7454 class = mono_class_from_name (module, name_space, name);
7461 class = search_modules (image, name_space, name);
7469 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7470 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7471 guint32 cols [MONO_EXP_TYPE_SIZE];
7474 idx = mono_metadata_token_index (token);
7476 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7478 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7479 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7480 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7483 class = mono_class_from_name (loaded_image, name_space, name);
7485 return return_nested_in (class, nested);
7487 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7488 guint32 assembly_idx;
7490 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7492 mono_assembly_load_reference (image, assembly_idx - 1);
7493 g_assert (image->references [assembly_idx - 1]);
7494 if (image->references [assembly_idx - 1] == (gpointer)-1)
7497 /* FIXME: Cycle detection */
7498 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7500 g_error ("not yet implemented");
7504 token = MONO_TOKEN_TYPE_DEF | token;
7506 class = mono_class_get (image, token);
7508 return return_nested_in (class, nested);
7512 /*FIXME test for interfaces with variant generic arguments*/
7514 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7515 gboolean check_interfaces)
7517 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7518 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7520 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7523 for (i = 0; i < klass->interface_count; i ++) {
7524 MonoClass *ic = klass->interfaces [i];
7529 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7534 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7537 if (klassc == mono_defaults.object_class)
7544 mono_type_is_generic_argument (MonoType *type)
7546 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7550 mono_class_has_variant_generic_params (MonoClass *klass)
7553 MonoGenericContainer *container;
7555 if (!klass->generic_class)
7558 container = klass->generic_class->container_class->generic_container;
7560 for (i = 0; i < container->type_argc; ++i)
7561 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7568 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7570 if (target == candidate)
7573 if (check_for_reference_conv &&
7574 mono_type_is_generic_argument (&target->byval_arg) &&
7575 mono_type_is_generic_argument (&candidate->byval_arg)) {
7576 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7577 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7579 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7582 if (!mono_class_is_assignable_from (target, candidate))
7588 * @container the generic container from the GTD
7589 * @klass: the class to be assigned to
7590 * @oklass: the source class
7592 * Both klass and oklass must be instances of the same generic interface.
7593 * Return true if @klass can be assigned to a @klass variable
7596 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7599 MonoType **klass_argv, **oklass_argv;
7600 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7601 MonoGenericContainer *container = klass_gtd->generic_container;
7603 if (klass == oklass)
7606 /*Viable candidates are instances of the same generic interface*/
7607 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7610 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7611 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7613 for (j = 0; j < container->type_argc; ++j) {
7614 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7615 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7617 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7621 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7622 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7624 if (param1_class != param2_class) {
7625 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7626 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7628 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7629 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7639 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7641 MonoGenericParam *gparam, *ogparam;
7642 MonoGenericParamInfo *tinfo, *cinfo;
7643 MonoClass **candidate_class;
7644 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7647 if (target == candidate)
7649 if (target->byval_arg.type != candidate->byval_arg.type)
7652 gparam = target->byval_arg.data.generic_param;
7653 ogparam = candidate->byval_arg.data.generic_param;
7654 tinfo = mono_generic_param_info (gparam);
7655 cinfo = mono_generic_param_info (ogparam);
7657 class_constraint_satisfied = FALSE;
7658 valuetype_constraint_satisfied = FALSE;
7660 /*candidate must have a super set of target's special constraints*/
7661 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7662 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7664 if (cinfo->constraints) {
7665 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7666 MonoClass *cc = *candidate_class;
7668 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7669 class_constraint_satisfied = TRUE;
7670 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7671 valuetype_constraint_satisfied = TRUE;
7674 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7675 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7677 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7679 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7681 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7682 valuetype_constraint_satisfied)) {
7687 /*candidate type constraints must be a superset of target's*/
7688 if (tinfo->constraints) {
7689 MonoClass **target_class;
7690 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7691 MonoClass *tc = *target_class;
7694 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7695 * check it's constraints since it satisfy the constraint by itself.
7697 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7700 if (!cinfo->constraints)
7703 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7704 MonoClass *cc = *candidate_class;
7706 if (mono_class_is_assignable_from (tc, cc))
7710 * This happens when we have the following:
7712 * Bar<K> where K : IFace
7713 * Foo<T, U> where T : U where U : IFace
7715 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7718 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7719 if (mono_gparam_is_assignable_from (target, cc))
7723 if (!*candidate_class)
7728 /*candidate itself must have a constraint that satisfy target*/
7729 if (cinfo->constraints) {
7730 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7731 MonoClass *cc = *candidate_class;
7732 if (mono_class_is_assignable_from (target, cc))
7740 * mono_class_is_assignable_from:
7741 * @klass: the class to be assigned to
7742 * @oklass: the source class
7744 * Return: true if an instance of object oklass can be assigned to an
7745 * instance of object @klass
7748 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7750 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7752 mono_class_init (klass);
7754 if (!oklass->inited)
7755 mono_class_init (oklass);
7757 if (klass->exception_type || oklass->exception_type)
7760 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7761 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7763 return mono_gparam_is_assignable_from (klass, oklass);
7766 if (MONO_CLASS_IS_INTERFACE (klass)) {
7767 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7768 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7769 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7773 for (i = 0; constraints [i]; ++i) {
7774 if (mono_class_is_assignable_from (klass, constraints [i]))
7782 /* interface_offsets might not be set for dynamic classes */
7783 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7785 * oklass might be a generic type parameter but they have
7786 * interface_offsets set.
7788 return mono_reflection_call_is_assignable_to (oklass, klass);
7789 if (!oklass->interface_bitmap)
7790 /* Happens with generic instances of not-yet created dynamic types */
7792 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7795 if (mono_class_has_variant_generic_params (klass)) {
7798 mono_class_setup_interfaces (oklass, &error);
7799 if (!mono_error_ok (&error)) {
7800 mono_error_cleanup (&error);
7804 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7805 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7806 MonoClass *iface = oklass->interfaces_packed [i];
7808 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7813 } else if (klass->delegate) {
7814 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7816 }else if (klass->rank) {
7817 MonoClass *eclass, *eoclass;
7819 if (oklass->rank != klass->rank)
7822 /* vectors vs. one dimensional arrays */
7823 if (oklass->byval_arg.type != klass->byval_arg.type)
7826 eclass = klass->cast_class;
7827 eoclass = oklass->cast_class;
7830 * a is b does not imply a[] is b[] when a is a valuetype, and
7831 * b is a reference type.
7834 if (eoclass->valuetype) {
7835 if ((eclass == mono_defaults.enum_class) ||
7836 (eclass == mono_defaults.enum_class->parent) ||
7837 (eclass == mono_defaults.object_class))
7841 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7842 } else if (mono_class_is_nullable (klass)) {
7843 if (mono_class_is_nullable (oklass))
7844 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7846 return mono_class_is_assignable_from (klass->cast_class, oklass);
7847 } else if (klass == mono_defaults.object_class)
7850 return mono_class_has_parent (oklass, klass);
7853 /*Check if @oklass is variant compatible with @klass.*/
7855 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7858 MonoType **klass_argv, **oklass_argv;
7859 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7860 MonoGenericContainer *container = klass_gtd->generic_container;
7862 /*Viable candidates are instances of the same generic interface*/
7863 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7866 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7867 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7869 for (j = 0; j < container->type_argc; ++j) {
7870 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7871 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7873 if (param1_class->valuetype != param2_class->valuetype)
7877 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7878 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7880 if (param1_class != param2_class) {
7881 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7882 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7884 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7885 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7893 /*Check if @candidate implements the interface @target*/
7895 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7899 gboolean is_variant = mono_class_has_variant_generic_params (target);
7901 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7902 if (mono_class_is_variant_compatible_slow (target, candidate))
7907 if (candidate == target)
7910 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7911 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7912 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7914 if (tb && tb->interfaces) {
7915 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7916 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7917 MonoClass *iface_class;
7919 /* we can't realize the type here since it can do pretty much anything. */
7922 iface_class = mono_class_from_mono_type (iface->type);
7923 if (iface_class == target)
7925 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
7927 if (mono_class_implement_interface_slow (target, iface_class))
7932 /*setup_interfaces don't mono_class_init anything*/
7933 mono_class_setup_interfaces (candidate, &error);
7934 if (!mono_error_ok (&error)) {
7935 mono_error_cleanup (&error);
7939 for (i = 0; i < candidate->interface_count; ++i) {
7940 if (candidate->interfaces [i] == target)
7943 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
7946 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
7950 candidate = candidate->parent;
7951 } while (candidate);
7957 * Check if @oklass can be assigned to @klass.
7958 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
7961 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
7963 if (candidate == target)
7965 if (target == mono_defaults.object_class)
7968 if (mono_class_has_parent (candidate, target))
7971 /*If target is not an interface there is no need to check them.*/
7972 if (MONO_CLASS_IS_INTERFACE (target))
7973 return mono_class_implement_interface_slow (target, candidate);
7975 if (target->delegate && mono_class_has_variant_generic_params (target))
7976 return mono_class_is_variant_compatible (target, candidate, FALSE);
7978 /*FIXME properly handle nullables and arrays */
7979 /*FIXME properly handle (M)VAR */
7984 * mono_class_get_cctor:
7985 * @klass: A MonoClass pointer
7987 * Returns: the static constructor of @klass if it exists, NULL otherwise.
7990 mono_class_get_cctor (MonoClass *klass)
7992 MonoCachedClassInfo cached_info;
7994 if (klass->image->dynamic) {
7996 * has_cctor is not set for these classes because mono_class_init () is
7999 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8002 if (!klass->has_cctor)
8005 if (mono_class_get_cached_class_info (klass, &cached_info))
8006 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8008 if (klass->generic_class && !klass->methods)
8009 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8011 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8015 * mono_class_get_finalizer:
8016 * @klass: The MonoClass pointer
8018 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8021 mono_class_get_finalizer (MonoClass *klass)
8023 MonoCachedClassInfo cached_info;
8026 mono_class_init (klass);
8027 if (!mono_class_has_finalizer (klass))
8030 if (mono_class_get_cached_class_info (klass, &cached_info))
8031 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8033 mono_class_setup_vtable (klass);
8034 return klass->vtable [finalize_slot];
8039 * mono_class_needs_cctor_run:
8040 * @klass: the MonoClass pointer
8041 * @caller: a MonoMethod describing the caller
8043 * Determines whenever the class has a static constructor and whenever it
8044 * needs to be called when executing CALLER.
8047 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8051 method = mono_class_get_cctor (klass);
8053 return (method == caller) ? FALSE : TRUE;
8059 * mono_class_array_element_size:
8062 * Returns: the number of bytes an element of type @klass
8063 * uses when stored into an array.
8066 mono_class_array_element_size (MonoClass *klass)
8068 MonoType *type = &klass->byval_arg;
8071 switch (type->type) {
8074 case MONO_TYPE_BOOLEAN:
8078 case MONO_TYPE_CHAR:
8087 case MONO_TYPE_CLASS:
8088 case MONO_TYPE_STRING:
8089 case MONO_TYPE_OBJECT:
8090 case MONO_TYPE_SZARRAY:
8091 case MONO_TYPE_ARRAY:
8093 case MONO_TYPE_MVAR:
8094 return sizeof (gpointer);
8099 case MONO_TYPE_VALUETYPE:
8100 if (type->data.klass->enumtype) {
8101 type = mono_class_enum_basetype (type->data.klass);
8102 klass = klass->element_class;
8105 return mono_class_instance_size (klass) - sizeof (MonoObject);
8106 case MONO_TYPE_GENERICINST:
8107 type = &type->data.generic_class->container_class->byval_arg;
8110 case MONO_TYPE_VOID:
8114 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8120 * mono_array_element_size:
8121 * @ac: pointer to a #MonoArrayClass
8123 * Returns: the size of single array element.
8126 mono_array_element_size (MonoClass *ac)
8128 g_assert (ac->rank);
8129 return ac->sizes.element_size;
8133 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8134 MonoGenericContext *context)
8136 if (image->dynamic) {
8137 MonoClass *tmp_handle_class;
8138 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8140 g_assert (tmp_handle_class);
8142 *handle_class = tmp_handle_class;
8144 if (tmp_handle_class == mono_defaults.typehandle_class)
8145 return &((MonoClass*)obj)->byval_arg;
8150 switch (token & 0xff000000) {
8151 case MONO_TOKEN_TYPE_DEF:
8152 case MONO_TOKEN_TYPE_REF:
8153 case MONO_TOKEN_TYPE_SPEC: {
8156 *handle_class = mono_defaults.typehandle_class;
8157 type = mono_type_get_full (image, token, context);
8160 mono_class_init (mono_class_from_mono_type (type));
8161 /* We return a MonoType* as handle */
8164 case MONO_TOKEN_FIELD_DEF: {
8166 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8170 *handle_class = mono_defaults.fieldhandle_class;
8171 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8174 mono_class_init (class);
8175 return mono_class_get_field (class, token);
8177 case MONO_TOKEN_METHOD_DEF:
8178 case MONO_TOKEN_METHOD_SPEC: {
8180 meth = mono_get_method_full (image, token, NULL, context);
8182 *handle_class = mono_defaults.methodhandle_class;
8185 case MONO_TOKEN_MEMBER_REF: {
8186 guint32 cols [MONO_MEMBERREF_SIZE];
8188 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8189 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8190 mono_metadata_decode_blob_size (sig, &sig);
8191 if (*sig == 0x6) { /* it's a field */
8193 MonoClassField *field;
8194 field = mono_field_from_token (image, token, &klass, context);
8196 *handle_class = mono_defaults.fieldhandle_class;
8200 meth = mono_get_method_full (image, token, NULL, context);
8202 *handle_class = mono_defaults.methodhandle_class;
8207 g_warning ("Unknown token 0x%08x in ldtoken", token);
8214 * This function might need to call runtime functions so it can't be part
8215 * of the metadata library.
8217 static MonoLookupDynamicToken lookup_dynamic = NULL;
8220 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8222 lookup_dynamic = func;
8226 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8228 MonoClass *handle_class;
8230 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8234 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8236 return lookup_dynamic (image, token, valid_token, handle_class, context);
8239 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8242 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8244 get_cached_class_info = func;
8248 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8250 if (!get_cached_class_info)
8253 return get_cached_class_info (klass, res);
8257 mono_install_get_class_from_name (MonoGetClassFromName func)
8259 get_class_from_name = func;
8263 mono_class_get_image (MonoClass *klass)
8265 return klass->image;
8269 * mono_class_get_element_class:
8270 * @klass: the MonoClass to act on
8272 * Returns: the element class of an array or an enumeration.
8275 mono_class_get_element_class (MonoClass *klass)
8277 return klass->element_class;
8281 * mono_class_is_valuetype:
8282 * @klass: the MonoClass to act on
8284 * Returns: true if the MonoClass represents a ValueType.
8287 mono_class_is_valuetype (MonoClass *klass)
8289 return klass->valuetype;
8293 * mono_class_is_enum:
8294 * @klass: the MonoClass to act on
8296 * Returns: true if the MonoClass represents an enumeration.
8299 mono_class_is_enum (MonoClass *klass)
8301 return klass->enumtype;
8305 * mono_class_enum_basetype:
8306 * @klass: the MonoClass to act on
8308 * Returns: the underlying type representation for an enumeration.
8311 mono_class_enum_basetype (MonoClass *klass)
8313 if (klass->element_class == klass)
8314 /* SRE or broken types */
8317 return &klass->element_class->byval_arg;
8321 * mono_class_get_parent
8322 * @klass: the MonoClass to act on
8324 * Returns: the parent class for this class.
8327 mono_class_get_parent (MonoClass *klass)
8329 return klass->parent;
8333 * mono_class_get_nesting_type;
8334 * @klass: the MonoClass to act on
8336 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8339 mono_class_get_nesting_type (MonoClass *klass)
8341 return klass->nested_in;
8345 * mono_class_get_rank:
8346 * @klass: the MonoClass to act on
8348 * Returns: the rank for the array (the number of dimensions).
8351 mono_class_get_rank (MonoClass *klass)
8357 * mono_class_get_flags:
8358 * @klass: the MonoClass to act on
8360 * The type flags from the TypeDef table from the metadata.
8361 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8364 * Returns: the flags from the TypeDef table.
8367 mono_class_get_flags (MonoClass *klass)
8369 return klass->flags;
8373 * mono_class_get_name
8374 * @klass: the MonoClass to act on
8376 * Returns: the name of the class.
8379 mono_class_get_name (MonoClass *klass)
8385 * mono_class_get_namespace:
8386 * @klass: the MonoClass to act on
8388 * Returns: the namespace of the class.
8391 mono_class_get_namespace (MonoClass *klass)
8393 return klass->name_space;
8397 * mono_class_get_type:
8398 * @klass: the MonoClass to act on
8400 * This method returns the internal Type representation for the class.
8402 * Returns: the MonoType from the class.
8405 mono_class_get_type (MonoClass *klass)
8407 return &klass->byval_arg;
8411 * mono_class_get_type_token
8412 * @klass: the MonoClass to act on
8414 * This method returns type token for the class.
8416 * Returns: the type token for the class.
8419 mono_class_get_type_token (MonoClass *klass)
8421 return klass->type_token;
8425 * mono_class_get_byref_type:
8426 * @klass: the MonoClass to act on
8431 mono_class_get_byref_type (MonoClass *klass)
8433 return &klass->this_arg;
8437 * mono_class_num_fields:
8438 * @klass: the MonoClass to act on
8440 * Returns: the number of static and instance fields in the class.
8443 mono_class_num_fields (MonoClass *klass)
8445 return klass->field.count;
8449 * mono_class_num_methods:
8450 * @klass: the MonoClass to act on
8452 * Returns: the number of methods in the class.
8455 mono_class_num_methods (MonoClass *klass)
8457 return klass->method.count;
8461 * mono_class_num_properties
8462 * @klass: the MonoClass to act on
8464 * Returns: the number of properties in the class.
8467 mono_class_num_properties (MonoClass *klass)
8469 mono_class_setup_properties (klass);
8471 return klass->ext->property.count;
8475 * mono_class_num_events:
8476 * @klass: the MonoClass to act on
8478 * Returns: the number of events in the class.
8481 mono_class_num_events (MonoClass *klass)
8483 mono_class_setup_events (klass);
8485 return klass->ext->event.count;
8489 * mono_class_get_fields:
8490 * @klass: the MonoClass to act on
8492 * This routine is an iterator routine for retrieving the fields in a class.
8494 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8495 * iterate over all of the elements. When no more values are
8496 * available, the return value is NULL.
8498 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8501 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8503 MonoClassField* field;
8507 mono_class_setup_fields_locking (klass);
8508 if (klass->exception_type)
8510 /* start from the first */
8511 if (klass->field.count) {
8512 return *iter = &klass->fields [0];
8520 if (field < &klass->fields [klass->field.count]) {
8521 return *iter = field;
8527 * mono_class_get_methods
8528 * @klass: the MonoClass to act on
8530 * This routine is an iterator routine for retrieving the fields in a class.
8532 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8533 * iterate over all of the elements. When no more values are
8534 * available, the return value is NULL.
8536 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8539 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8541 MonoMethod** method;
8545 mono_class_setup_methods (klass);
8548 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8549 * FIXME we should better report this error to the caller
8551 if (!klass->methods)
8553 /* start from the first */
8554 if (klass->method.count) {
8555 *iter = &klass->methods [0];
8556 return klass->methods [0];
8564 if (method < &klass->methods [klass->method.count]) {
8572 * mono_class_get_virtual_methods:
8574 * Iterate over the virtual methods of KLASS.
8576 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8579 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8581 MonoMethod** method;
8584 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
8586 mono_class_setup_methods (klass);
8588 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8589 * FIXME we should better report this error to the caller
8591 if (!klass->methods)
8593 /* start from the first */
8594 method = &klass->methods [0];
8599 while (method < &klass->methods [klass->method.count]) {
8600 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8604 if (method < &klass->methods [klass->method.count]) {
8611 /* Search directly in metadata to avoid calling setup_methods () */
8612 MonoMethod *res = NULL;
8618 start_index = GPOINTER_TO_UINT (*iter);
8621 for (i = start_index; i < klass->method.count; ++i) {
8624 /* class->method.first points into the methodptr table */
8625 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8627 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8631 if (i < klass->method.count) {
8632 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8633 /* Add 1 here so the if (*iter) check fails */
8634 *iter = GUINT_TO_POINTER (i + 1);
8643 * mono_class_get_properties:
8644 * @klass: the MonoClass to act on
8646 * This routine is an iterator routine for retrieving the properties in a class.
8648 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8649 * iterate over all of the elements. When no more values are
8650 * available, the return value is NULL.
8652 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8655 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8657 MonoProperty* property;
8661 mono_class_setup_properties (klass);
8662 /* start from the first */
8663 if (klass->ext->property.count) {
8664 return *iter = &klass->ext->properties [0];
8672 if (property < &klass->ext->properties [klass->ext->property.count]) {
8673 return *iter = property;
8679 * mono_class_get_events:
8680 * @klass: the MonoClass to act on
8682 * This routine is an iterator routine for retrieving the properties in a class.
8684 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8685 * iterate over all of the elements. When no more values are
8686 * available, the return value is NULL.
8688 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8691 mono_class_get_events (MonoClass* klass, gpointer *iter)
8697 mono_class_setup_events (klass);
8698 /* start from the first */
8699 if (klass->ext->event.count) {
8700 return *iter = &klass->ext->events [0];
8708 if (event < &klass->ext->events [klass->ext->event.count]) {
8709 return *iter = event;
8715 * mono_class_get_interfaces
8716 * @klass: the MonoClass to act on
8718 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8720 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8721 * iterate over all of the elements. When no more values are
8722 * available, the return value is NULL.
8724 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8727 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8735 mono_class_init (klass);
8736 if (!klass->interfaces_inited) {
8737 mono_class_setup_interfaces (klass, &error);
8738 if (!mono_error_ok (&error)) {
8739 mono_error_cleanup (&error);
8743 /* start from the first */
8744 if (klass->interface_count) {
8745 *iter = &klass->interfaces [0];
8746 return klass->interfaces [0];
8754 if (iface < &klass->interfaces [klass->interface_count]) {
8762 * mono_class_get_nested_types
8763 * @klass: the MonoClass to act on
8765 * This routine is an iterator routine for retrieving the nested types of a class.
8766 * This works only if @klass is non-generic, or a generic type definition.
8768 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8769 * iterate over all of the elements. When no more values are
8770 * available, the return value is NULL.
8772 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8775 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8783 if (!klass->nested_classes_inited) {
8784 if (!klass->type_token)
8785 klass->nested_classes_inited = TRUE;
8786 mono_loader_lock ();
8787 if (!klass->nested_classes_inited) {
8788 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8791 guint32 cols [MONO_NESTED_CLASS_SIZE];
8792 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8793 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8794 if (!mono_error_ok (&error)) {
8795 /*FIXME don't swallow the error message*/
8796 mono_error_cleanup (&error);
8798 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8801 mono_class_alloc_ext (klass);
8802 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8804 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8807 mono_memory_barrier ();
8808 klass->nested_classes_inited = TRUE;
8809 mono_loader_unlock ();
8813 /* start from the first */
8814 if (klass->ext && klass->ext->nested_classes) {
8815 *iter = klass->ext->nested_classes;
8816 return klass->ext->nested_classes->data;
8818 /* no nested types */
8832 * mono_field_get_name:
8833 * @field: the MonoClassField to act on
8835 * Returns: the name of the field.
8838 mono_field_get_name (MonoClassField *field)
8844 * mono_field_get_type:
8845 * @field: the MonoClassField to act on
8847 * Returns: MonoType of the field.
8850 mono_field_get_type (MonoClassField *field)
8853 MonoType *type = mono_field_get_type_checked (field, &error);
8854 if (!mono_error_ok (&error)) {
8855 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8856 mono_error_cleanup (&error);
8863 * mono_field_get_type_checked:
8864 * @field: the MonoClassField to act on
8865 * @error: used to return any erro found while retrieving @field type
8867 * Returns: MonoType of the field.
8870 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
8872 mono_error_init (error);
8874 mono_field_resolve_type (field, error);
8879 * mono_field_get_parent:
8880 * @field: the MonoClassField to act on
8882 * Returns: MonoClass where the field was defined.
8885 mono_field_get_parent (MonoClassField *field)
8887 return field->parent;
8891 * mono_field_get_flags;
8892 * @field: the MonoClassField to act on
8894 * The metadata flags for a field are encoded using the
8895 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
8897 * Returns: the flags for the field.
8900 mono_field_get_flags (MonoClassField *field)
8903 return mono_field_resolve_flags (field);
8904 return field->type->attrs;
8908 * mono_field_get_offset;
8909 * @field: the MonoClassField to act on
8911 * Returns: the field offset.
8914 mono_field_get_offset (MonoClassField *field)
8916 return field->offset;
8920 mono_field_get_rva (MonoClassField *field)
8924 MonoClass *klass = field->parent;
8926 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
8928 if (!klass->ext || !klass->ext->field_def_values) {
8929 mono_loader_lock ();
8930 mono_class_alloc_ext (klass);
8931 if (!klass->ext->field_def_values)
8932 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
8933 mono_loader_unlock ();
8936 field_index = mono_field_get_index (field);
8938 if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
8939 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
8941 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
8942 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
8945 return klass->ext->field_def_values [field_index].data;
8949 * mono_field_get_data;
8950 * @field: the MonoClassField to act on
8952 * Returns: pointer to the metadata constant value or to the field
8953 * data if it has an RVA flag.
8956 mono_field_get_data (MonoClassField *field)
8958 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
8959 MonoTypeEnum def_type;
8961 return mono_class_get_field_default_value (field, &def_type);
8962 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
8963 return mono_field_get_rva (field);
8970 * mono_property_get_name:
8971 * @prop: the MonoProperty to act on
8973 * Returns: the name of the property
8976 mono_property_get_name (MonoProperty *prop)
8982 * mono_property_get_set_method
8983 * @prop: the MonoProperty to act on.
8985 * Returns: the setter method of the property (A MonoMethod)
8988 mono_property_get_set_method (MonoProperty *prop)
8994 * mono_property_get_get_method
8995 * @prop: the MonoProperty to act on.
8997 * Returns: the setter method of the property (A MonoMethod)
9000 mono_property_get_get_method (MonoProperty *prop)
9006 * mono_property_get_parent:
9007 * @prop: the MonoProperty to act on.
9009 * Returns: the MonoClass where the property was defined.
9012 mono_property_get_parent (MonoProperty *prop)
9014 return prop->parent;
9018 * mono_property_get_flags:
9019 * @prop: the MonoProperty to act on.
9021 * The metadata flags for a property are encoded using the
9022 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9024 * Returns: the flags for the property.
9027 mono_property_get_flags (MonoProperty *prop)
9033 * mono_event_get_name:
9034 * @event: the MonoEvent to act on
9036 * Returns: the name of the event.
9039 mono_event_get_name (MonoEvent *event)
9045 * mono_event_get_add_method:
9046 * @event: The MonoEvent to act on.
9048 * Returns: the @add' method for the event (a MonoMethod).
9051 mono_event_get_add_method (MonoEvent *event)
9057 * mono_event_get_remove_method:
9058 * @event: The MonoEvent to act on.
9060 * Returns: the @remove method for the event (a MonoMethod).
9063 mono_event_get_remove_method (MonoEvent *event)
9065 return event->remove;
9069 * mono_event_get_raise_method:
9070 * @event: The MonoEvent to act on.
9072 * Returns: the @raise method for the event (a MonoMethod).
9075 mono_event_get_raise_method (MonoEvent *event)
9077 return event->raise;
9081 * mono_event_get_parent:
9082 * @event: the MonoEvent to act on.
9084 * Returns: the MonoClass where the event is defined.
9087 mono_event_get_parent (MonoEvent *event)
9089 return event->parent;
9093 * mono_event_get_flags
9094 * @event: the MonoEvent to act on.
9096 * The metadata flags for an event are encoded using the
9097 * EVENT_* constants. See the tabledefs.h file for details.
9099 * Returns: the flags for the event.
9102 mono_event_get_flags (MonoEvent *event)
9104 return event->attrs;
9108 * mono_class_get_method_from_name:
9109 * @klass: where to look for the method
9110 * @name_space: name of the method
9111 * @param_count: number of parameters. -1 for any number.
9113 * Obtains a MonoMethod with a given name and number of parameters.
9114 * It only works if there are no multiple signatures for any given method name.
9117 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9119 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9123 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9125 MonoMethod *res = NULL;
9128 /* Search directly in the metadata to avoid calling setup_methods () */
9129 for (i = 0; i < klass->method.count; ++i) {
9130 guint32 cols [MONO_METHOD_SIZE];
9132 MonoMethodSignature *sig;
9134 /* class->method.first points into the methodptr table */
9135 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9137 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9138 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9139 if (param_count == -1) {
9143 sig = mono_method_signature (method);
9144 if (sig && sig->param_count == param_count) {
9155 * mono_class_get_method_from_name_flags:
9156 * @klass: where to look for the method
9157 * @name_space: name of the method
9158 * @param_count: number of parameters. -1 for any number.
9159 * @flags: flags which must be set in the method
9161 * Obtains a MonoMethod with a given name and number of parameters.
9162 * It only works if there are no multiple signatures for any given method name.
9165 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9167 MonoMethod *res = NULL;
9170 mono_class_init (klass);
9172 if (klass->generic_class && !klass->methods) {
9173 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9175 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9179 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9180 mono_class_setup_methods (klass);
9182 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9183 See mono/tests/array_load_exception.il
9184 FIXME we should better report this error to the caller
9186 if (!klass->methods)
9188 for (i = 0; i < klass->method.count; ++i) {
9189 MonoMethod *method = klass->methods [i];
9191 if (method->name[0] == name [0] &&
9192 !strcmp (name, method->name) &&
9193 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9194 ((method->flags & flags) == flags)) {
9201 res = find_method_in_metadata (klass, name, param_count, flags);
9208 * mono_class_set_failure:
9209 * @klass: class in which the failure was detected
9210 * @ex_type: the kind of exception/error to be thrown (later)
9211 * @ex_data: exception data (specific to each type of exception/error)
9213 * Keep a detected failure informations in the class for later processing.
9214 * Note that only the first failure is kept.
9216 * LOCKING: Acquires the loader lock.
9219 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9221 if (klass->exception_type)
9224 mono_loader_lock ();
9225 klass->exception_type = ex_type;
9227 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9228 mono_loader_unlock ();
9234 * mono_class_get_exception_data:
9236 * Return the exception_data property of KLASS.
9238 * LOCKING: Acquires the loader lock.
9241 mono_class_get_exception_data (MonoClass *klass)
9243 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9247 * mono_classes_init:
9249 * Initialize the resources used by this module.
9252 mono_classes_init (void)
9254 mono_counters_register ("Inflated methods size",
9255 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9256 mono_counters_register ("Inflated classes",
9257 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9258 mono_counters_register ("Inflated classes size",
9259 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9260 mono_counters_register ("MonoClass size",
9261 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9262 mono_counters_register ("MonoClassExt size",
9263 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9267 * mono_classes_cleanup:
9269 * Free the resources used by this module.
9272 mono_classes_cleanup (void)
9274 if (global_interface_bitset)
9275 mono_bitset_free (global_interface_bitset);
9276 global_interface_bitset = NULL;
9280 * mono_class_get_exception_for_failure:
9281 * @klass: class in which the failure was detected
9283 * Return a constructed MonoException than the caller can then throw
9284 * using mono_raise_exception - or NULL if no failure is present (or
9285 * doesn't result in an exception).
9288 mono_class_get_exception_for_failure (MonoClass *klass)
9290 gpointer exception_data = mono_class_get_exception_data (klass);
9292 switch (klass->exception_type) {
9293 #ifndef DISABLE_SECURITY
9294 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9295 MonoDomain *domain = mono_domain_get ();
9296 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9297 MonoMethod *method = exception_data;
9298 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9299 MonoObject *exc = NULL;
9303 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9304 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9305 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9307 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9308 return (MonoException*) exc;
9311 case MONO_EXCEPTION_TYPE_LOAD: {
9314 char *str = mono_type_get_full_name (klass);
9315 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9316 name = mono_string_new (mono_domain_get (), str);
9318 ex = mono_get_exception_type_load (name, astr);
9322 case MONO_EXCEPTION_MISSING_METHOD: {
9323 char *class_name = exception_data;
9324 char *assembly_name = class_name + strlen (class_name) + 1;
9326 return mono_get_exception_missing_method (class_name, assembly_name);
9328 case MONO_EXCEPTION_MISSING_FIELD: {
9329 char *class_name = exception_data;
9330 char *member_name = class_name + strlen (class_name) + 1;
9332 return mono_get_exception_missing_field (class_name, member_name);
9334 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9335 char *msg_format = exception_data;
9336 char *assembly_name = msg_format + strlen (msg_format) + 1;
9337 char *msg = g_strdup_printf (msg_format, assembly_name);
9340 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9346 case MONO_EXCEPTION_BAD_IMAGE: {
9347 return mono_get_exception_bad_image_format (exception_data);
9350 MonoLoaderError *error;
9353 error = mono_loader_get_last_error ();
9355 ex = mono_loader_error_prepare_exception (error);
9359 /* TODO - handle other class related failures */
9366 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9368 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9369 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9371 if (outer_klass == inner_klass)
9373 inner_klass = inner_klass->nested_in;
9374 } while (inner_klass);
9379 mono_class_get_generic_type_definition (MonoClass *klass)
9381 return klass->generic_class ? klass->generic_class->container_class : klass;
9385 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9387 * Generic instantiations are ignored for all super types of @klass.
9389 * Visibility checks ignoring generic instantiations.
9392 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9395 klass = mono_class_get_generic_type_definition (klass);
9396 parent = mono_class_get_generic_type_definition (parent);
9397 mono_class_setup_supertypes (klass);
9399 for (i = 0; i < klass->idepth; ++i) {
9400 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9406 * Subtype can only access parent members with family protection if the site object
9407 * is subclass of Subtype. For example:
9408 * class A { protected int x; }
9410 * void valid_access () {
9414 * void invalid_access () {
9421 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9423 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9426 if (context_klass == NULL)
9428 /*if access_klass is not member_klass context_klass must be type compat*/
9429 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9435 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9438 if (accessing == accessed)
9440 if (!accessed || !accessing)
9443 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9444 * anywhere so untrusted friends are not safe to access platform's code internals */
9445 if (mono_security_core_clr_enabled ()) {
9446 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9450 mono_assembly_load_friends (accessed);
9451 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9452 MonoAssemblyName *friend = tmp->data;
9453 /* Be conservative with checks */
9456 if (strcmp (accessing->aname.name, friend->name))
9458 if (friend->public_key_token [0]) {
9459 if (!accessing->aname.public_key_token [0])
9461 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9470 * If klass is a generic type or if it is derived from a generic type, return the
9471 * MonoClass of the generic definition
9472 * Returns NULL if not found
9475 get_generic_definition_class (MonoClass *klass)
9478 if (klass->generic_class && klass->generic_class->container_class)
9479 return klass->generic_class->container_class;
9480 klass = klass->parent;
9486 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9489 for (i = 0; i < ginst->type_argc; ++i) {
9490 MonoType *type = ginst->type_argv[i];
9491 switch (type->type) {
9492 case MONO_TYPE_SZARRAY:
9493 if (!can_access_type (access_klass, type->data.klass))
9496 case MONO_TYPE_ARRAY:
9497 if (!can_access_type (access_klass, type->data.array->eklass))
9501 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9504 case MONO_TYPE_CLASS:
9505 case MONO_TYPE_VALUETYPE:
9506 case MONO_TYPE_GENERICINST:
9507 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9515 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9519 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9522 if (access_klass->element_class && !access_klass->enumtype)
9523 access_klass = access_klass->element_class;
9525 if (member_klass->element_class && !member_klass->enumtype)
9526 member_klass = member_klass->element_class;
9528 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9530 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9533 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9536 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9539 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9542 /*Non nested type with nested visibility. We just fail it.*/
9543 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9546 switch (access_level) {
9547 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9548 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9550 case TYPE_ATTRIBUTE_PUBLIC:
9553 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9556 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9557 return is_nesting_type (member_klass, access_klass);
9559 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9560 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9562 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9563 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9565 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9566 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9567 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9569 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9570 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9571 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9576 /* FIXME: check visibility of type, too */
9578 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9580 MonoClass *member_generic_def;
9581 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9584 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9585 access_klass->generic_container) &&
9586 (member_generic_def = get_generic_definition_class (member_klass))) {
9587 MonoClass *access_container;
9589 if (access_klass->generic_container)
9590 access_container = access_klass;
9592 access_container = access_klass->generic_class->container_class;
9594 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9598 /* Partition I 8.5.3.2 */
9599 /* the access level values are the same for fields and methods */
9600 switch (access_level) {
9601 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9602 /* same compilation unit */
9603 return access_klass->image == member_klass->image;
9604 case FIELD_ATTRIBUTE_PRIVATE:
9605 return access_klass == member_klass;
9606 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9607 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9608 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9611 case FIELD_ATTRIBUTE_ASSEMBLY:
9612 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9613 case FIELD_ATTRIBUTE_FAMILY:
9614 if (is_valid_family_access (access_klass, member_klass, context_klass))
9617 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9618 if (is_valid_family_access (access_klass, member_klass, context_klass))
9620 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9621 case FIELD_ATTRIBUTE_PUBLIC:
9628 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9630 /* FIXME: check all overlapping fields */
9631 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9633 MonoClass *nested = method->klass->nested_in;
9635 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9638 nested = nested->nested_in;
9645 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9647 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9649 MonoClass *nested = method->klass->nested_in;
9651 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9654 nested = nested->nested_in;
9659 * with generics calls to explicit interface implementations can be expressed
9660 * directly: the method is private, but we must allow it. This may be opening
9661 * a hole or the generics code should handle this differently.
9662 * Maybe just ensure the interface type is public.
9664 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9670 * mono_method_can_access_method_full:
9671 * @method: The caller method
9672 * @called: The called method
9673 * @context_klass: The static type on stack of the owner @called object used
9675 * This function must be used with instance calls, as they have more strict family accessibility.
9676 * It can be used with static methods, but context_klass should be NULL.
9678 * Returns: TRUE if caller have proper visibility and acessibility to @called
9681 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9683 MonoClass *access_class = method->klass;
9684 MonoClass *member_class = called->klass;
9685 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9687 MonoClass *nested = access_class->nested_in;
9689 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9692 nested = nested->nested_in;
9699 can = can_access_type (access_class, member_class);
9701 MonoClass *nested = access_class->nested_in;
9703 can = can_access_type (nested, member_class);
9706 nested = nested->nested_in;
9713 if (called->is_inflated) {
9714 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9715 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9724 * mono_method_can_access_field_full:
9725 * @method: The caller method
9726 * @field: The accessed field
9727 * @context_klass: The static type on stack of the owner @field object used
9729 * This function must be used with instance fields, as they have more strict family accessibility.
9730 * It can be used with static fields, but context_klass should be NULL.
9732 * Returns: TRUE if caller have proper visibility and acessibility to @field
9735 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9737 MonoClass *access_class = method->klass;
9738 MonoClass *member_class = field->parent;
9739 /* FIXME: check all overlapping fields */
9740 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9742 MonoClass *nested = access_class->nested_in;
9744 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9747 nested = nested->nested_in;
9754 can = can_access_type (access_class, member_class);
9756 MonoClass *nested = access_class->nested_in;
9758 can = can_access_type (nested, member_class);
9761 nested = nested->nested_in;
9771 * mono_class_can_access_class:
9772 * @source_class: The source class
9773 * @target_class: The accessed class
9775 * This function returns is @target_class is visible to @source_class
9777 * Returns: TRUE if source have proper visibility and acessibility to target
9780 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9782 return can_access_type (source_class, target_class);
9786 * mono_type_is_valid_enum_basetype:
9787 * @type: The MonoType to check
9789 * Returns: TRUE if the type can be used as the basetype of an enum
9791 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9792 switch (type->type) {
9795 case MONO_TYPE_BOOLEAN:
9798 case MONO_TYPE_CHAR:
9811 * mono_class_is_valid_enum:
9812 * @klass: An enum class to be validated
9814 * This method verify the required properties an enum should have.
9816 * Returns: TRUE if the informed enum class is valid
9818 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9819 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9820 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9822 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9823 MonoClassField * field;
9824 gpointer iter = NULL;
9825 gboolean found_base_field = FALSE;
9827 g_assert (klass->enumtype);
9828 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9829 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9833 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9836 while ((field = mono_class_get_fields (klass, &iter))) {
9837 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9838 if (found_base_field)
9840 found_base_field = TRUE;
9841 if (!mono_type_is_valid_enum_basetype (field->type))
9846 if (!found_base_field)
9849 if (klass->method.count > 0)
9856 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9858 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
9862 * mono_class_setup_interface_id:
9864 * Initializes MonoClass::interface_id if required.
9866 * LOCKING: Acquires the loader lock.
9869 mono_class_setup_interface_id (MonoClass *class)
9871 mono_loader_lock ();
9872 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
9873 class->interface_id = mono_get_unique_iid (class);
9874 mono_loader_unlock ();
9878 * mono_class_alloc_ext:
9880 * Allocate klass->ext if not already done.
9881 * LOCKING: Assumes the loader lock is held.
9884 mono_class_alloc_ext (MonoClass *klass)
9887 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
9888 class_ext_size += sizeof (MonoClassExt);
9893 * mono_class_setup_interfaces:
9895 * Initialize class->interfaces/interfaces_count.
9896 * LOCKING: Acquires the loader lock.
9897 * This function can fail the type.
9900 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
9904 mono_error_init (error);
9906 if (klass->interfaces_inited)
9909 mono_loader_lock ();
9911 if (klass->interfaces_inited) {
9912 mono_loader_unlock ();
9916 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
9919 /* generic IList, ICollection, IEnumerable */
9920 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
9921 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
9923 args [0] = &klass->element_class->byval_arg;
9924 klass->interfaces [0] = mono_class_bind_generic_parameters (
9925 mono_defaults.generic_ilist_class, 1, args, FALSE);
9926 if (klass->interface_count > 1)
9927 klass->interfaces [1] = mono_class_bind_generic_parameters (
9928 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
9929 } else if (klass->generic_class) {
9930 MonoClass *gklass = klass->generic_class->container_class;
9932 klass->interface_count = gklass->interface_count;
9933 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
9934 for (i = 0; i < klass->interface_count; i++) {
9935 klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
9936 if (!mono_error_ok (error)) {
9937 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
9938 klass->interfaces = NULL;
9944 mono_memory_barrier ();
9946 klass->interfaces_inited = TRUE;
9948 mono_loader_unlock ();
9952 mono_field_resolve_type (MonoClassField *field, MonoError *error)
9954 MonoClass *class = field->parent;
9955 MonoImage *image = class->image;
9956 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
9957 int field_idx = field - class->fields;
9959 mono_error_init (error);
9962 MonoClassField *gfield = >d->fields [field_idx];
9963 MonoType *gtype = mono_field_get_type_checked (gfield, error);
9964 if (!mono_error_ok (error)) {
9965 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
9966 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
9970 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
9971 if (!mono_error_ok (error)) {
9972 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
9973 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
9978 guint32 cols [MONO_FIELD_SIZE];
9979 MonoGenericContainer *container = NULL;
9980 int idx = class->field.first + field_idx;
9982 /*FIXME, in theory we do not lazy load SRE fields*/
9983 g_assert (!image->dynamic);
9985 if (class->generic_container) {
9986 container = class->generic_container;
9988 container = gtd->generic_container;
9989 g_assert (container);
9992 /* class->field.first and idx points into the fieldptr table */
9993 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
9995 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
9996 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
9997 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10001 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10003 mono_metadata_decode_value (sig, &sig);
10004 /* FIELD signature == 0x06 */
10005 g_assert (*sig == 0x06);
10006 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10008 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10013 mono_field_resolve_flags (MonoClassField *field)
10015 MonoClass *class = field->parent;
10016 MonoImage *image = class->image;
10017 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10018 int field_idx = field - class->fields;
10022 MonoClassField *gfield = >d->fields [field_idx];
10023 return mono_field_get_flags (gfield);
10025 int idx = class->field.first + field_idx;
10027 /*FIXME, in theory we do not lazy load SRE fields*/
10028 g_assert (!image->dynamic);
10030 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10035 * mono_class_setup_basic_field_info:
10036 * @class: The class to initialize
10038 * Initializes the class->fields array of fields.
10039 * Aquires the loader lock.
10042 mono_class_setup_basic_field_info_locking (MonoClass *class)
10044 mono_loader_lock ();
10045 mono_class_setup_basic_field_info (class);
10046 mono_loader_unlock ();
10050 * mono_class_get_fields_lazy:
10051 * @klass: the MonoClass to act on
10053 * This routine is an iterator routine for retrieving the fields in a class.
10054 * Only minimal information about fields are loaded. Accessors must be used
10055 * for all MonoClassField returned.
10057 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10058 * iterate over all of the elements. When no more values are
10059 * available, the return value is NULL.
10061 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10064 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10066 MonoClassField* field;
10070 mono_class_setup_basic_field_info_locking (klass);
10071 if (!klass->fields)
10073 /* start from the first */
10074 if (klass->field.count) {
10075 return *iter = &klass->fields [0];
10083 if (field < &klass->fields [klass->field.count]) {
10084 return *iter = field;
10090 mono_class_full_name (MonoClass *klass)
10092 return mono_type_full_name (&klass->byval_arg);