2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* Low level lock which protects data structures in this module */
56 static mono_mutex_t classes_mutex;
58 /* Function supplied by the runtime to find classes by name using information from the AOT file */
59 static MonoGetClassFromName get_class_from_name = NULL;
61 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
62 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
63 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
64 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
65 static int generic_array_methods (MonoClass *class);
66 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
68 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
69 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
70 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
71 static guint32 mono_field_resolve_flags (MonoClassField *field);
72 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
73 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
76 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
80 We use gclass recording to allow recursive system f types to be referenced by a parent.
82 Given the following type hierarchy:
84 class TextBox : TextBoxBase<TextBox> {}
85 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
86 class TextInput<T> : Input<T> where T: TextInput<T> {}
89 The runtime tries to load TextBoxBase<>.
90 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
91 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
92 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
94 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
95 at this point, iow, both are registered in the type map and both and a NULL parent. This means
96 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
98 To fix that what we do is to record all generic instantes created while resolving the parent of
99 any generic type definition and, after resolved, correct the parent field if needed.
102 static int record_gclass_instantiation;
103 static GSList *gclass_recorded_list;
104 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
109 mono_locks_acquire (&classes_mutex, ClassesLock);
113 classes_unlock (void)
115 mono_locks_release (&classes_mutex, ClassesLock);
119 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
122 enable_gclass_recording (void)
124 ++record_gclass_instantiation;
128 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
131 disable_gclass_recording (gclass_record_func func, void *user_data)
133 GSList **head = &gclass_recorded_list;
135 g_assert (record_gclass_instantiation > 0);
136 --record_gclass_instantiation;
139 GSList *node = *head;
140 if (func ((MonoClass*)node->data, user_data)) {
142 g_slist_free_1 (node);
148 /* We automatically discard all recorded gclasses when disabled. */
149 if (!record_gclass_instantiation && gclass_recorded_list) {
150 g_slist_free (gclass_recorded_list);
151 gclass_recorded_list = NULL;
156 * mono_class_from_typeref:
157 * @image: a MonoImage
158 * @type_token: a TypeRef token
160 * Creates the MonoClass* structure representing the type defined by
161 * the typeref token valid inside @image.
162 * Returns: the MonoClass* representing the typeref token, NULL ifcould
166 mono_class_from_typeref (MonoImage *image, guint32 type_token)
169 MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
170 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
175 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
177 guint32 cols [MONO_TYPEREF_SIZE];
178 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
180 const char *name, *nspace;
181 MonoClass *res = NULL;
184 mono_error_init (error);
186 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
189 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
191 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
192 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
194 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
195 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
196 case MONO_RESOLTION_SCOPE_MODULE:
198 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
199 This is not the observed behavior of existing implementations.
200 The defacto behavior is that it's just a typedef in disguise.
202 /* a typedef in disguise */
203 res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
206 case MONO_RESOLTION_SCOPE_MODULEREF:
207 module = mono_image_load_module (image, idx);
209 res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
212 case MONO_RESOLTION_SCOPE_TYPEREF: {
213 MonoClass *enclosing;
216 if (idx == mono_metadata_token_index (type_token)) {
217 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
221 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
222 if (!mono_error_ok (error))
225 if (enclosing->nested_classes_inited && enclosing->ext) {
226 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
227 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
229 if (strcmp (res->name, name) == 0)
233 /* Don't call mono_class_init as we might've been called by it recursively */
234 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
236 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
237 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
238 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
240 if (strcmp (nname, name) == 0)
241 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
243 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
246 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
249 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
253 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
254 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
258 if (!image->references || !image->references [idx - 1])
259 mono_assembly_load_reference (image, idx - 1);
260 g_assert (image->references [idx - 1]);
262 /* If the assembly did not load, register this as a type load exception */
263 if (image->references [idx - 1] == REFERENCE_MISSING){
264 MonoAssemblyName aname;
267 mono_assembly_get_assemblyref (image, idx - 1, &aname);
268 human_name = mono_stringify_assembly_name (&aname);
269 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
273 res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
276 /* Generic case, should be avoided for when a better error is possible. */
277 if (!res && mono_error_ok (error)) {
278 char *name = mono_class_name_from_token (image, type_token);
279 char *assembly = mono_assembly_name_from_token (image, type_token);
280 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
287 mono_image_memdup (MonoImage *image, void *data, guint size)
289 void *res = mono_image_alloc (image, size);
290 memcpy (res, data, size);
294 /* Copy everything mono_metadata_free_array free. */
296 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
299 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
301 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
303 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
305 a = g_memdup (a, sizeof (MonoArrayType));
307 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
309 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
314 /* Copy everything mono_metadata_free_method_signature free. */
316 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
320 sig = mono_metadata_signature_dup_full (image, sig);
322 sig->ret = mono_metadata_type_dup (image, sig->ret);
323 for (i = 0; i < sig->param_count; ++i)
324 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
330 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
332 MonoAssembly *ta = klass->image->assembly;
335 name = mono_stringify_assembly_name (&ta->aname);
336 g_string_append_printf (str, ", %s", name);
341 mono_type_name_check_byref (MonoType *type, GString *str)
344 g_string_append_c (str, '&');
348 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
349 MonoTypeNameFormat format)
353 switch (type->type) {
354 case MONO_TYPE_ARRAY: {
355 int i, rank = type->data.array->rank;
356 MonoTypeNameFormat nested_format;
358 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
359 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
361 mono_type_get_name_recurse (
362 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
363 g_string_append_c (str, '[');
365 g_string_append_c (str, '*');
366 for (i = 1; i < rank; i++)
367 g_string_append_c (str, ',');
368 g_string_append_c (str, ']');
370 mono_type_name_check_byref (type, str);
372 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
373 _mono_type_get_assembly_name (type->data.array->eklass, str);
376 case MONO_TYPE_SZARRAY: {
377 MonoTypeNameFormat nested_format;
379 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
380 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
382 mono_type_get_name_recurse (
383 &type->data.klass->byval_arg, str, FALSE, nested_format);
384 g_string_append (str, "[]");
386 mono_type_name_check_byref (type, str);
388 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
389 _mono_type_get_assembly_name (type->data.klass, str);
392 case MONO_TYPE_PTR: {
393 MonoTypeNameFormat nested_format;
395 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
396 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
398 mono_type_get_name_recurse (
399 type->data.type, str, FALSE, nested_format);
400 g_string_append_c (str, '*');
402 mono_type_name_check_byref (type, str);
404 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
405 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
410 if (!mono_generic_param_info (type->data.generic_param))
411 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
413 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
415 mono_type_name_check_byref (type, str);
419 klass = mono_class_from_mono_type (type);
420 if (klass->nested_in) {
421 mono_type_get_name_recurse (
422 &klass->nested_in->byval_arg, str, TRUE, format);
423 if (format == MONO_TYPE_NAME_FORMAT_IL)
424 g_string_append_c (str, '.');
426 g_string_append_c (str, '+');
427 } else if (*klass->name_space) {
428 g_string_append (str, klass->name_space);
429 g_string_append_c (str, '.');
431 if (format == MONO_TYPE_NAME_FORMAT_IL) {
432 char *s = strchr (klass->name, '`');
433 int len = s ? s - klass->name : strlen (klass->name);
435 g_string_append_len (str, klass->name, len);
437 g_string_append (str, klass->name);
440 if (klass->generic_class) {
441 MonoGenericClass *gclass = klass->generic_class;
442 MonoGenericInst *inst = gclass->context.class_inst;
443 MonoTypeNameFormat nested_format;
446 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
447 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
449 if (format == MONO_TYPE_NAME_FORMAT_IL)
450 g_string_append_c (str, '<');
452 g_string_append_c (str, '[');
453 for (i = 0; i < inst->type_argc; i++) {
454 MonoType *t = inst->type_argv [i];
457 g_string_append_c (str, ',');
458 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
459 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
460 g_string_append_c (str, '[');
461 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
462 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
463 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
464 g_string_append_c (str, ']');
466 if (format == MONO_TYPE_NAME_FORMAT_IL)
467 g_string_append_c (str, '>');
469 g_string_append_c (str, ']');
470 } else if (klass->generic_container &&
471 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
472 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
475 if (format == MONO_TYPE_NAME_FORMAT_IL)
476 g_string_append_c (str, '<');
478 g_string_append_c (str, '[');
479 for (i = 0; i < klass->generic_container->type_argc; i++) {
481 g_string_append_c (str, ',');
482 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
484 if (format == MONO_TYPE_NAME_FORMAT_IL)
485 g_string_append_c (str, '>');
487 g_string_append_c (str, ']');
490 mono_type_name_check_byref (type, str);
492 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
493 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
494 _mono_type_get_assembly_name (klass, str);
500 * mono_type_get_name_full:
502 * @format: the format for the return string.
505 * Returns: the string representation in a number of formats:
507 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
508 * returned in the formatrequired by System.Reflection, this is the
509 * inverse of mono_reflection_parse_type ().
511 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
512 * be used by the IL assembler.
514 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
516 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
519 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
523 result = g_string_new ("");
525 mono_type_get_name_recurse (type, result, FALSE, format);
527 return g_string_free (result, FALSE);
531 * mono_type_get_full_name:
534 * Returns: the string representation for type as required by System.Reflection.
535 * The inverse of mono_reflection_parse_type ().
538 mono_type_get_full_name (MonoClass *class)
540 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
544 * mono_type_get_name:
547 * Returns: the string representation for type as it would be represented in IL code.
550 mono_type_get_name (MonoType *type)
552 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
556 * mono_type_get_underlying_type:
559 * Returns: the MonoType for the underlying integer type if @type
560 * is an enum and byref is false, otherwise the type itself.
563 mono_type_get_underlying_type (MonoType *type)
565 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
566 return mono_class_enum_basetype (type->data.klass);
567 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
568 return mono_class_enum_basetype (type->data.generic_class->container_class);
573 * mono_class_is_open_constructed_type:
576 * Returns TRUE if type represents a generics open constructed type.
577 * IOW, not all type parameters required for the instantiation have
578 * been provided or it's a generic type definition.
580 * An open constructed type means it's a non realizable type. Not to
581 * be mixed up with an abstract type - we can't cast or dispatch to
582 * an open type, for example.
585 mono_class_is_open_constructed_type (MonoType *t)
591 case MONO_TYPE_SZARRAY:
592 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
593 case MONO_TYPE_ARRAY:
594 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
596 return mono_class_is_open_constructed_type (t->data.type);
597 case MONO_TYPE_GENERICINST:
598 return t->data.generic_class->context.class_inst->is_open;
599 case MONO_TYPE_CLASS:
600 case MONO_TYPE_VALUETYPE:
601 return t->data.klass->generic_container != NULL;
608 This is a simple function to catch the most common bad instances of generic types.
609 Specially those that might lead to further failures in the runtime.
612 is_valid_generic_argument (MonoType *type)
614 switch (type->type) {
616 //case MONO_TYPE_TYPEDBYREF:
623 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
625 mono_error_init (error);
627 switch (type->type) {
628 case MONO_TYPE_MVAR: {
630 int num = mono_type_get_generic_param_num (type);
631 MonoGenericInst *inst = context->method_inst;
632 if (!inst || !inst->type_argv)
634 if (num >= inst->type_argc) {
635 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
636 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
637 num, info ? info->name : "", inst->type_argc);
641 if (!is_valid_generic_argument (inst->type_argv [num])) {
642 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
643 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
644 num, info ? info->name : "", inst->type_argv [num]->type);
648 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
649 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
650 * ->byref and ->attrs from @type are propagated to the returned type.
652 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
653 nt->byref = type->byref;
654 nt->attrs = type->attrs;
657 case MONO_TYPE_VAR: {
659 int num = mono_type_get_generic_param_num (type);
660 MonoGenericInst *inst = context->class_inst;
663 if (num >= inst->type_argc) {
664 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
665 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
666 num, info ? info->name : "", inst->type_argc);
669 if (!is_valid_generic_argument (inst->type_argv [num])) {
670 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
671 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
672 num, info ? info->name : "", inst->type_argv [num]->type);
675 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
676 nt->byref = type->byref;
677 nt->attrs = type->attrs;
680 case MONO_TYPE_SZARRAY: {
681 MonoClass *eclass = type->data.klass;
682 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
683 if (!inflated || !mono_error_ok (error))
685 nt = mono_metadata_type_dup (image, type);
686 nt->data.klass = mono_class_from_mono_type (inflated);
687 mono_metadata_free_type (inflated);
690 case MONO_TYPE_ARRAY: {
691 MonoClass *eclass = type->data.array->eklass;
692 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
693 if (!inflated || !mono_error_ok (error))
695 nt = mono_metadata_type_dup (image, type);
696 nt->data.array->eklass = mono_class_from_mono_type (inflated);
697 mono_metadata_free_type (inflated);
700 case MONO_TYPE_GENERICINST: {
701 MonoGenericClass *gclass = type->data.generic_class;
702 MonoGenericInst *inst;
704 if (!gclass->context.class_inst->is_open)
707 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
708 if (!mono_error_ok (error))
710 if (inst != gclass->context.class_inst)
711 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
713 if (gclass == type->data.generic_class)
716 nt = mono_metadata_type_dup (image, type);
717 nt->data.generic_class = gclass;
720 case MONO_TYPE_CLASS:
721 case MONO_TYPE_VALUETYPE: {
722 MonoClass *klass = type->data.klass;
723 MonoGenericContainer *container = klass->generic_container;
724 MonoGenericInst *inst;
725 MonoGenericClass *gclass = NULL;
731 /* We can't use context->class_inst directly, since it can have more elements */
732 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
733 if (!mono_error_ok (error))
735 if (inst == container->context.class_inst)
738 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
740 nt = mono_metadata_type_dup (image, type);
741 nt->type = MONO_TYPE_GENERICINST;
742 nt->data.generic_class = gclass;
752 mono_generic_class_get_context (MonoGenericClass *gclass)
754 return &gclass->context;
758 mono_class_get_context (MonoClass *class)
760 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
764 * mono_class_get_generic_container:
766 * Return the generic container of KLASS which should be a generic type definition.
768 MonoGenericContainer*
769 mono_class_get_generic_container (MonoClass *klass)
771 g_assert (klass->is_generic);
773 return klass->generic_container;
777 * mono_class_get_generic_class:
779 * Return the MonoGenericClass of KLASS, which should be a generic instance.
782 mono_class_get_generic_class (MonoClass *klass)
784 g_assert (klass->is_inflated);
786 return klass->generic_class;
790 * mono_class_inflate_generic_type_with_mempool:
791 * @mempool: a mempool
793 * @context: a generics context
794 * @error: error context
796 * The same as mono_class_inflate_generic_type, but allocates the MonoType
797 * from mempool if it is non-NULL. If it is NULL, the MonoType is
798 * allocated on the heap and is owned by the caller.
799 * The returned type can potentially be the same as TYPE, so it should not be
800 * modified by the caller, and it should be freed using mono_metadata_free_type ().
803 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
805 MonoType *inflated = NULL;
806 mono_error_init (error);
809 inflated = inflate_generic_type (image, type, context, error);
810 if (!mono_error_ok (error))
814 MonoType *shared = mono_metadata_get_shared_type (type);
819 return mono_metadata_type_dup (image, type);
823 mono_stats.inflated_type_count++;
828 * mono_class_inflate_generic_type:
830 * @context: a generics context
832 * If @type is a generic type and @context is not NULL, instantiate it using the
833 * generics context @context.
835 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
836 * on the heap and is owned by the caller. Returns NULL on error.
838 * @deprecated Please use mono_class_inflate_generic_type_checked instead
841 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
845 result = mono_class_inflate_generic_type_checked (type, context, &error);
847 if (!mono_error_ok (&error)) {
848 mono_error_cleanup (&error);
855 * mono_class_inflate_generic_type:
857 * @context: a generics context
858 * @error: error context to use
860 * If @type is a generic type and @context is not NULL, instantiate it using the
861 * generics context @context.
863 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
864 * on the heap and is owned by the caller.
867 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
869 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
873 * mono_class_inflate_generic_type_no_copy:
875 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
879 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
881 MonoType *inflated = NULL;
883 mono_error_init (error);
885 inflated = inflate_generic_type (image, type, context, error);
886 if (!mono_error_ok (error))
893 mono_stats.inflated_type_count++;
898 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
903 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
904 if (!mono_error_ok (error))
907 res = mono_class_from_mono_type (inflated);
908 mono_metadata_free_type (inflated);
913 * mono_class_inflate_generic_class:
915 * Inflate the class GKLASS with CONTEXT.
918 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
923 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
924 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
931 static MonoGenericContext
932 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
934 MonoGenericInst *class_inst = NULL;
935 MonoGenericInst *method_inst = NULL;
936 MonoGenericContext res = { NULL, NULL };
938 mono_error_init (error);
940 if (context->class_inst) {
941 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
942 if (!mono_error_ok (error))
946 if (context->method_inst) {
947 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
948 if (!mono_error_ok (error))
952 res.class_inst = class_inst;
953 res.method_inst = method_inst;
959 * mono_class_inflate_generic_method:
960 * @method: a generic method
961 * @context: a generics context
963 * Instantiate the generic method @method using the generics context @context.
965 * Returns: the new instantiated method
968 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
970 return mono_class_inflate_generic_method_full (method, NULL, context);
974 * mono_class_inflate_generic_method_full:
976 * Instantiate method @method with the generic context @context.
977 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
978 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
981 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
984 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
985 if (!mono_error_ok (&error))
986 /*FIXME do proper error handling - on this case, kill this function. */
987 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
993 * mono_class_inflate_generic_method_full_checked:
994 * Same as mono_class_inflate_generic_method_full but return failure using @error.
997 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1000 MonoMethodInflated *iresult, *cached;
1001 MonoMethodSignature *sig;
1002 MonoGenericContext tmp_context;
1003 gboolean is_mb_open = FALSE;
1005 mono_error_init (error);
1007 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1008 while (method->is_inflated) {
1009 MonoGenericContext *method_context = mono_method_get_context (method);
1010 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1012 tmp_context = inflate_generic_context (method_context, context, error);
1013 if (!mono_error_ok (error))
1015 context = &tmp_context;
1017 if (mono_metadata_generic_context_equal (method_context, context))
1020 method = imethod->declaring;
1024 * A method only needs to be inflated if the context has argument for which it is
1027 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1028 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1031 if (!((method->is_generic && context->method_inst) ||
1032 (method->klass->generic_container && context->class_inst)))
1036 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1037 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1038 * This is opposite to the way non-SRE MethodInfos behave.
1040 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1042 * void Example<T> () {
1046 * In Example, the method token must be encoded as: "void Example<!!0>()"
1048 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1049 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1051 * On the other hand, inflating a non-SRE generic method with its own arguments should
1052 * return itself. For example:
1054 * MethodInfo m = ... //m is a generic method definition
1055 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1058 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1059 * what happens with regular methods.
1061 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1062 * everything should behave like a regular type or method.
1065 is_mb_open = method->is_generic &&
1066 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1067 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1069 iresult = g_new0 (MonoMethodInflated, 1);
1070 iresult->context = *context;
1071 iresult->declaring = method;
1072 iresult->method.method.is_mb_open = is_mb_open;
1074 if (!context->method_inst && method->is_generic)
1075 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1077 if (!context->class_inst) {
1078 g_assert (!iresult->declaring->klass->generic_class);
1079 if (iresult->declaring->klass->generic_container)
1080 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1081 else if (iresult->declaring->klass->generic_class)
1082 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1085 mono_loader_lock ();
1086 cached = mono_method_inflated_lookup (iresult, FALSE);
1088 mono_loader_unlock ();
1090 return (MonoMethod*)cached;
1093 mono_stats.inflated_method_count++;
1095 inflated_methods_size += sizeof (MonoMethodInflated);
1097 sig = mono_method_signature (method);
1099 char *name = mono_type_get_full_name (method->klass);
1100 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1106 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1108 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1111 result = (MonoMethod *) iresult;
1112 result->is_inflated = TRUE;
1113 result->is_generic = FALSE;
1114 result->sre_method = FALSE;
1115 result->signature = NULL;
1116 result->is_mb_open = is_mb_open;
1118 if (!context->method_inst) {
1119 /* Set the generic_container of the result to the generic_container of method */
1120 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1122 if (generic_container) {
1123 result->is_generic = 1;
1124 mono_method_set_generic_container (result, generic_container);
1128 if (!klass_hint || !klass_hint->generic_class ||
1129 klass_hint->generic_class->container_class != method->klass ||
1130 klass_hint->generic_class->context.class_inst != context->class_inst)
1133 if (method->klass->generic_container)
1134 result->klass = klass_hint;
1136 if (!result->klass) {
1137 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1138 if (!mono_error_ok (error))
1141 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1143 mono_metadata_free_type (inflated);
1147 * FIXME: This should hold, but it doesn't:
1149 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1150 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1151 * g_assert (result->is_generic);
1154 * Fixing this here causes other things to break, hence a very
1155 * ugly hack in mini-trampolines.c - see
1156 * is_generic_method_definition().
1159 mono_method_inflated_lookup (iresult, TRUE);
1160 mono_loader_unlock ();
1164 mono_loader_unlock ();
1170 * mono_get_inflated_method:
1172 * Obsolete. We keep it around since it's mentioned in the public API.
1175 mono_get_inflated_method (MonoMethod *method)
1181 * mono_method_get_context_general:
1183 * @uninflated: handle uninflated methods?
1185 * Returns the generic context of a method or NULL if it doesn't have
1186 * one. For an inflated method that's the context stored in the
1187 * method. Otherwise it's in the method's generic container or in the
1188 * generic container of the method's class.
1191 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1193 if (method->is_inflated) {
1194 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1195 return &imethod->context;
1199 if (method->is_generic)
1200 return &(mono_method_get_generic_container (method)->context);
1201 if (method->klass->generic_container)
1202 return &method->klass->generic_container->context;
1207 * mono_method_get_context:
1210 * Returns the generic context for method if it's inflated, otherwise
1214 mono_method_get_context (MonoMethod *method)
1216 return mono_method_get_context_general (method, FALSE);
1220 * mono_method_get_generic_container:
1222 * Returns the generic container of METHOD, which should be a generic method definition.
1223 * Returns NULL if METHOD is not a generic method definition.
1224 * LOCKING: Acquires the loader lock.
1226 MonoGenericContainer*
1227 mono_method_get_generic_container (MonoMethod *method)
1229 MonoGenericContainer *container;
1231 if (!method->is_generic)
1234 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1235 g_assert (container);
1241 * mono_method_set_generic_container:
1243 * Sets the generic container of METHOD to CONTAINER.
1244 * LOCKING: Acquires the loader lock.
1247 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1249 g_assert (method->is_generic);
1251 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1255 * mono_class_find_enum_basetype:
1256 * @class: The enum class
1258 * Determine the basetype of an enum by iterating through its fields. We do this
1259 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1262 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1264 MonoGenericContainer *container = NULL;
1265 MonoImage *m = class->image;
1266 const int top = class->field.count;
1269 g_assert (class->enumtype);
1271 mono_error_init (error);
1273 if (class->generic_container)
1274 container = class->generic_container;
1275 else if (class->generic_class) {
1276 MonoClass *gklass = class->generic_class->container_class;
1278 container = gklass->generic_container;
1279 g_assert (container);
1283 * Fetch all the field information.
1285 for (i = 0; i < top; i++){
1287 guint32 cols [MONO_FIELD_SIZE];
1288 int idx = class->field.first + i;
1291 /* class->field.first and idx points into the fieldptr table */
1292 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1294 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1297 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1298 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1302 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1303 mono_metadata_decode_value (sig, &sig);
1304 /* FIELD signature == 0x06 */
1306 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1310 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1312 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1313 mono_error_set_from_loader_error (error);
1315 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1318 if (class->generic_class) {
1319 //FIXME do we leak here?
1320 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1321 if (!mono_error_ok (error))
1323 ftype->attrs = cols [MONO_FIELD_FLAGS];
1328 mono_error_set_type_load_class (error, class, "Could not find base type");
1331 g_assert (!mono_loader_get_last_error ());
1336 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1339 mono_type_has_exceptions (MonoType *type)
1341 switch (type->type) {
1342 case MONO_TYPE_CLASS:
1343 case MONO_TYPE_VALUETYPE:
1344 case MONO_TYPE_SZARRAY:
1345 return type->data.klass->exception_type;
1346 case MONO_TYPE_ARRAY:
1347 return type->data.array->eklass->exception_type;
1348 case MONO_TYPE_GENERICINST:
1349 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1357 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1361 mono_class_alloc (MonoClass *class, int size)
1363 if (class->generic_class)
1364 return mono_image_set_alloc (class->generic_class->owner, size);
1366 return mono_image_alloc (class->image, size);
1370 mono_class_alloc0 (MonoClass *class, int size)
1374 res = mono_class_alloc (class, size);
1375 memset (res, 0, size);
1379 #define mono_class_new0(class,struct_type, n_structs) \
1380 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1383 * mono_class_setup_basic_field_info:
1384 * @class: The class to initialize
1386 * Initializes the class->fields.
1387 * LOCKING: Assumes the loader lock is held.
1390 mono_class_setup_basic_field_info (MonoClass *class)
1392 MonoClassField *field;
1400 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1401 image = class->image;
1402 top = class->field.count;
1404 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1406 * This happens when a generic instance of an unfinished generic typebuilder
1407 * is used as an element type for creating an array type. We can't initialize
1408 * the fields of this class using the fields of gklass, since gklass is not
1409 * finished yet, fields could be added to it later.
1415 mono_class_setup_basic_field_info (gtd);
1417 top = gtd->field.count;
1418 class->field.first = gtd->field.first;
1419 class->field.count = gtd->field.count;
1422 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1425 * Fetch all the field information.
1427 for (i = 0; i < top; i++){
1428 field = &class->fields [i];
1429 field->parent = class;
1432 field->name = mono_field_get_name (>d->fields [i]);
1434 int idx = class->field.first + i;
1435 /* class->field.first and idx points into the fieldptr table */
1436 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1437 /* The name is needed for fieldrefs */
1438 field->name = mono_metadata_string_heap (image, name_idx);
1444 * mono_class_setup_fields:
1445 * @class: The class to initialize
1447 * Initializes the class->fields.
1448 * LOCKING: Assumes the loader lock is held.
1451 mono_class_setup_fields (MonoClass *class)
1454 MonoImage *m = class->image;
1456 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1457 int i, blittable = TRUE;
1458 guint32 real_size = 0;
1459 guint32 packing_size = 0;
1460 gboolean explicit_size;
1461 MonoClassField *field;
1462 MonoGenericContainer *container = NULL;
1463 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1466 * FIXME: We have a race condition here. It's possible that this function returns
1467 * to its caller with `instance_size` set to `0` instead of the actual size. This
1468 * is not a problem when the function is called recursively on the same class,
1469 * because the size will be initialized by the outer invocation. What follows is a
1470 * description of how it can occur in other cases, too. There it is a problem,
1471 * because it can lead to the GC being asked to allocate an object of size `0`,
1472 * which SGen chokes on. The race condition is triggered infrequently by
1473 * `tests/sgen-suspend.cs`.
1475 * This function is called for a class whenever one of its subclasses is inited.
1476 * For example, it's called for every subclass of Object. What it does is this:
1478 * if (class->setup_fields_called)
1481 * class->instance_size = 0;
1483 * class->setup_fields_called = 1;
1484 * ... critical point
1485 * class->instance_size = actual_instance_size;
1487 * The last two steps are sometimes reversed, but that only changes the way in which
1488 * the race condition works.
1490 * Assume thread A goes through this function and makes it to the critical point.
1491 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1492 * immediately, but `instance_size` is incorrect.
1494 * The other case looks like this:
1496 * if (class->setup_fields_called)
1498 * ... critical point X
1499 * class->instance_size = 0;
1500 * ... critical point Y
1501 * class->instance_size = actual_instance_size;
1503 * class->setup_fields_called = 1;
1505 * Assume thread A goes through the function and makes it to critical point X. Now
1506 * thread B runs through the whole of the function, returning, assuming
1507 * `instance_size` is set. At that point thread A gets to run and makes it to
1508 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1511 if (class->setup_fields_called)
1514 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1516 * This happens when a generic instance of an unfinished generic typebuilder
1517 * is used as an element type for creating an array type. We can't initialize
1518 * the fields of this class using the fields of gklass, since gklass is not
1519 * finished yet, fields could be added to it later.
1524 mono_class_setup_basic_field_info (class);
1525 top = class->field.count;
1528 mono_class_setup_fields (gtd);
1529 if (gtd->exception_type) {
1530 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1535 class->instance_size = 0;
1537 class->sizes.class_size = 0;
1539 if (class->parent) {
1540 /* For generic instances, class->parent might not have been initialized */
1541 mono_class_init (class->parent);
1542 if (!class->parent->size_inited) {
1543 mono_class_setup_fields (class->parent);
1544 if (class->parent->exception_type) {
1545 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1549 class->instance_size += class->parent->instance_size;
1550 class->min_align = class->parent->min_align;
1551 /* we use |= since it may have been set already */
1552 class->has_references |= class->parent->has_references;
1553 blittable = class->parent->blittable;
1555 class->instance_size = sizeof (MonoObject);
1556 class->min_align = 1;
1559 /* We can't really enable 16 bytes alignment until the GC supports it.
1560 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1561 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1562 Bug #506144 is an example of this issue.
1564 if (class->simd_type)
1565 class->min_align = 16;
1567 /* Get the real size */
1568 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1570 if (explicit_size) {
1571 if ((packing_size & 0xfffffff0) != 0) {
1572 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1573 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1576 class->packing_size = packing_size;
1577 real_size += class->instance_size;
1581 if (explicit_size && real_size) {
1582 class->instance_size = MAX (real_size, class->instance_size);
1584 class->blittable = blittable;
1585 mono_memory_barrier ();
1586 class->size_inited = 1;
1587 class->fields_inited = 1;
1588 class->setup_fields_called = 1;
1592 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1595 /* Prevent infinite loops if the class references itself */
1596 class->setup_fields_called = 1;
1598 if (class->generic_container) {
1599 container = class->generic_container;
1601 container = gtd->generic_container;
1602 g_assert (container);
1606 * Fetch all the field information.
1608 for (i = 0; i < top; i++){
1609 int idx = class->field.first + i;
1610 field = &class->fields [i];
1612 field->parent = class;
1615 mono_field_resolve_type (field, &error);
1616 if (!mono_error_ok (&error)) {
1617 /*mono_field_resolve_type already failed class*/
1618 mono_error_cleanup (&error);
1622 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1623 g_assert (field->type);
1626 if (mono_field_is_deleted (field))
1629 MonoClassField *gfield = >d->fields [i];
1630 field->offset = gfield->offset;
1632 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1634 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1635 field->offset = offset;
1637 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1638 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1641 if (field->offset < -1) { /*-1 is used to encode special static fields */
1642 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1648 /* Only do these checks if we still think this type is blittable */
1649 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1650 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1653 MonoClass *field_class = mono_class_from_mono_type (field->type);
1655 mono_class_setup_fields (field_class);
1656 if (field_class->exception_type) {
1657 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1661 if (!field_class || !field_class->blittable)
1666 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1667 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1668 blittable = class->element_class->blittable;
1671 if (mono_type_has_exceptions (field->type)) {
1672 char *class_name = mono_type_get_full_name (class);
1673 char *type_name = mono_type_full_name (field->type);
1675 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1676 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1677 g_free (class_name);
1681 /* The def_value of fields is compute lazily during vtable creation */
1684 if (class == mono_defaults.string_class)
1687 class->blittable = blittable;
1689 if (class->enumtype && !mono_class_enum_basetype (class)) {
1690 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1693 if (explicit_size && real_size) {
1694 class->instance_size = MAX (real_size, class->instance_size);
1697 if (class->exception_type)
1699 mono_class_layout_fields (class);
1701 /*valuetypes can't be neither bigger than 1Mb or empty. */
1702 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1703 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1705 mono_memory_barrier ();
1706 class->fields_inited = 1;
1710 * mono_class_setup_fields_locking:
1711 * @class: The class to initialize
1713 * Initializes the class->fields array of fields.
1714 * Aquires the loader lock.
1717 mono_class_setup_fields_locking (MonoClass *class)
1719 /* This can be checked without locks */
1720 if (class->fields_inited)
1722 mono_loader_lock ();
1723 mono_class_setup_fields (class);
1724 mono_loader_unlock ();
1728 * mono_class_has_references:
1730 * Returns whenever @klass->has_references is set, initializing it if needed.
1731 * Aquires the loader lock.
1734 mono_class_has_references (MonoClass *klass)
1736 if (klass->init_pending) {
1737 /* Be conservative */
1740 mono_class_init (klass);
1742 return klass->has_references;
1747 * mono_type_get_basic_type_from_generic:
1750 * Returns a closed type corresponding to the possibly open type
1754 mono_type_get_basic_type_from_generic (MonoType *type)
1756 /* When we do generic sharing we let type variables stand for reference types. */
1757 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1758 return &mono_defaults.object_class->byval_arg;
1763 * mono_class_layout_fields:
1766 * Compute the placement of fields inside an object or struct, according to
1767 * the layout rules and set the following fields in @class:
1768 * - has_references (if the class contains instance references firled or structs that contain references)
1769 * - has_static_refs (same, but for static fields)
1770 * - instance_size (size of the object in memory)
1771 * - class_size (size needed for the static fields)
1772 * - size_inited (flag set when the instance_size is set)
1774 * LOCKING: this is supposed to be called with the loader lock held.
1777 mono_class_layout_fields (MonoClass *class)
1780 const int top = class->field.count;
1781 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1782 guint32 pass, passes, real_size;
1783 gboolean gc_aware_layout = FALSE;
1784 gboolean has_static_fields = FALSE;
1785 MonoClassField *field;
1788 * When we do generic sharing we need to have layout
1789 * information for open generic classes (either with a generic
1790 * context containing type variables or with a generic
1791 * container), so we don't return in that case anymore.
1795 * Enable GC aware auto layout: in this mode, reference
1796 * fields are grouped together inside objects, increasing collector
1798 * Requires that all classes whose layout is known to native code be annotated
1799 * with [StructLayout (LayoutKind.Sequential)]
1800 * Value types have gc_aware_layout disabled by default, as per
1801 * what the default is for other runtimes.
1803 /* corlib is missing [StructLayout] directives in many places */
1804 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1805 if (!class->valuetype)
1806 gc_aware_layout = TRUE;
1809 /* Compute klass->has_references */
1811 * Process non-static fields first, since static fields might recursively
1812 * refer to the class itself.
1814 for (i = 0; i < top; i++) {
1817 field = &class->fields [i];
1819 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1820 ftype = mono_type_get_underlying_type (field->type);
1821 ftype = mono_type_get_basic_type_from_generic (ftype);
1822 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 class->has_references = TRUE;
1827 for (i = 0; i < top; i++) {
1830 field = &class->fields [i];
1832 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1833 ftype = mono_type_get_underlying_type (field->type);
1834 ftype = mono_type_get_basic_type_from_generic (ftype);
1835 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1836 class->has_static_refs = TRUE;
1840 for (i = 0; i < top; i++) {
1843 field = &class->fields [i];
1845 ftype = mono_type_get_underlying_type (field->type);
1846 ftype = mono_type_get_basic_type_from_generic (ftype);
1847 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1848 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1849 class->has_static_refs = TRUE;
1851 class->has_references = TRUE;
1856 * Compute field layout and total size (not considering static fields)
1860 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1861 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1863 if (gc_aware_layout)
1868 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1871 if (class->parent) {
1872 mono_class_setup_fields (class->parent);
1873 if (class->parent->exception_type) {
1874 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1877 real_size = class->parent->instance_size;
1879 real_size = sizeof (MonoObject);
1882 for (pass = 0; pass < passes; ++pass) {
1883 for (i = 0; i < top; i++){
1888 field = &class->fields [i];
1890 if (mono_field_is_deleted (field))
1892 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1895 ftype = mono_type_get_underlying_type (field->type);
1896 ftype = mono_type_get_basic_type_from_generic (ftype);
1897 if (gc_aware_layout) {
1898 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1907 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1908 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1909 /* This field is a hack inserted by MCS to empty structures */
1913 size = mono_type_size (field->type, &align);
1915 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1916 align = class->packing_size ? MIN (class->packing_size, align): align;
1917 /* if the field has managed references, we need to force-align it
1920 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1921 align = MAX (align, sizeof (gpointer));
1923 class->min_align = MAX (align, class->min_align);
1924 field->offset = real_size;
1926 field->offset += align - 1;
1927 field->offset &= ~(align - 1);
1929 /*TypeBuilders produce all sort of weird things*/
1930 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1931 real_size = field->offset + size;
1934 class->instance_size = MAX (real_size, class->instance_size);
1936 if (class->instance_size & (class->min_align - 1)) {
1937 class->instance_size += class->min_align - 1;
1938 class->instance_size &= ~(class->min_align - 1);
1942 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1944 for (i = 0; i < top; i++) {
1949 field = &class->fields [i];
1952 * There must be info about all the fields in a type if it
1953 * uses explicit layout.
1956 if (mono_field_is_deleted (field))
1958 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1961 size = mono_type_size (field->type, &align);
1962 align = class->packing_size ? MIN (class->packing_size, align): align;
1963 class->min_align = MAX (align, class->min_align);
1966 * When we get here, field->offset is already set by the
1967 * loader (for either runtime fields or fields loaded from metadata).
1968 * The offset is from the start of the object: this works for both
1969 * classes and valuetypes.
1971 field->offset += sizeof (MonoObject);
1972 ftype = mono_type_get_underlying_type (field->type);
1973 ftype = mono_type_get_basic_type_from_generic (ftype);
1974 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1975 if (field->offset % sizeof (gpointer)) {
1976 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1983 real_size = MAX (real_size, size + field->offset);
1985 class->instance_size = MAX (real_size, class->instance_size);
1986 if (class->instance_size & (class->min_align - 1)) {
1987 class->instance_size += class->min_align - 1;
1988 class->instance_size &= ~(class->min_align - 1);
1993 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1995 * For small structs, set min_align to at least the struct size to improve
1996 * performance, and since the JIT memset/memcpy code assumes this and generates
1997 * unaligned accesses otherwise. See #78990 for a testcase.
1999 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2000 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2003 mono_memory_barrier ();
2004 class->size_inited = 1;
2007 * Compute static field layout and size
2009 for (i = 0; i < top; i++){
2013 field = &class->fields [i];
2015 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2017 if (mono_field_is_deleted (field))
2020 if (mono_type_has_exceptions (field->type)) {
2021 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2025 has_static_fields = TRUE;
2027 size = mono_type_size (field->type, &align);
2028 field->offset = class->sizes.class_size;
2029 /*align is always non-zero here*/
2030 field->offset += align - 1;
2031 field->offset &= ~(align - 1);
2032 class->sizes.class_size = field->offset + size;
2035 if (has_static_fields && class->sizes.class_size == 0)
2036 /* Simplify code which depends on class_size != 0 if the class has static fields */
2037 class->sizes.class_size = 8;
2041 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2045 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2046 method->klass = class;
2047 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2048 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2049 method->signature = sig;
2050 method->name = name;
2053 if (name [0] == '.') {
2054 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2056 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2062 * mono_class_setup_methods:
2065 * Initializes the 'methods' array in CLASS.
2066 * Calling this method should be avoided if possible since it allocates a lot
2067 * of long-living MonoMethod structures.
2068 * Methods belonging to an interface are assigned a sequential slot starting
2071 * On failure this function sets class->exception_type
2074 mono_class_setup_methods (MonoClass *class)
2077 MonoMethod **methods;
2082 if (class->generic_class) {
2084 MonoClass *gklass = class->generic_class->container_class;
2086 mono_class_init (gklass);
2087 if (!gklass->exception_type)
2088 mono_class_setup_methods (gklass);
2089 if (gklass->exception_type) {
2090 /* FIXME make exception_data less opaque so it's possible to dup it here */
2091 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2095 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2096 count = gklass->method.count;
2097 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2099 for (i = 0; i < count; i++) {
2100 methods [i] = mono_class_inflate_generic_method_full_checked (
2101 gklass->methods [i], class, mono_class_get_context (class), &error);
2102 if (!mono_error_ok (&error)) {
2103 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2104 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)));
2107 mono_error_cleanup (&error);
2111 } else if (class->rank) {
2113 MonoMethod *amethod;
2114 MonoMethodSignature *sig;
2115 int count_generic = 0, first_generic = 0;
2118 count = 3 + (class->rank > 1? 2: 1);
2120 mono_class_setup_interfaces (class, &error);
2121 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2123 if (class->interface_count) {
2124 count_generic = generic_array_methods (class);
2125 first_generic = count;
2126 count += class->interface_count * count_generic;
2129 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2131 sig = mono_metadata_signature_alloc (class->image, class->rank);
2132 sig->ret = &mono_defaults.void_class->byval_arg;
2133 sig->pinvoke = TRUE;
2134 sig->hasthis = TRUE;
2135 for (i = 0; i < class->rank; ++i)
2136 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2138 amethod = create_array_method (class, ".ctor", sig);
2139 methods [method_num++] = amethod;
2140 if (class->rank > 1) {
2141 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2142 sig->ret = &mono_defaults.void_class->byval_arg;
2143 sig->pinvoke = TRUE;
2144 sig->hasthis = TRUE;
2145 for (i = 0; i < class->rank * 2; ++i)
2146 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2148 amethod = create_array_method (class, ".ctor", sig);
2149 methods [method_num++] = amethod;
2151 /* element Get (idx11, [idx2, ...]) */
2152 sig = mono_metadata_signature_alloc (class->image, class->rank);
2153 sig->ret = &class->element_class->byval_arg;
2154 sig->pinvoke = TRUE;
2155 sig->hasthis = TRUE;
2156 for (i = 0; i < class->rank; ++i)
2157 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2158 amethod = create_array_method (class, "Get", sig);
2159 methods [method_num++] = amethod;
2160 /* element& Address (idx11, [idx2, ...]) */
2161 sig = mono_metadata_signature_alloc (class->image, class->rank);
2162 sig->ret = &class->element_class->this_arg;
2163 sig->pinvoke = TRUE;
2164 sig->hasthis = TRUE;
2165 for (i = 0; i < class->rank; ++i)
2166 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2167 amethod = create_array_method (class, "Address", sig);
2168 methods [method_num++] = amethod;
2169 /* void Set (idx11, [idx2, ...], element) */
2170 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2171 sig->ret = &mono_defaults.void_class->byval_arg;
2172 sig->pinvoke = TRUE;
2173 sig->hasthis = TRUE;
2174 for (i = 0; i < class->rank; ++i)
2175 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2176 sig->params [i] = &class->element_class->byval_arg;
2177 amethod = create_array_method (class, "Set", sig);
2178 methods [method_num++] = amethod;
2180 for (i = 0; i < class->interface_count; i++)
2181 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2183 count = class->method.count;
2184 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2185 for (i = 0; i < count; ++i) {
2186 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2187 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2191 if (MONO_CLASS_IS_INTERFACE (class)) {
2193 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2194 for (i = 0; i < count; ++i) {
2195 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2196 methods [i]->slot = slot++;
2200 mono_image_lock (class->image);
2202 if (!class->methods) {
2203 class->method.count = count;
2205 /* Needed because of the double-checking locking pattern */
2206 mono_memory_barrier ();
2208 class->methods = methods;
2211 mono_image_unlock (class->image);
2215 * mono_class_get_method_by_index:
2217 * Returns class->methods [index], initializing class->methods if neccesary.
2219 * LOCKING: Acquires the loader lock.
2222 mono_class_get_method_by_index (MonoClass *class, int index)
2224 /* Avoid calling setup_methods () if possible */
2225 if (class->generic_class && !class->methods) {
2226 MonoClass *gklass = class->generic_class->container_class;
2229 m = mono_class_inflate_generic_method_full (
2230 gklass->methods [index], class, mono_class_get_context (class));
2232 * If setup_methods () is called later for this class, no duplicates are created,
2233 * since inflate_generic_method guarantees that only one instance of a method
2234 * is created for each context.
2237 mono_class_setup_methods (class);
2238 g_assert (m == class->methods [index]);
2242 mono_class_setup_methods (class);
2243 if (class->exception_type) /*FIXME do proper error handling*/
2245 g_assert (index >= 0 && index < class->method.count);
2246 return class->methods [index];
2251 * mono_class_get_inflated_method:
2253 * Given an inflated class CLASS and a method METHOD which should be a method of
2254 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2257 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2259 MonoClass *gklass = class->generic_class->container_class;
2262 g_assert (method->klass == gklass);
2264 mono_class_setup_methods (gklass);
2265 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2267 for (i = 0; i < gklass->method.count; ++i) {
2268 if (gklass->methods [i] == method) {
2270 return class->methods [i];
2272 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2280 * mono_class_get_vtable_entry:
2282 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2283 * LOCKING: Acquires the loader lock.
2286 mono_class_get_vtable_entry (MonoClass *class, int offset)
2290 if (class->rank == 1) {
2292 * szarrays do not overwrite any methods of Array, so we can avoid
2293 * initializing their vtables in some cases.
2295 mono_class_setup_vtable (class->parent);
2296 if (offset < class->parent->vtable_size)
2297 return class->parent->vtable [offset];
2300 if (class->generic_class) {
2301 MonoClass *gklass = class->generic_class->container_class;
2302 mono_class_setup_vtable (gklass);
2303 m = gklass->vtable [offset];
2305 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2307 mono_class_setup_vtable (class);
2308 if (class->exception_type)
2310 m = class->vtable [offset];
2317 * mono_class_get_vtable_size:
2319 * Return the vtable size for KLASS.
2322 mono_class_get_vtable_size (MonoClass *klass)
2324 mono_class_setup_vtable (klass);
2326 return klass->vtable_size;
2330 * mono_class_setup_properties:
2332 * Initialize class->ext.property and class->ext.properties.
2334 * This method can fail the class.
2337 mono_class_setup_properties (MonoClass *class)
2339 guint startm, endm, i, j;
2340 guint32 cols [MONO_PROPERTY_SIZE];
2341 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2342 MonoProperty *properties;
2346 if (class->ext && class->ext->properties)
2349 if (class->generic_class) {
2350 MonoClass *gklass = class->generic_class->container_class;
2352 mono_class_init (gklass);
2353 mono_class_setup_properties (gklass);
2354 if (gklass->exception_type) {
2355 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2359 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2361 for (i = 0; i < gklass->ext->property.count; i++) {
2362 MonoProperty *prop = &properties [i];
2364 *prop = gklass->ext->properties [i];
2367 prop->get = mono_class_inflate_generic_method_full (
2368 prop->get, class, mono_class_get_context (class));
2370 prop->set = mono_class_inflate_generic_method_full (
2371 prop->set, class, mono_class_get_context (class));
2373 prop->parent = class;
2376 first = gklass->ext->property.first;
2377 count = gklass->ext->property.count;
2379 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2380 count = last - first;
2383 mono_class_setup_methods (class);
2384 if (class->exception_type)
2388 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2389 for (i = first; i < last; ++i) {
2390 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2391 properties [i - first].parent = class;
2392 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2393 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2395 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2396 for (j = startm; j < endm; ++j) {
2399 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2401 if (class->image->uncompressed_metadata)
2402 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2403 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2405 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2407 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2408 case METHOD_SEMANTIC_SETTER:
2409 properties [i - first].set = method;
2411 case METHOD_SEMANTIC_GETTER:
2412 properties [i - first].get = method;
2421 mono_class_alloc_ext (class);
2423 mono_image_lock (class->image);
2425 if (class->ext->properties) {
2426 /* We leak 'properties' which was allocated from the image mempool */
2427 mono_image_unlock (class->image);
2431 class->ext->property.first = first;
2432 class->ext->property.count = count;
2434 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2435 mono_memory_barrier ();
2437 /* Leave this assignment as the last op in the function */
2438 class->ext->properties = properties;
2440 mono_image_unlock (class->image);
2444 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2446 MonoMethod **om, **retval;
2449 for (om = methods, count = 0; *om; ++om, ++count)
2452 retval = g_new0 (MonoMethod*, count + 1);
2454 for (om = methods, count = 0; *om; ++om, ++count)
2455 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2460 /*This method can fail the class.*/
2462 mono_class_setup_events (MonoClass *class)
2465 guint startm, endm, i, j;
2466 guint32 cols [MONO_EVENT_SIZE];
2467 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2471 if (class->ext && class->ext->events)
2474 if (class->generic_class) {
2475 MonoClass *gklass = class->generic_class->container_class;
2476 MonoGenericContext *context;
2478 mono_class_setup_events (gklass);
2479 if (gklass->exception_type) {
2480 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2484 first = gklass->ext->event.first;
2485 count = gklass->ext->event.count;
2487 events = mono_class_new0 (class, MonoEvent, count);
2490 context = mono_class_get_context (class);
2492 for (i = 0; i < count; i++) {
2493 MonoEvent *event = &events [i];
2494 MonoEvent *gevent = &gklass->ext->events [i];
2496 event->parent = class;
2497 event->name = gevent->name;
2498 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2499 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2500 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2501 #ifndef MONO_SMALL_CONFIG
2502 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2504 event->attrs = gevent->attrs;
2507 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2508 count = last - first;
2511 mono_class_setup_methods (class);
2512 if (class->exception_type) {
2513 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2518 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2519 for (i = first; i < last; ++i) {
2520 MonoEvent *event = &events [i - first];
2522 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2523 event->parent = class;
2524 event->attrs = cols [MONO_EVENT_FLAGS];
2525 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2527 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2528 for (j = startm; j < endm; ++j) {
2531 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2533 if (class->image->uncompressed_metadata)
2534 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2535 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2537 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2539 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2540 case METHOD_SEMANTIC_ADD_ON:
2541 event->add = method;
2543 case METHOD_SEMANTIC_REMOVE_ON:
2544 event->remove = method;
2546 case METHOD_SEMANTIC_FIRE:
2547 event->raise = method;
2549 case METHOD_SEMANTIC_OTHER: {
2550 #ifndef MONO_SMALL_CONFIG
2553 if (event->other == NULL) {
2554 event->other = g_new0 (MonoMethod*, 2);
2556 while (event->other [n])
2558 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2560 event->other [n] = method;
2561 /* NULL terminated */
2562 event->other [n + 1] = NULL;
2573 mono_class_alloc_ext (class);
2575 mono_image_lock (class->image);
2577 if (class->ext->events) {
2578 mono_image_unlock (class->image);
2582 class->ext->event.first = first;
2583 class->ext->event.count = count;
2585 /* Flush any pending writes as we do double checked locking on class->ext.events */
2586 mono_memory_barrier ();
2588 /* Leave this assignment as the last op in the function */
2589 class->ext->events = events;
2591 mono_image_unlock (class->image);
2595 * Global pool of interface IDs, represented as a bitset.
2596 * LOCKING: Protected by the classes lock.
2598 static MonoBitSet *global_interface_bitset = NULL;
2601 * mono_unload_interface_ids:
2602 * @bitset: bit set of interface IDs
2604 * When an image is unloaded, the interface IDs associated with
2605 * the image are put back in the global pool of IDs so the numbers
2609 mono_unload_interface_ids (MonoBitSet *bitset)
2612 mono_bitset_sub (global_interface_bitset, bitset);
2617 mono_unload_interface_id (MonoClass *class)
2619 if (global_interface_bitset && class->interface_id) {
2621 mono_bitset_clear (global_interface_bitset, class->interface_id);
2627 * mono_get_unique_iid:
2630 * Assign a unique integer ID to the interface represented by @class.
2631 * The ID will positive and as small as possible.
2632 * LOCKING: Acquires the classes lock.
2633 * Returns: the new ID.
2636 mono_get_unique_iid (MonoClass *class)
2640 g_assert (MONO_CLASS_IS_INTERFACE (class));
2644 if (!global_interface_bitset) {
2645 global_interface_bitset = mono_bitset_new (128, 0);
2648 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2650 int old_size = mono_bitset_size (global_interface_bitset);
2651 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2652 mono_bitset_free (global_interface_bitset);
2653 global_interface_bitset = new_set;
2656 mono_bitset_set (global_interface_bitset, iid);
2657 /* set the bit also in the per-image set */
2658 if (!class->generic_class) {
2659 if (class->image->interface_bitset) {
2660 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2661 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2662 mono_bitset_free (class->image->interface_bitset);
2663 class->image->interface_bitset = new_set;
2666 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2668 mono_bitset_set (class->image->interface_bitset, iid);
2673 #ifndef MONO_SMALL_CONFIG
2674 if (mono_print_vtable) {
2676 char *type_name = mono_type_full_name (&class->byval_arg);
2677 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2678 generic_id = class->generic_class->context.class_inst->id;
2679 g_assert (generic_id != 0);
2683 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2688 g_assert (iid <= 65535);
2693 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2698 mono_class_setup_interfaces (klass, error);
2699 if (!mono_error_ok (error))
2702 for (i = 0; i < klass->interface_count; i++) {
2703 ic = klass->interfaces [i];
2706 *res = g_ptr_array_new ();
2707 g_ptr_array_add (*res, ic);
2708 mono_class_init (ic);
2709 if (ic->exception_type) {
2710 mono_error_set_type_load_class (error, ic, "Error Loading class");
2714 collect_implemented_interfaces_aux (ic, res, error);
2715 if (!mono_error_ok (error))
2721 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2723 GPtrArray *res = NULL;
2725 collect_implemented_interfaces_aux (klass, &res, error);
2726 if (!mono_error_ok (error)) {
2728 g_ptr_array_free (res, TRUE);
2735 compare_interface_ids (const void *p_key, const void *p_element) {
2736 const MonoClass *key = p_key;
2737 const MonoClass *element = *(MonoClass**) p_element;
2739 return (key->interface_id - element->interface_id);
2742 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2744 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2745 MonoClass **result = mono_binary_search (
2747 klass->interfaces_packed,
2748 klass->interface_offsets_count,
2749 sizeof (MonoClass *),
2750 compare_interface_ids);
2752 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2759 * mono_class_interface_offset_with_variance:
2761 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2762 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2764 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2766 * FIXME figure out MS disambiguation rules and fix this function.
2769 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2770 int i = mono_class_interface_offset (klass, itf);
2771 *non_exact_match = FALSE;
2775 if (!mono_class_has_variant_generic_params (itf))
2778 for (i = 0; i < klass->interface_offsets_count; i++) {
2779 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2780 *non_exact_match = TRUE;
2781 return klass->interface_offsets_packed [i];
2789 print_implemented_interfaces (MonoClass *klass) {
2792 GPtrArray *ifaces = NULL;
2794 int ancestor_level = 0;
2796 name = mono_type_get_full_name (klass);
2797 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2800 for (i = 0; i < klass->interface_offsets_count; i++)
2801 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2802 klass->interfaces_packed [i]->interface_id,
2803 klass->interface_offsets_packed [i],
2804 klass->interfaces_packed [i]->method.count,
2805 klass->interfaces_packed [i]->name_space,
2806 klass->interfaces_packed [i]->name );
2807 printf ("Interface flags: ");
2808 for (i = 0; i <= klass->max_interface_id; i++)
2809 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2810 printf ("(%d,T)", i);
2812 printf ("(%d,F)", i);
2814 printf ("Dump interface flags:");
2815 #ifdef COMPRESSED_INTERFACE_BITMAP
2817 const uint8_t* p = klass->interface_bitmap;
2818 i = klass->max_interface_id;
2820 printf (" %d x 00 %02X", p [0], p [1]);
2826 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2827 printf (" %02X", klass->interface_bitmap [i]);
2830 while (klass != NULL) {
2831 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2832 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2833 if (!mono_error_ok (&error)) {
2834 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2835 mono_error_cleanup (&error);
2836 } else if (ifaces) {
2837 for (i = 0; i < ifaces->len; i++) {
2838 MonoClass *ic = g_ptr_array_index (ifaces, i);
2839 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2840 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2842 mono_class_interface_offset (klass, ic),
2847 g_ptr_array_free (ifaces, TRUE);
2850 klass = klass->parent;
2855 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2858 args [0] = &arg0->byval_arg;
2860 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2864 array_class_get_if_rank (MonoClass *class, guint rank)
2866 return rank ? mono_array_class_get (class, rank) : class;
2870 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2872 valuetype_types [0] = eclass;
2873 if (eclass == mono_defaults.int16_class)
2874 valuetype_types [1] = mono_defaults.uint16_class;
2875 else if (eclass == mono_defaults.uint16_class)
2876 valuetype_types [1] = mono_defaults.int16_class;
2877 else if (eclass == mono_defaults.int32_class)
2878 valuetype_types [1] = mono_defaults.uint32_class;
2879 else if (eclass == mono_defaults.uint32_class)
2880 valuetype_types [1] = mono_defaults.int32_class;
2881 else if (eclass == mono_defaults.int64_class)
2882 valuetype_types [1] = mono_defaults.uint64_class;
2883 else if (eclass == mono_defaults.uint64_class)
2884 valuetype_types [1] = mono_defaults.int64_class;
2885 else if (eclass == mono_defaults.byte_class)
2886 valuetype_types [1] = mono_defaults.sbyte_class;
2887 else if (eclass == mono_defaults.sbyte_class)
2888 valuetype_types [1] = mono_defaults.byte_class;
2889 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2890 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2893 /* this won't be needed once bug #325495 is completely fixed
2894 * though we'll need something similar to know which interfaces to allow
2895 * in arrays when they'll be lazyly created
2897 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2898 * MS returns diferrent types based on which instance is called. For example:
2899 * object obj = new byte[10][];
2900 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2901 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2904 * Fixing this should kill quite some code, save some bits and improve compatibility.
2907 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2909 MonoClass *eclass = class->element_class;
2910 static MonoClass* generic_icollection_class = NULL;
2911 static MonoClass* generic_ienumerable_class = NULL;
2912 static MonoClass* generic_ienumerator_class = NULL;
2913 static MonoClass* generic_ireadonlylist_class = NULL;
2914 static MonoClass* generic_ireadonlycollection_class = NULL;
2915 MonoClass *valuetype_types[2] = { NULL, NULL };
2916 MonoClass **interfaces = NULL;
2917 int i, nifaces, interface_count, real_count, original_rank;
2919 gboolean internal_enumerator;
2920 gboolean eclass_is_valuetype;
2922 if (!mono_defaults.generic_ilist_class) {
2926 internal_enumerator = FALSE;
2927 eclass_is_valuetype = FALSE;
2928 original_rank = eclass->rank;
2929 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2930 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2932 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2934 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2935 original_rank = eclass->rank;
2937 eclass = eclass->element_class;
2938 internal_enumerator = TRUE;
2939 *is_enumerator = TRUE;
2947 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2948 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2950 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2952 if (!generic_icollection_class) {
2953 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2954 "System.Collections.Generic", "ICollection`1");
2955 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2956 "System.Collections.Generic", "IEnumerable`1");
2957 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2958 "System.Collections.Generic", "IEnumerator`1");
2959 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2960 "System.Collections.Generic", "IReadOnlyList`1");
2961 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2962 "System.Collections.Generic", "IReadOnlyCollection`1");
2965 mono_class_init (eclass);
2968 * Arrays in 2.0 need to implement a number of generic interfaces
2969 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2970 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2971 * We collect the types needed to build the
2972 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2973 * the generic interfaces needed to implement.
2975 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2976 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2978 if (eclass->valuetype) {
2979 nifaces = generic_ireadonlylist_class ? 5 : 3;
2980 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2982 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2983 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2984 if (internal_enumerator) {
2986 if (valuetype_types [1])
2990 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2991 interfaces [0] = valuetype_types [0];
2992 if (valuetype_types [1])
2993 interfaces [nifaces] = valuetype_types [1];
2995 eclass_is_valuetype = TRUE;
2998 int idepth = eclass->idepth;
2999 if (!internal_enumerator)
3001 nifaces = generic_ireadonlylist_class ? 2 : 3;
3003 // FIXME: This doesn't seem to work/required for generic params
3004 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3005 mono_class_setup_interface_offsets (eclass);
3007 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3008 /* we add object for interfaces and the supertypes for the other
3009 * types. The last of the supertypes is the element class itself which we
3010 * already created the explicit interfaces for (so we include it for IEnumerator
3011 * and exclude it for arrays).
3013 if (MONO_CLASS_IS_INTERFACE (eclass))
3016 interface_count += idepth;
3017 if (eclass->rank && eclass->element_class->valuetype) {
3018 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3019 if (valuetype_types [1])
3022 /* IList, ICollection, IEnumerable, IReadOnlyList */
3023 interface_count *= nifaces;
3024 real_count = interface_count;
3025 if (internal_enumerator) {
3026 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3027 if (valuetype_types [1])
3030 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3031 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3032 interfaces [0] = mono_defaults.object_class;
3036 for (i = 0; i < idepth; i++) {
3037 mono_class_init (eclass->supertypes [i]);
3038 interfaces [j] = eclass->supertypes [i];
3042 if (all_interfaces) {
3043 for (i = 0; i < eclass->interface_offsets_count; i++) {
3044 interfaces [j] = eclass->interfaces_packed [i];
3048 for (i = 0; i < eclass->interface_count; i++) {
3049 interfaces [j] = eclass->interfaces [i];
3053 if (valuetype_types [1]) {
3054 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3059 /* instantiate the generic interfaces */
3060 for (i = 0; i < interface_count; i += nifaces) {
3061 MonoClass *iface = interfaces [i];
3063 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3064 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3066 if (eclass->valuetype) {
3067 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3068 if (generic_ireadonlylist_class) {
3069 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3070 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3073 if (!generic_ireadonlylist_class)
3074 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3077 if (internal_enumerator) {
3079 /* instantiate IEnumerator<iface> */
3080 for (i = 0; i < interface_count; i++) {
3081 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3083 j = interface_count;
3084 if (!eclass_is_valuetype) {
3085 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3086 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3089 for (i = 0; i < eclass->idepth; i++) {
3090 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3094 for (i = 0; i < eclass->interface_offsets_count; i++) {
3095 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3099 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3101 if (valuetype_types [1])
3102 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3106 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3107 for (i = 0; i < real_count; ++i) {
3108 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3109 g_print ("%s implements %s\n", type_name, name);
3120 find_array_interface (MonoClass *klass, const char *name)
3123 for (i = 0; i < klass->interface_count; ++i) {
3124 if (strcmp (klass->interfaces [i]->name, name) == 0)
3131 * Return the number of virtual methods.
3132 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3133 * Return -1 on failure.
3134 * FIXME It would be nice if this information could be cached somewhere.
3137 count_virtual_methods (MonoClass *class)
3141 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3143 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3144 mono_class_setup_methods (class);
3145 if (class->exception_type)
3148 for (i = 0; i < class->method.count; ++i) {
3149 flags = class->methods [i]->flags;
3150 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3154 for (i = 0; i < class->method.count; ++i) {
3155 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3157 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3165 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3173 m = (l + num_ifaces) / 2;
3174 if (interfaces_full [m] == ic)
3176 if (l == num_ifaces)
3178 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3187 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3189 int i = find_interface (num_ifaces, interfaces_full, ic);
3191 return interface_offsets_full [i];
3196 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3198 int i = find_interface (num_ifaces, interfaces_full, ic);
3202 interface_offsets_full [i] = offset;
3205 for (i = 0; i < num_ifaces; ++i) {
3206 if (interfaces_full [i]) {
3208 if (interfaces_full [i]->interface_id < ic->interface_id)
3211 while (end < num_ifaces && interfaces_full [end]) end++;
3212 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3213 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3215 interfaces_full [i] = ic;
3216 interface_offsets_full [i] = offset;
3222 #ifdef COMPRESSED_INTERFACE_BITMAP
3225 * Compressed interface bitmap design.
3227 * Interface bitmaps take a large amount of memory, because their size is
3228 * linear with the maximum interface id assigned in the process (each interface
3229 * is assigned a unique id as it is loaded). The number of interface classes
3230 * is high because of the many implicit interfaces implemented by arrays (we'll
3231 * need to lazy-load them in the future).
3232 * Most classes implement a very small number of interfaces, so the bitmap is
3233 * sparse. This bitmap needs to be checked by interface casts, so access to the
3234 * needed bit must be fast and doable with few jit instructions.
3236 * The current compression format is as follows:
3237 * *) it is a sequence of one or more two-byte elements
3238 * *) the first byte in the element is the count of empty bitmap bytes
3239 * at the current bitmap position
3240 * *) the second byte in the element is an actual bitmap byte at the current
3243 * As an example, the following compressed bitmap bytes:
3244 * 0x07 0x01 0x00 0x7
3245 * correspond to the following bitmap:
3246 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3248 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3249 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3250 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3254 * mono_compress_bitmap:
3255 * @dest: destination buffer
3256 * @bitmap: bitmap buffer
3257 * @size: size of @bitmap in bytes
3259 * This is a mono internal function.
3260 * The @bitmap data is compressed into a format that is small but
3261 * still searchable in few instructions by the JIT and runtime.
3262 * The compressed data is stored in the buffer pointed to by the
3263 * @dest array. Passing a #NULL value for @dest allows to just compute
3264 * the size of the buffer.
3265 * This compression algorithm assumes the bits set in the bitmap are
3266 * few and far between, like in interface bitmaps.
3267 * Returns: the size of the compressed bitmap in bytes.
3270 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3274 const uint8_t *end = bitmap + size;
3275 while (bitmap < end) {
3276 if (*bitmap || numz == 255) {
3300 * mono_class_interface_match:
3301 * @bitmap: a compressed bitmap buffer
3302 * @id: the index to check in the bitmap
3304 * This is a mono internal function.
3305 * Checks if a bit is set in a compressed interface bitmap. @id must
3306 * be already checked for being smaller than the maximum id encoded in the
3309 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3313 mono_class_interface_match (const uint8_t *bitmap, int id)
3316 id -= bitmap [0] * 8;
3320 return bitmap [1] & (1 << id);
3329 * LOCKING: this is supposed to be called with the loader lock held.
3330 * Return -1 on failure and set exception_type
3333 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3337 int i, j, max_iid, num_ifaces;
3338 MonoClass **interfaces_full = NULL;
3339 int *interface_offsets_full = NULL;
3341 GPtrArray **ifaces_array = NULL;
3342 int interface_offsets_count;
3343 MonoClass **array_interfaces = NULL;
3344 int num_array_interfaces;
3345 int is_enumerator = FALSE;
3347 mono_class_setup_supertypes (class);
3349 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3350 * implicit interfaces have the property that they are assigned the same slot in the
3351 * vtables for compatible interfaces
3353 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3355 /* compute maximum number of slots and maximum interface id */
3357 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3358 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3359 for (j = 0; j < class->idepth; j++) {
3360 k = class->supertypes [j];
3361 num_ifaces += k->interface_count;
3362 for (i = 0; i < k->interface_count; i++) {
3363 ic = k->interfaces [i];
3366 mono_class_init (ic);
3368 if (max_iid < ic->interface_id)
3369 max_iid = ic->interface_id;
3371 ifaces = mono_class_get_implemented_interfaces (k, &error);
3372 if (!mono_error_ok (&error)) {
3373 char *name = mono_type_get_full_name (k);
3374 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)));
3376 mono_error_cleanup (&error);
3381 num_ifaces += ifaces->len;
3382 for (i = 0; i < ifaces->len; ++i) {
3383 ic = g_ptr_array_index (ifaces, i);
3384 if (max_iid < ic->interface_id)
3385 max_iid = ic->interface_id;
3387 ifaces_array [j] = ifaces;
3391 for (i = 0; i < num_array_interfaces; ++i) {
3392 ic = array_interfaces [i];
3393 mono_class_init (ic);
3394 if (max_iid < ic->interface_id)
3395 max_iid = ic->interface_id;
3398 if (MONO_CLASS_IS_INTERFACE (class)) {
3400 if (max_iid < class->interface_id)
3401 max_iid = class->interface_id;
3403 class->max_interface_id = max_iid;
3404 /* compute vtable offset for interfaces */
3405 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3406 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3408 for (i = 0; i < num_ifaces; i++) {
3409 interface_offsets_full [i] = -1;
3412 /* skip the current class */
3413 for (j = 0; j < class->idepth - 1; j++) {
3414 k = class->supertypes [j];
3415 ifaces = ifaces_array [j];
3418 for (i = 0; i < ifaces->len; ++i) {
3420 ic = g_ptr_array_index (ifaces, i);
3422 /*Force the sharing of interface offsets between parent and subtypes.*/
3423 io = mono_class_interface_offset (k, ic);
3425 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3430 g_assert (class == class->supertypes [class->idepth - 1]);
3431 ifaces = ifaces_array [class->idepth - 1];
3433 for (i = 0; i < ifaces->len; ++i) {
3435 ic = g_ptr_array_index (ifaces, i);
3436 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3438 count = count_virtual_methods (ic);
3440 char *name = mono_type_get_full_name (ic);
3441 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3450 if (MONO_CLASS_IS_INTERFACE (class))
3451 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3453 if (num_array_interfaces) {
3454 if (is_enumerator) {
3455 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3456 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3457 g_assert (ienumerator_offset >= 0);
3458 for (i = 0; i < num_array_interfaces; ++i) {
3459 ic = array_interfaces [i];
3460 if (strcmp (ic->name, "IEnumerator`1") == 0)
3461 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3463 g_assert_not_reached ();
3464 /*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);*/
3467 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3468 int ilist_iface_idx = find_array_interface (class, "IList`1");
3469 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3470 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3471 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3472 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3473 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3474 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3475 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3476 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3477 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3478 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3479 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3480 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3481 for (i = 0; i < num_array_interfaces; ++i) {
3483 ic = array_interfaces [i];
3484 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3485 offset = ilist_offset;
3486 else if (strcmp (ic->name, "ICollection`1") == 0)
3487 offset = icollection_offset;
3488 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3489 offset = ienumerable_offset;
3490 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3491 offset = ireadonlylist_offset;
3492 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3493 offset = ireadonlycollection_offset;
3495 g_assert_not_reached ();
3496 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3497 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3502 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3503 if (interface_offsets_full [i] != -1) {
3504 interface_offsets_count ++;
3509 * We might get called multiple times:
3510 * - mono_class_init ()
3511 * - mono_class_setup_vtable ().
3512 * - mono_class_setup_interface_offsets ().
3513 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3514 * means we have to overwrite those when called from other places (#4440).
3516 if (class->interfaces_packed && !overwrite) {
3517 g_assert (class->interface_offsets_count == interface_offsets_count);
3521 class->interface_offsets_count = interface_offsets_count;
3522 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3523 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3524 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3525 #ifdef COMPRESSED_INTERFACE_BITMAP
3526 bitmap = g_malloc0 (bsize);
3528 bitmap = mono_class_alloc0 (class, bsize);
3530 for (i = 0; i < interface_offsets_count; i++) {
3531 int id = interfaces_full [i]->interface_id;
3532 bitmap [id >> 3] |= (1 << (id & 7));
3533 class->interfaces_packed [i] = interfaces_full [i];
3534 class->interface_offsets_packed [i] = interface_offsets_full [i];
3535 /*if (num_array_interfaces)
3536 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]);*/
3538 #ifdef COMPRESSED_INTERFACE_BITMAP
3539 i = mono_compress_bitmap (NULL, bitmap, bsize);
3540 class->interface_bitmap = mono_class_alloc0 (class, i);
3541 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3544 class->interface_bitmap = bitmap;
3549 g_free (interfaces_full);
3550 g_free (interface_offsets_full);
3551 g_free (array_interfaces);
3552 for (i = 0; i < class->idepth; i++) {
3553 ifaces = ifaces_array [i];
3555 g_ptr_array_free (ifaces, TRUE);
3557 g_free (ifaces_array);
3559 //printf ("JUST DONE: ");
3560 //print_implemented_interfaces (class);
3566 * Setup interface offsets for interfaces.
3568 * - class->max_interface_id
3569 * - class->interface_offsets_count
3570 * - class->interfaces_packed
3571 * - class->interface_offsets_packed
3572 * - class->interface_bitmap
3574 * This function can fail @class.
3577 mono_class_setup_interface_offsets (MonoClass *class)
3579 mono_loader_lock ();
3581 setup_interface_offsets (class, 0, FALSE);
3583 mono_loader_unlock ();
3586 /*Checks if @klass has @parent as one of it's parents type gtd
3590 * Bar<T> : Foo<Bar<Bar<T>>>
3594 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3596 klass = mono_class_get_generic_type_definition (klass);
3597 parent = mono_class_get_generic_type_definition (parent);
3598 mono_class_setup_supertypes (klass);
3599 mono_class_setup_supertypes (parent);
3601 return klass->idepth >= parent->idepth &&
3602 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3606 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3608 MonoGenericInst *ginst;
3610 if (!class->generic_class) {
3611 mono_class_setup_vtable_full (class, in_setup);
3612 return class->exception_type == 0;
3615 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3616 if (class->generic_class->container_class->exception_type) {
3617 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3621 ginst = class->generic_class->context.class_inst;
3622 for (i = 0; i < ginst->type_argc; ++i) {
3624 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3626 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3627 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3628 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3630 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3631 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3639 * mono_class_setup_vtable:
3641 * Creates the generic vtable of CLASS.
3642 * Initializes the following fields in MonoClass:
3645 * Plus all the fields initialized by setup_interface_offsets ().
3646 * If there is an error during vtable construction, class->exception_type is set.
3648 * LOCKING: Acquires the loader lock.
3651 mono_class_setup_vtable (MonoClass *class)
3653 mono_class_setup_vtable_full (class, NULL);
3657 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3659 MonoMethod **overrides;
3660 MonoGenericContext *context;
3668 if (MONO_CLASS_IS_INTERFACE (class)) {
3669 /* This sets method->slot for all methods if this is an interface */
3670 mono_class_setup_methods (class);
3674 if (class->exception_type)
3677 if (g_list_find (in_setup, class))
3680 mono_loader_lock ();
3682 if (class->vtable) {
3683 mono_loader_unlock ();
3687 mono_stats.generic_vtable_count ++;
3688 in_setup = g_list_prepend (in_setup, class);
3690 if (class->generic_class) {
3691 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3692 mono_loader_unlock ();
3693 g_list_remove (in_setup, class);
3697 context = mono_class_get_context (class);
3698 type_token = class->generic_class->container_class->type_token;
3700 context = (MonoGenericContext *) class->generic_container;
3701 type_token = class->type_token;
3704 if (image_is_dynamic (class->image)) {
3705 /* Generic instances can have zero method overrides without causing any harm.
3706 * This is true since we don't do layout all over again for them, we simply inflate
3707 * the layout of the parent.
3709 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3711 /* The following call fails if there are missing methods in the type */
3712 /* FIXME it's probably a good idea to avoid this for generic instances. */
3713 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3717 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3719 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3723 mono_loader_unlock ();
3724 g_list_remove (in_setup, class);
3729 #define DEBUG_INTERFACE_VTABLE_CODE 0
3730 #define TRACE_INTERFACE_VTABLE_CODE 0
3731 #define VERIFY_INTERFACE_VTABLE_CODE 0
3732 #define VTABLE_SELECTOR (1)
3734 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3735 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3736 if (!(VTABLE_SELECTOR)) break; \
3740 #define DEBUG_INTERFACE_VTABLE(stmt)
3743 #if TRACE_INTERFACE_VTABLE_CODE
3744 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3745 if (!(VTABLE_SELECTOR)) break; \
3749 #define TRACE_INTERFACE_VTABLE(stmt)
3752 #if VERIFY_INTERFACE_VTABLE_CODE
3753 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3754 if (!(VTABLE_SELECTOR)) break; \
3758 #define VERIFY_INTERFACE_VTABLE(stmt)
3762 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3764 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3768 GString *res = g_string_new ("");
3770 g_string_append_c (res, '(');
3771 for (i = 0; i < sig->param_count; ++i) {
3773 g_string_append_c (res, ',');
3774 mono_type_get_desc (res, sig->params [i], include_namespace);
3776 g_string_append (res, ")=>");
3777 if (sig->ret != NULL) {
3778 mono_type_get_desc (res, sig->ret, include_namespace);
3780 g_string_append (res, "NULL");
3783 g_string_free (res, FALSE);
3787 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3788 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3789 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3790 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3798 is_wcf_hack_disabled (void)
3800 static gboolean disabled;
3801 static gboolean inited = FALSE;
3803 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3810 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) {
3811 MonoMethodSignature *cmsig, *imsig;
3812 if (strcmp (im->name, cm->name) == 0) {
3813 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3814 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3817 if (! slot_is_empty) {
3818 if (require_newslot) {
3819 if (! interface_is_explicitly_implemented_by_class) {
3820 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3823 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3824 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3828 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3831 cmsig = mono_method_signature (cm);
3832 imsig = mono_method_signature (im);
3833 if (!cmsig || !imsig) {
3834 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3838 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3839 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3840 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3841 TRACE_INTERFACE_VTABLE (printf ("]"));
3844 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3845 /* CAS - SecurityAction.InheritanceDemand on interface */
3846 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3847 mono_secman_inheritancedemand_method (cm, im);
3850 if (mono_security_core_clr_enabled ())
3851 mono_security_core_clr_check_override (class, cm, im);
3853 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3854 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3855 char *body_name = mono_method_full_name (cm, TRUE);
3856 char *decl_name = mono_method_full_name (im, TRUE);
3857 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));
3865 MonoClass *ic = im->klass;
3866 const char *ic_name_space = ic->name_space;
3867 const char *ic_name = ic->name;
3870 if (! require_newslot) {
3871 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3874 if (cm->klass->rank == 0) {
3875 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3878 cmsig = mono_method_signature (cm);
3879 imsig = mono_method_signature (im);
3880 if (!cmsig || !imsig) {
3881 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3885 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3886 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3887 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3888 TRACE_INTERFACE_VTABLE (printf ("]"));
3891 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3892 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3895 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3896 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3899 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))) {
3900 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3904 subname = strstr (cm->name, ic_name_space);
3905 if (subname != cm->name) {
3906 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3909 subname += strlen (ic_name_space);
3910 if (subname [0] != '.') {
3911 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3915 if (strstr (subname, ic_name) != subname) {
3916 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3919 subname += strlen (ic_name);
3920 if (subname [0] != '.') {
3921 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3925 if (strcmp (subname, im->name) != 0) {
3926 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3930 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3931 /* CAS - SecurityAction.InheritanceDemand on interface */
3932 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3933 mono_secman_inheritancedemand_method (cm, im);
3936 if (mono_security_core_clr_enabled ())
3937 mono_security_core_clr_check_override (class, cm, im);
3939 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3940 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3941 char *body_name = mono_method_full_name (cm, TRUE);
3942 char *decl_name = mono_method_full_name (im, TRUE);
3943 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));
3953 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3955 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3956 MonoMethod *method = key;
3957 MonoMethod *override = value;
3958 MonoClass *method_class = mono_method_get_class (method);
3959 MonoClass *override_class = mono_method_get_class (override);
3961 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3962 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3963 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3966 print_overrides (GHashTable *override_map, const char *message) {
3968 printf ("Override map \"%s\" START:\n", message);
3969 g_hash_table_foreach (override_map, foreach_override, NULL);
3970 printf ("Override map \"%s\" END.\n", message);
3972 printf ("Override map \"%s\" EMPTY.\n", message);
3976 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3977 char *full_name = mono_type_full_name (&class->byval_arg);
3981 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3983 if (print_interfaces) {
3984 print_implemented_interfaces (class);
3985 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3988 if (class->parent) {
3989 parent_size = class->parent->vtable_size;
3993 for (i = 0; i < size; ++i) {
3994 MonoMethod *cm = vtable [i];
3995 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3996 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3998 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4006 #if VERIFY_INTERFACE_VTABLE_CODE
4008 mono_method_try_get_vtable_index (MonoMethod *method)
4010 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4011 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4012 if (imethod->declaring->is_generic)
4013 return imethod->declaring->slot;
4015 return method->slot;
4019 mono_class_verify_vtable (MonoClass *class)
4022 char *full_name = mono_type_full_name (&class->byval_arg);
4024 printf ("*** Verifying VTable of class '%s' \n", full_name);
4028 if (!class->methods)
4031 for (i = 0; i < class->method.count; ++i) {
4032 MonoMethod *cm = class->methods [i];
4035 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4039 full_name = mono_method_full_name (cm, TRUE);
4041 slot = mono_method_try_get_vtable_index (cm);
4043 if (slot >= class->vtable_size) {
4044 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4048 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4049 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4050 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4051 g_free (other_name);
4054 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4061 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4063 char *method_signature;
4066 for (index = 0; index < onum; ++index) {
4067 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4068 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4070 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4071 type_name = mono_type_full_name (&class->byval_arg);
4072 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4073 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4074 g_free (method_signature);
4076 mono_class_setup_methods (class);
4077 if (class->exception_type) {
4078 char *name = mono_type_get_full_name (class);
4079 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4083 for (index = 0; index < class->method.count; ++index) {
4084 MonoMethod *cm = class->methods [index];
4085 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4087 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4088 g_free (method_signature);
4093 mono_method_get_method_definition (MonoMethod *method)
4095 while (method->is_inflated)
4096 method = ((MonoMethodInflated*)method)->declaring;
4101 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4105 for (i = 0; i < onum; ++i) {
4106 MonoMethod *decl = overrides [i * 2];
4107 MonoMethod *body = overrides [i * 2 + 1];
4109 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4110 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4114 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4115 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4116 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4118 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4122 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4123 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4124 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4126 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4130 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4131 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4135 body = mono_method_get_method_definition (body);
4136 decl = mono_method_get_method_definition (decl);
4138 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4139 char *body_name = mono_method_full_name (body, TRUE);
4140 char *decl_name = mono_method_full_name (decl, TRUE);
4141 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));
4151 mono_class_need_stelemref_method (MonoClass *class)
4153 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4157 * LOCKING: this is supposed to be called with the loader lock held.
4160 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4164 MonoMethod **vtable;
4165 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4166 GPtrArray *ifaces = NULL;
4167 GHashTable *override_map = NULL;
4168 gboolean security_enabled = mono_security_enabled ();
4170 gpointer class_iter;
4171 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4172 int first_non_interface_slot;
4174 GSList *virt_methods = NULL, *l;
4175 int stelemref_slot = 0;
4180 if (overrides && !verify_class_overrides (class, overrides, onum))
4183 ifaces = mono_class_get_implemented_interfaces (class, &error);
4184 if (!mono_error_ok (&error)) {
4185 char *name = mono_type_get_full_name (class);
4186 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)));
4188 mono_error_cleanup (&error);
4190 } else if (ifaces) {
4191 for (i = 0; i < ifaces->len; i++) {
4192 MonoClass *ic = g_ptr_array_index (ifaces, i);
4193 max_vtsize += ic->method.count;
4195 g_ptr_array_free (ifaces, TRUE);
4199 if (class->parent) {
4200 mono_class_init (class->parent);
4201 mono_class_setup_vtable_full (class->parent, in_setup);
4203 if (class->parent->exception_type) {
4204 char *name = mono_type_get_full_name (class->parent);
4205 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4210 max_vtsize += class->parent->vtable_size;
4211 cur_slot = class->parent->vtable_size;
4214 max_vtsize += class->method.count;
4216 /*Array have a slot for stelemref*/
4217 if (mono_class_need_stelemref_method (class)) {
4218 stelemref_slot = cur_slot;
4223 vtable = alloca (sizeof (gpointer) * max_vtsize);
4224 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4226 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4228 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4229 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4232 max_iid = class->max_interface_id;
4233 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4235 /* Optimized version for generic instances */
4236 if (class->generic_class) {
4238 MonoClass *gklass = class->generic_class->container_class;
4241 mono_class_setup_vtable_full (gklass, in_setup);
4242 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4243 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4247 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4248 class->vtable_size = gklass->vtable_size;
4249 for (i = 0; i < gklass->vtable_size; ++i)
4250 if (gklass->vtable [i]) {
4251 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4252 if (!mono_error_ok (&error)) {
4253 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4254 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4256 mono_error_cleanup (&error);
4260 tmp [i]->slot = gklass->vtable [i]->slot;
4262 mono_memory_barrier ();
4263 class->vtable = tmp;
4265 /* Have to set method->slot for abstract virtual methods */
4266 if (class->methods && gklass->methods) {
4267 for (i = 0; i < class->method.count; ++i)
4268 if (class->methods [i]->slot == -1)
4269 class->methods [i]->slot = gklass->methods [i]->slot;
4275 if (class->parent && class->parent->vtable_size) {
4276 MonoClass *parent = class->parent;
4279 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4281 // Also inherit parent interface vtables, just as a starting point.
4282 // This is needed otherwise bug-77127.exe fails when the property methods
4283 // have different names in the iterface and the class, because for child
4284 // classes the ".override" information is not used anymore.
4285 for (i = 0; i < parent->interface_offsets_count; i++) {
4286 MonoClass *parent_interface = parent->interfaces_packed [i];
4287 int interface_offset = mono_class_interface_offset (class, parent_interface);
4288 /*FIXME this is now dead code as this condition will never hold true.
4289 Since interface offsets are inherited then the offset of an interface implemented
4290 by a parent will never be the out of it's vtable boundary.
4292 if (interface_offset >= parent->vtable_size) {
4293 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4296 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4297 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4298 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4299 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4300 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4301 parent_interface_offset + j, parent_interface_offset, j,
4302 interface_offset + j, interface_offset, j));
4309 /*Array have a slot for stelemref*/
4310 if (mono_class_need_stelemref_method (class)) {
4311 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4313 method->slot = stelemref_slot;
4315 g_assert (method->slot == stelemref_slot);
4317 vtable [stelemref_slot] = method;
4320 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4321 /* override interface methods */
4322 for (i = 0; i < onum; i++) {
4323 MonoMethod *decl = overrides [i*2];
4324 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4326 dslot = mono_method_get_vtable_slot (decl);
4328 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4332 dslot += mono_class_interface_offset (class, decl->klass);
4333 vtable [dslot] = overrides [i*2 + 1];
4334 vtable [dslot]->slot = dslot;
4336 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4338 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4340 if (mono_security_core_clr_enabled ())
4341 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4344 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4345 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4348 * Create a list of virtual methods to avoid calling
4349 * mono_class_get_virtual_methods () which is slow because of the metadata
4353 gpointer iter = NULL;
4356 virt_methods = NULL;
4357 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4358 virt_methods = g_slist_prepend (virt_methods, cm);
4360 if (class->exception_type)
4364 // Loop on all implemented interfaces...
4365 for (i = 0; i < class->interface_offsets_count; i++) {
4366 MonoClass *parent = class->parent;
4368 gboolean interface_is_explicitly_implemented_by_class;
4371 ic = class->interfaces_packed [i];
4372 ic_offset = mono_class_interface_offset (class, ic);
4374 mono_class_setup_methods (ic);
4375 if (ic->exception_type)
4378 // Check if this interface is explicitly implemented (instead of just inherited)
4379 if (parent != NULL) {
4380 int implemented_interfaces_index;
4381 interface_is_explicitly_implemented_by_class = FALSE;
4382 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4383 if (ic == class->interfaces [implemented_interfaces_index]) {
4384 interface_is_explicitly_implemented_by_class = TRUE;
4389 interface_is_explicitly_implemented_by_class = TRUE;
4392 // Loop on all interface methods...
4393 for (im_index = 0; im_index < ic->method.count; im_index++) {
4394 MonoMethod *im = ic->methods [im_index];
4395 int im_slot = ic_offset + im->slot;
4396 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4398 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4401 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4403 // If there is an explicit implementation, just use it right away,
4404 // otherwise look for a matching method
4405 if (override_im == NULL) {
4410 // First look for a suitable method among the class methods
4412 for (l = virt_methods; l; l = l->next) {
4414 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)));
4415 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4416 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4417 vtable [im_slot] = cm;
4418 /* Why do we need this? */
4423 TRACE_INTERFACE_VTABLE (printf ("\n"));
4424 if (class->exception_type) /*Might be set by check_interface_method_override*/
4428 // If the slot is still empty, look in all the inherited virtual methods...
4429 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4430 MonoClass *parent = class->parent;
4431 // Reverse order, so that last added methods are preferred
4432 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4433 MonoMethod *cm = parent->vtable [cm_index];
4435 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));
4436 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4437 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4438 vtable [im_slot] = cm;
4439 /* Why do we need this? */
4445 if (class->exception_type) /*Might be set by check_interface_method_override*/
4447 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4451 g_assert (vtable [im_slot] == override_im);
4456 // If the class is not abstract, check that all its interface slots are full.
4457 // The check is done here and not directly at the end of the loop above because
4458 // it can happen (for injected generic array interfaces) that the same slot is
4459 // processed multiple times (those interfaces have overlapping slots), and it
4460 // will not always be the first pass the one that fills the slot.
4461 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4462 for (i = 0; i < class->interface_offsets_count; i++) {
4466 ic = class->interfaces_packed [i];
4467 ic_offset = mono_class_interface_offset (class, ic);
4469 for (im_index = 0; im_index < ic->method.count; im_index++) {
4470 MonoMethod *im = ic->methods [im_index];
4471 int im_slot = ic_offset + im->slot;
4473 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4476 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4477 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4478 if (vtable [im_slot] == NULL) {
4479 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4486 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4488 for (l = virt_methods; l; l = l->next) {
4491 * If the method is REUSE_SLOT, we must check in the
4492 * base class for a method to override.
4494 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4496 for (k = class->parent; k ; k = k->parent) {
4501 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4502 MonoMethodSignature *cmsig, *m1sig;
4504 cmsig = mono_method_signature (cm);
4505 m1sig = mono_method_signature (m1);
4507 if (!cmsig || !m1sig) {
4508 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4512 if (!strcmp(cm->name, m1->name) &&
4513 mono_metadata_signature_equal (cmsig, m1sig)) {
4515 /* CAS - SecurityAction.InheritanceDemand */
4516 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4517 mono_secman_inheritancedemand_method (cm, m1);
4520 if (mono_security_core_clr_enabled ())
4521 mono_security_core_clr_check_override (class, cm, m1);
4523 slot = mono_method_get_vtable_slot (m1);
4527 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4528 char *body_name = mono_method_full_name (cm, TRUE);
4529 char *decl_name = mono_method_full_name (m1, TRUE);
4530 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));
4536 g_assert (cm->slot < max_vtsize);
4538 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4539 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4540 mono_method_full_name (m1, 1), m1,
4541 mono_method_full_name (cm, 1), cm));
4542 g_hash_table_insert (override_map, m1, cm);
4546 if (k->exception_type)
4556 /*Non final newslot methods must be given a non-interface vtable slot*/
4557 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4561 cm->slot = cur_slot++;
4563 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4564 vtable [cm->slot] = cm;
4567 /* override non interface methods */
4568 for (i = 0; i < onum; i++) {
4569 MonoMethod *decl = overrides [i*2];
4570 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4571 g_assert (decl->slot != -1);
4572 vtable [decl->slot] = overrides [i*2 + 1];
4573 overrides [i * 2 + 1]->slot = decl->slot;
4575 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4576 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4577 mono_method_full_name (decl, 1), decl,
4578 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4579 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4581 if (mono_security_core_clr_enabled ())
4582 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4587 * If a method occupies more than one place in the vtable, and it is
4588 * overriden, then change the other occurances too.
4593 for (i = 0; i < max_vtsize; ++i)
4595 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4597 cm = g_hash_table_lookup (override_map, vtable [i]);
4602 g_hash_table_destroy (override_map);
4603 override_map = NULL;
4606 g_slist_free (virt_methods);
4607 virt_methods = NULL;
4609 /* Ensure that all vtable slots are filled with concrete instance methods */
4610 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4611 for (i = 0; i < cur_slot; ++i) {
4612 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4613 char *type_name = mono_type_get_full_name (class);
4614 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4615 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));
4617 g_free (method_name);
4623 if (class->generic_class) {
4624 MonoClass *gklass = class->generic_class->container_class;
4626 mono_class_init (gklass);
4628 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4630 /* Check that the vtable_size value computed in mono_class_init () is correct */
4631 if (class->vtable_size)
4632 g_assert (cur_slot == class->vtable_size);
4633 class->vtable_size = cur_slot;
4636 /* Try to share the vtable with our parent. */
4637 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4638 mono_memory_barrier ();
4639 class->vtable = class->parent->vtable;
4641 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4642 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4643 mono_memory_barrier ();
4644 class->vtable = tmp;
4647 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4648 if (mono_print_vtable) {
4651 print_implemented_interfaces (class);
4653 for (i = 0; i <= max_iid; i++)
4654 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4657 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4658 class->vtable_size, icount);
4660 for (i = 0; i < cur_slot; ++i) {
4665 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4666 mono_method_full_name (cm, TRUE));
4672 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4673 class->name, max_iid);
4675 for (i = 0; i < class->interface_count; i++) {
4676 ic = class->interfaces [i];
4677 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4678 mono_class_interface_offset (class, ic),
4679 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4682 for (k = class->parent; k ; k = k->parent) {
4683 for (i = 0; i < k->interface_count; i++) {
4684 ic = k->interfaces [i];
4685 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4686 mono_class_interface_offset (class, ic),
4687 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4693 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4698 char *name = mono_type_get_full_name (class);
4699 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4702 g_hash_table_destroy (override_map);
4704 g_slist_free (virt_methods);
4709 * mono_method_get_vtable_slot:
4711 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4712 * LOCKING: Acquires the loader lock.
4714 * FIXME Use proper MonoError machinery here.
4717 mono_method_get_vtable_slot (MonoMethod *method)
4719 if (method->slot == -1) {
4720 mono_class_setup_vtable (method->klass);
4721 if (method->klass->exception_type)
4723 if (method->slot == -1) {
4727 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4728 g_assert (method->klass->generic_class);
4729 gklass = method->klass->generic_class->container_class;
4730 mono_class_setup_methods (method->klass);
4731 g_assert (method->klass->methods);
4732 for (i = 0; i < method->klass->method.count; ++i) {
4733 if (method->klass->methods [i] == method)
4736 g_assert (i < method->klass->method.count);
4737 g_assert (gklass->methods);
4738 method->slot = gklass->methods [i]->slot;
4740 g_assert (method->slot != -1);
4742 return method->slot;
4746 * mono_method_get_vtable_index:
4749 * Returns the index into the runtime vtable to access the method or,
4750 * in the case of a virtual generic method, the virtual generic method
4751 * thunk. Returns -1 on failure.
4753 * FIXME Use proper MonoError machinery here.
4756 mono_method_get_vtable_index (MonoMethod *method)
4758 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4759 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4760 if (imethod->declaring->is_generic)
4761 return mono_method_get_vtable_slot (imethod->declaring);
4763 return mono_method_get_vtable_slot (method);
4766 static MonoMethod *default_ghc = NULL;
4767 static MonoMethod *default_finalize = NULL;
4768 static int finalize_slot = -1;
4769 static int ghc_slot = -1;
4772 initialize_object_slots (MonoClass *class)
4777 if (class == mono_defaults.object_class) {
4778 mono_class_setup_vtable (class);
4779 for (i = 0; i < class->vtable_size; ++i) {
4780 MonoMethod *cm = class->vtable [i];
4782 if (!strcmp (cm->name, "GetHashCode"))
4784 else if (!strcmp (cm->name, "Finalize"))
4788 g_assert (ghc_slot > 0);
4789 default_ghc = class->vtable [ghc_slot];
4791 g_assert (finalize_slot > 0);
4792 default_finalize = class->vtable [finalize_slot];
4797 MonoMethod *array_method;
4799 } GenericArrayMethodInfo;
4801 static int generic_array_method_num = 0;
4802 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4805 generic_array_methods (MonoClass *class)
4807 int i, count_generic = 0;
4808 GList *list = NULL, *tmp;
4809 if (generic_array_method_num)
4810 return generic_array_method_num;
4811 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4812 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4813 for (i = 0; i < class->parent->method.count; i++) {
4814 MonoMethod *m = class->parent->methods [i];
4815 if (!strncmp (m->name, "InternalArray__", 15)) {
4817 list = g_list_prepend (list, m);
4820 list = g_list_reverse (list);
4821 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4823 for (tmp = list; tmp; tmp = tmp->next) {
4824 const char *mname, *iname;
4826 MonoMethod *m = tmp->data;
4827 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4828 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4830 generic_array_method_info [i].array_method = m;
4831 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4832 iname = "System.Collections.Generic.ICollection`1.";
4833 mname = m->name + 27;
4834 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4835 iname = "System.Collections.Generic.IEnumerable`1.";
4836 mname = m->name + 27;
4837 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4838 iname = "System.Collections.Generic.IReadOnlyList`1.";
4839 mname = m->name + strlen (ireadonlylist_prefix);
4840 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4841 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4842 mname = m->name + strlen (ireadonlycollection_prefix);
4843 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4844 iname = "System.Collections.Generic.IList`1.";
4845 mname = m->name + 15;
4847 g_assert_not_reached ();
4850 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4851 strcpy (name, iname);
4852 strcpy (name + strlen (iname), mname);
4853 generic_array_method_info [i].name = name;
4856 /*g_print ("array generic methods: %d\n", count_generic);*/
4858 generic_array_method_num = count_generic;
4860 return generic_array_method_num;
4864 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4866 MonoGenericContext tmp_context;
4869 tmp_context.class_inst = NULL;
4870 tmp_context.method_inst = iface->generic_class->context.class_inst;
4871 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4873 for (i = 0; i < generic_array_method_num; i++) {
4874 MonoMethod *m = generic_array_method_info [i].array_method;
4875 MonoMethod *inflated;
4877 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4878 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4883 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4885 int null_length = strlen ("(null)");
4886 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4887 char *s = mono_image_alloc (image, len);
4890 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4891 g_assert (result == len - 1);
4897 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4899 gpointer exception_data = NULL;
4901 switch (error->exception_type) {
4902 case MONO_EXCEPTION_TYPE_LOAD:
4903 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4906 case MONO_EXCEPTION_MISSING_METHOD:
4907 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4910 case MONO_EXCEPTION_MISSING_FIELD: {
4911 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4912 const char *class_name;
4915 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4917 class_name = error->klass->name;
4919 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4922 g_free ((void*)class_name);
4926 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4929 if (error->ref_only)
4930 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.";
4932 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4934 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4938 case MONO_EXCEPTION_BAD_IMAGE:
4939 exception_data = error->msg;
4943 g_assert_not_reached ();
4946 mono_class_set_failure (class, error->exception_type, exception_data);
4951 * @class: the class to initialize
4953 * Compute the instance_size, class_size and other infos that cannot be
4954 * computed at mono_class_get() time. Also compute vtable_size if possible.
4955 * Returns TRUE on success or FALSE if there was a problem in loading
4956 * the type (incorrect assemblies, missing assemblies, methods, etc).
4958 * LOCKING: Acquires the loader lock.
4961 mono_class_init (MonoClass *class)
4964 MonoCachedClassInfo cached_info;
4965 gboolean has_cached_info;
4969 /* Double-checking locking pattern */
4970 if (class->inited || class->exception_type)
4971 return class->exception_type == MONO_EXCEPTION_NONE;
4973 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4975 /* We do everything inside the lock to prevent races */
4976 mono_loader_lock ();
4978 if (class->inited || class->exception_type) {
4979 mono_loader_unlock ();
4980 /* Somebody might have gotten in before us */
4981 return class->exception_type == MONO_EXCEPTION_NONE;
4984 if (class->init_pending) {
4985 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4989 class->init_pending = 1;
4991 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4992 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4997 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4998 MonoClass *element_class = class->element_class;
4999 if (!element_class->inited)
5000 mono_class_init (element_class);
5001 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5002 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5007 /* CAS - SecurityAction.InheritanceDemand */
5008 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5009 mono_secman_inheritancedemand_class (class, class->parent);
5012 mono_stats.initialized_class_count++;
5014 if (class->generic_class && !class->generic_class->is_dynamic) {
5015 MonoClass *gklass = class->generic_class->container_class;
5017 mono_stats.generic_class_count++;
5019 class->method = gklass->method;
5020 class->field = gklass->field;
5022 mono_class_init (gklass);
5023 // FIXME: Why is this needed ?
5024 if (!gklass->exception_type)
5025 mono_class_setup_methods (gklass);
5026 if (gklass->exception_type) {
5027 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5031 if (MONO_CLASS_IS_INTERFACE (class))
5032 class->interface_id = mono_get_unique_iid (class);
5035 if (class->parent && !class->parent->inited)
5036 mono_class_init (class->parent);
5038 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5040 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5041 class->nested_classes_inited = TRUE;
5044 * Computes the size used by the fields, and their locations
5046 if (has_cached_info) {
5047 class->instance_size = cached_info.instance_size;
5048 class->sizes.class_size = cached_info.class_size;
5049 class->packing_size = cached_info.packing_size;
5050 class->min_align = cached_info.min_align;
5051 class->blittable = cached_info.blittable;
5052 class->has_references = cached_info.has_references;
5053 class->has_static_refs = cached_info.has_static_refs;
5054 class->no_special_static_fields = cached_info.no_special_static_fields;
5057 if (!class->size_inited){
5058 mono_class_setup_fields (class);
5059 if (class->exception_type || mono_loader_get_last_error ())
5063 /* Initialize arrays */
5065 class->method.count = 3 + (class->rank > 1? 2: 1);
5067 if (class->interface_count) {
5068 int count_generic = generic_array_methods (class);
5069 class->method.count += class->interface_count * count_generic;
5073 mono_class_setup_supertypes (class);
5076 initialize_object_slots (class);
5079 * Initialize the rest of the data without creating a generic vtable if possible.
5080 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5081 * also avoid computing a generic vtable.
5083 if (has_cached_info) {
5085 class->vtable_size = cached_info.vtable_size;
5086 class->has_finalize = cached_info.has_finalize;
5087 class->has_finalize_inited = TRUE;
5088 class->ghcimpl = cached_info.ghcimpl;
5089 class->has_cctor = cached_info.has_cctor;
5090 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5091 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5092 * The first slot if for array with.
5094 static int szarray_vtable_size[2] = { 0 };
5096 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5099 if (!szarray_vtable_size [slot]) {
5100 mono_class_setup_vtable (class);
5101 szarray_vtable_size [slot] = class->vtable_size;
5103 class->vtable_size = szarray_vtable_size[slot];
5105 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5106 MonoClass *gklass = class->generic_class->container_class;
5108 /* Generic instance case */
5109 class->ghcimpl = gklass->ghcimpl;
5110 class->has_cctor = gklass->has_cctor;
5112 mono_class_setup_vtable (gklass);
5113 if (gklass->exception_type) {
5114 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5118 class->vtable_size = gklass->vtable_size;
5122 /* ghcimpl is not currently used
5124 if (class->parent) {
5125 MonoMethod *cmethod = class->vtable [ghc_slot];
5126 if (cmethod->is_inflated)
5127 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5128 if (cmethod == default_ghc) {
5134 /* C# doesn't allow interfaces to have cctors */
5135 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5136 MonoMethod *cmethod = NULL;
5138 if (class->type_token) {
5139 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5140 /* The find_method function ignores the 'flags' argument */
5141 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5142 class->has_cctor = 1;
5144 mono_class_setup_methods (class);
5145 if (class->exception_type)
5148 for (i = 0; i < class->method.count; ++i) {
5149 MonoMethod *method = class->methods [i];
5150 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5151 (strcmp (".cctor", method->name) == 0)) {
5152 class->has_cctor = 1;
5160 if (class->parent) {
5161 int first_iface_slot;
5162 /* This will compute class->parent->vtable_size for some classes */
5163 mono_class_init (class->parent);
5164 if (class->parent->exception_type) {
5165 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5168 if (mono_loader_get_last_error ())
5170 if (!class->parent->vtable_size) {
5171 /* FIXME: Get rid of this somehow */
5172 mono_class_setup_vtable (class->parent);
5173 if (class->parent->exception_type) {
5174 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5177 if (mono_loader_get_last_error ())
5180 first_iface_slot = class->parent->vtable_size;
5181 if (mono_class_need_stelemref_method (class))
5183 setup_interface_offsets (class, first_iface_slot, TRUE);
5185 setup_interface_offsets (class, 0, TRUE);
5188 if (mono_security_core_clr_enabled ())
5189 mono_security_core_clr_check_inheritance (class);
5191 if (mono_loader_get_last_error ()) {
5192 if (class->exception_type == MONO_EXCEPTION_NONE) {
5193 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5195 mono_loader_clear_error ();
5198 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5199 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5204 /* Because of the double-checking locking pattern */
5205 mono_memory_barrier ();
5207 class->init_pending = 0;
5209 mono_loader_unlock ();
5211 if (mono_debugger_class_init_func)
5212 mono_debugger_class_init_func (class);
5214 return class->exception_type == MONO_EXCEPTION_NONE;
5218 * mono_class_has_finalizer:
5220 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5224 mono_class_has_finalizer (MonoClass *klass)
5226 MonoClass *class = klass;
5227 gboolean has_finalize = FALSE;
5229 if (klass->has_finalize_inited)
5230 return klass->has_finalize;
5232 /* Interfaces and valuetypes are not supposed to have finalizers */
5233 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5234 MonoMethod *cmethod = NULL;
5236 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5237 } else if (class->generic_class) {
5238 MonoClass *gklass = class->generic_class->container_class;
5240 has_finalize = mono_class_has_finalizer (gklass);
5241 } else if (class->parent && class->parent->has_finalize) {
5242 has_finalize = TRUE;
5244 if (class->parent) {
5246 * Can't search in metadata for a method named Finalize, because that
5247 * ignores overrides.
5249 mono_class_setup_vtable (class);
5250 if (class->exception_type || mono_loader_get_last_error ())
5253 cmethod = class->vtable [finalize_slot];
5257 g_assert (class->vtable_size > finalize_slot);
5259 if (class->parent) {
5260 if (cmethod->is_inflated)
5261 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5262 if (cmethod != default_finalize)
5263 has_finalize = TRUE;
5269 mono_image_lock (klass->image);
5271 if (!klass->has_finalize_inited) {
5272 klass->has_finalize = has_finalize ? 1 : 0;
5274 mono_memory_barrier ();
5275 klass->has_finalize_inited = TRUE;
5278 mono_image_unlock (klass->image);
5280 return klass->has_finalize;
5284 mono_is_corlib_image (MonoImage *image)
5286 /* FIXME: allow the dynamic case for our compilers and with full trust */
5287 if (image_is_dynamic (image))
5288 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5290 return image == mono_defaults.corlib;
5294 * LOCKING: this assumes the loader lock is held
5297 mono_class_setup_mono_type (MonoClass *class)
5299 const char *name = class->name;
5300 const char *nspace = class->name_space;
5301 gboolean is_corlib = mono_is_corlib_image (class->image);
5303 class->this_arg.byref = 1;
5304 class->this_arg.data.klass = class;
5305 class->this_arg.type = MONO_TYPE_CLASS;
5306 class->byval_arg.data.klass = class;
5307 class->byval_arg.type = MONO_TYPE_CLASS;
5309 if (is_corlib && !strcmp (nspace, "System")) {
5310 if (!strcmp (name, "ValueType")) {
5312 * do not set the valuetype bit for System.ValueType.
5313 * class->valuetype = 1;
5315 class->blittable = TRUE;
5316 } else if (!strcmp (name, "Enum")) {
5318 * do not set the valuetype bit for System.Enum.
5319 * class->valuetype = 1;
5321 class->valuetype = 0;
5322 class->enumtype = 0;
5323 } else if (!strcmp (name, "Object")) {
5324 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5325 } else if (!strcmp (name, "String")) {
5326 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5327 } else if (!strcmp (name, "TypedReference")) {
5328 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5332 if (class->valuetype) {
5333 int t = MONO_TYPE_VALUETYPE;
5335 if (is_corlib && !strcmp (nspace, "System")) {
5338 if (!strcmp (name, "Boolean")) {
5339 t = MONO_TYPE_BOOLEAN;
5340 } else if (!strcmp(name, "Byte")) {
5342 class->blittable = TRUE;
5346 if (!strcmp (name, "Char")) {
5351 if (!strcmp (name, "Double")) {
5353 class->blittable = TRUE;
5357 if (!strcmp (name, "Int32")) {
5359 class->blittable = TRUE;
5360 } else if (!strcmp(name, "Int16")) {
5362 class->blittable = TRUE;
5363 } else if (!strcmp(name, "Int64")) {
5365 class->blittable = TRUE;
5366 } else if (!strcmp(name, "IntPtr")) {
5368 class->blittable = TRUE;
5372 if (!strcmp (name, "Single")) {
5374 class->blittable = TRUE;
5375 } else if (!strcmp(name, "SByte")) {
5377 class->blittable = TRUE;
5381 if (!strcmp (name, "UInt32")) {
5383 class->blittable = TRUE;
5384 } else if (!strcmp(name, "UInt16")) {
5386 class->blittable = TRUE;
5387 } else if (!strcmp(name, "UInt64")) {
5389 class->blittable = TRUE;
5390 } else if (!strcmp(name, "UIntPtr")) {
5392 class->blittable = TRUE;
5396 if (!strcmp (name, "TypedReference")) {
5397 t = MONO_TYPE_TYPEDBYREF;
5398 class->blittable = TRUE;
5402 if (!strcmp (name, "Void")) {
5410 class->this_arg.type = class->byval_arg.type = t;
5413 if (MONO_CLASS_IS_INTERFACE (class))
5414 class->interface_id = mono_get_unique_iid (class);
5420 * COM initialization is delayed until needed.
5421 * However when a [ComImport] attribute is present on a type it will trigger
5422 * the initialization. This is not a problem unless the BCL being executed
5423 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5426 init_com_from_comimport (MonoClass *class)
5428 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5429 if (mono_security_core_clr_enabled ()) {
5430 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5431 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5432 /* but it can not be made available for application (i.e. user code) since all COM calls
5433 * are considered native calls. In this case we fail with a TypeLoadException (just like
5434 * Silverlight 2 does */
5435 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5440 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5442 #endif /*DISABLE_COM*/
5445 * LOCKING: this assumes the loader lock is held
5448 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5450 gboolean system_namespace;
5451 gboolean is_corlib = mono_is_corlib_image (class->image);
5453 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5455 /* if root of the hierarchy */
5456 if (system_namespace && !strcmp (class->name, "Object")) {
5457 class->parent = NULL;
5458 class->instance_size = sizeof (MonoObject);
5461 if (!strcmp (class->name, "<Module>")) {
5462 class->parent = NULL;
5463 class->instance_size = 0;
5467 if (!MONO_CLASS_IS_INTERFACE (class)) {
5468 /* Imported COM Objects always derive from __ComObject. */
5470 if (MONO_CLASS_IS_IMPORT (class)) {
5471 init_com_from_comimport (class);
5472 if (parent == mono_defaults.object_class)
5473 parent = mono_class_get_com_object_class ();
5477 /* set the parent to something useful and safe, but mark the type as broken */
5478 parent = mono_defaults.object_class;
5479 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5482 class->parent = parent;
5484 if (parent->generic_class && !parent->name) {
5486 * If the parent is a generic instance, we may get
5487 * called before it is fully initialized, especially
5488 * before it has its name.
5493 #ifndef DISABLE_REMOTING
5494 class->marshalbyref = parent->marshalbyref;
5495 class->contextbound = parent->contextbound;
5498 class->delegate = parent->delegate;
5500 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5501 mono_class_set_is_com_object (class);
5503 if (system_namespace) {
5504 #ifndef DISABLE_REMOTING
5505 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5506 class->marshalbyref = 1;
5508 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5509 class->contextbound = 1;
5511 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5512 class->delegate = 1;
5515 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5516 (strcmp (class->parent->name_space, "System") == 0)))
5517 class->valuetype = 1;
5518 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5519 class->valuetype = class->enumtype = 1;
5521 /*class->enumtype = class->parent->enumtype; */
5523 /* initialize com types if COM interfaces are present */
5525 if (MONO_CLASS_IS_IMPORT (class))
5526 init_com_from_comimport (class);
5528 class->parent = NULL;
5534 * mono_class_setup_supertypes:
5537 * Build the data structure needed to make fast type checks work.
5538 * This currently sets two fields in @class:
5539 * - idepth: distance between @class and System.Object in the type
5541 * - supertypes: array of classes: each element has a class in the hierarchy
5542 * starting from @class up to System.Object
5544 * LOCKING: This function is atomic, in case of contention we waste memory.
5547 mono_class_setup_supertypes (MonoClass *class)
5550 MonoClass **supertypes;
5552 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5556 if (class->parent && !class->parent->supertypes)
5557 mono_class_setup_supertypes (class->parent);
5559 class->idepth = class->parent->idepth + 1;
5563 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5564 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5566 if (class->parent) {
5567 supertypes [class->idepth - 1] = class;
5568 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5570 supertypes [0] = class;
5573 mono_atomic_store_release (&class->supertypes, supertypes);
5577 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5579 MonoClass *gtd = (MonoClass*)user_data;
5580 /* Only try to fix generic instances of @gtd */
5581 if (gclass->generic_class->container_class != gtd)
5584 /* Check if the generic instance has no parent. */
5585 if (gtd->parent && !gclass->parent)
5586 mono_generic_class_setup_parent (gclass, gtd);
5592 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5594 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5595 mono_error_set_type_load_class (error, class, msg);
5599 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5601 MonoLoaderError *lerror = mono_loader_get_last_error ();
5604 set_failure_from_loader_error (class, lerror);
5605 mono_error_set_from_loader_error (error);
5609 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5610 mono_error_set_type_load_class (error, class, msg);
5615 * mono_class_create_from_typedef:
5616 * @image: image where the token is valid
5617 * @type_token: typedef token
5618 * @error: used to return any error found while creating the type
5620 * Create the MonoClass* representing the specified type token.
5621 * @type_token must be a TypeDef token.
5623 * FIXME: don't return NULL on failure, just the the caller figure it out.
5626 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5628 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5629 MonoClass *class, *parent = NULL;
5630 guint32 cols [MONO_TYPEDEF_SIZE];
5631 guint32 cols_next [MONO_TYPEDEF_SIZE];
5632 guint tidx = mono_metadata_token_index (type_token);
5633 MonoGenericContext *context = NULL;
5634 const char *name, *nspace;
5636 MonoClass **interfaces;
5637 guint32 field_last, method_last;
5638 guint32 nesting_tokeen;
5640 mono_error_init (error);
5642 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5643 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5644 g_assert (!mono_loader_get_last_error ());
5648 mono_loader_lock ();
5650 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5651 mono_loader_unlock ();
5652 g_assert (!mono_loader_get_last_error ());
5656 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5658 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5659 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5661 class = mono_image_alloc0 (image, sizeof (MonoClass));
5664 class->name_space = nspace;
5666 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5668 class->image = image;
5669 class->type_token = type_token;
5670 class->flags = cols [MONO_TYPEDEF_FLAGS];
5672 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5674 classes_size += sizeof (MonoClass);
5677 * Check whether we're a generic type definition.
5679 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5680 if (class->generic_container) {
5681 class->is_generic = 1;
5682 class->generic_container->owner.klass = class;
5683 context = &class->generic_container->context;
5686 if (class->generic_container)
5687 enable_gclass_recording ();
5689 if (cols [MONO_TYPEDEF_EXTENDS]) {
5691 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5693 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5694 /*WARNING: this must satisfy mono_metadata_type_hash*/
5695 class->this_arg.byref = 1;
5696 class->this_arg.data.klass = class;
5697 class->this_arg.type = MONO_TYPE_CLASS;
5698 class->byval_arg.data.klass = class;
5699 class->byval_arg.type = MONO_TYPE_CLASS;
5701 parent = mono_class_get_checked (image, parent_token, error);
5702 if (parent && context) /* Always inflate */
5703 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5705 if (parent == NULL) {
5706 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5707 goto parent_failure;
5710 for (tmp = parent; tmp; tmp = tmp->parent) {
5712 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5713 goto parent_failure;
5715 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5716 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5717 goto parent_failure;
5722 mono_class_setup_parent (class, parent);
5724 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5725 mono_class_setup_mono_type (class);
5727 if (class->generic_container)
5728 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5731 * This might access class->byval_arg for recursion generated by generic constraints,
5732 * so it has to come after setup_mono_type ().
5734 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5735 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5736 if (!mono_error_ok (error)) {
5737 /*FIXME implement a mono_class_set_failure_from_mono_error */
5738 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5739 mono_loader_unlock ();
5740 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5741 g_assert (!mono_loader_get_last_error ());
5746 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5750 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5754 class->cast_class = class->element_class = class;
5756 if (!class->enumtype) {
5757 if (!mono_metadata_interfaces_from_typedef_full (
5758 image, type_token, &interfaces, &icount, FALSE, context)){
5759 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5760 mono_loader_unlock ();
5761 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5765 class->interfaces = interfaces;
5766 class->interface_count = icount;
5767 class->interfaces_inited = 1;
5770 /*g_print ("Load class %s\n", name);*/
5773 * Compute the field and method lists
5775 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5776 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5778 if (tt->rows > tidx){
5779 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5780 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5781 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5783 field_last = image->tables [MONO_TABLE_FIELD].rows;
5784 method_last = image->tables [MONO_TABLE_METHOD].rows;
5787 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5788 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5789 class->field.count = field_last - class->field.first;
5791 class->field.count = 0;
5793 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5794 class->method.count = method_last - class->method.first;
5796 class->method.count = 0;
5798 /* reserve space to store vector pointer in arrays */
5799 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5800 class->instance_size += 2 * sizeof (gpointer);
5801 g_assert (class->field.count == 0);
5804 if (class->enumtype) {
5805 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5806 if (!enum_basetype) {
5807 /*set it to a default value as the whole runtime can't handle this to be null*/
5808 class->cast_class = class->element_class = mono_defaults.int32_class;
5809 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5810 mono_loader_unlock ();
5811 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5812 g_assert (!mono_loader_get_last_error ());
5815 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5819 * If we're a generic type definition, load the constraints.
5820 * We must do this after the class has been constructed to make certain recursive scenarios
5823 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5824 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5825 mono_loader_unlock ();
5826 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5827 g_assert (!mono_loader_get_last_error ());
5831 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5832 if (!strncmp (name, "Vector", 6))
5833 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");
5836 mono_loader_unlock ();
5838 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5839 g_assert (!mono_loader_get_last_error ());
5844 mono_class_setup_mono_type (class);
5845 mono_loader_unlock ();
5846 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5847 g_assert (!mono_loader_get_last_error ());
5851 /** is klass Nullable<T>? */
5853 mono_class_is_nullable (MonoClass *klass)
5855 return klass->generic_class != NULL &&
5856 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5860 /** if klass is T? return T */
5862 mono_class_get_nullable_param (MonoClass *klass)
5864 g_assert (mono_class_is_nullable (klass));
5865 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5869 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5873 MonoGenericClass *gclass = klass->generic_class;
5875 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5876 if (!mono_error_ok (&error)) {
5877 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5878 klass->parent = mono_defaults.object_class;
5879 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5880 mono_error_cleanup (&error);
5884 mono_class_setup_parent (klass, klass->parent);
5886 if (klass->enumtype) {
5887 klass->cast_class = gtd->cast_class;
5888 klass->element_class = gtd->element_class;
5894 * Create the `MonoClass' for an instantiation of a generic type.
5895 * We only do this if we actually need it.
5898 mono_generic_class_get_class (MonoGenericClass *gclass)
5900 MonoClass *klass, *gklass;
5902 if (gclass->cached_class)
5903 return gclass->cached_class;
5905 mono_loader_lock ();
5906 if (gclass->cached_class) {
5907 mono_loader_unlock ();
5908 return gclass->cached_class;
5911 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5913 gklass = gclass->container_class;
5915 if (record_gclass_instantiation > 0)
5916 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5918 if (gklass->nested_in) {
5919 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5920 klass->nested_in = gklass->nested_in;
5923 klass->name = gklass->name;
5924 klass->name_space = gklass->name_space;
5926 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5928 klass->image = gklass->image;
5929 klass->flags = gklass->flags;
5930 klass->type_token = gklass->type_token;
5931 klass->field.count = gklass->field.count;
5933 klass->is_inflated = 1;
5934 klass->generic_class = gclass;
5936 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5937 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5938 klass->this_arg.byref = TRUE;
5939 klass->enumtype = gklass->enumtype;
5940 klass->valuetype = gklass->valuetype;
5942 klass->cast_class = klass->element_class = klass;
5944 if (mono_class_is_nullable (klass))
5945 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5948 * We're not interested in the nested classes of a generic instance.
5949 * We use the generic type definition to look for nested classes.
5952 mono_generic_class_setup_parent (klass, gklass);
5954 if (gclass->is_dynamic) {
5957 mono_class_setup_supertypes (klass);
5959 if (klass->enumtype) {
5961 * For enums, gklass->fields might not been set, but instance_size etc. is
5962 * already set in mono_reflection_create_internal_class (). For non-enums,
5963 * these will be computed normally in mono_class_layout_fields ().
5965 klass->instance_size = gklass->instance_size;
5966 klass->sizes.class_size = gklass->sizes.class_size;
5967 mono_memory_barrier ();
5968 klass->size_inited = 1;
5972 mono_memory_barrier ();
5973 gclass->cached_class = klass;
5975 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5977 inflated_classes ++;
5978 inflated_classes_size += sizeof (MonoClass);
5980 mono_loader_unlock ();
5986 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5988 MonoClass *klass, **ptr;
5990 MonoGenericContainer *container = mono_generic_param_owner (param);
5994 image = mono_defaults.corlib;
5996 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5997 classes_size += sizeof (MonoClass);
6000 klass->name = pinfo->name;
6002 int n = mono_generic_param_num (param);
6003 klass->name = mono_image_alloc0 (image, 16);
6004 sprintf ((char*)klass->name, "%d", n);
6009 MonoMethod *omethod = container->owner.method;
6010 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6012 MonoClass *oklass = container->owner.klass;
6013 klass->name_space = oklass ? oklass->name_space : "";
6016 klass->name_space = "";
6019 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6023 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6027 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6028 klass->parent = pinfo->constraints [0];
6030 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6031 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6033 klass->parent = mono_defaults.object_class;
6036 if (count - pos > 0) {
6037 klass->interface_count = count - pos;
6038 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6039 klass->interfaces_inited = TRUE;
6040 for (i = pos; i < count; i++)
6041 klass->interfaces [i - pos] = pinfo->constraints [i];
6044 klass->image = image;
6046 klass->inited = TRUE;
6047 klass->cast_class = klass->element_class = klass;
6048 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6050 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6051 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6052 klass->this_arg.byref = TRUE;
6054 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6055 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6057 /*Init these fields to sane values*/
6058 klass->min_align = 1;
6059 klass->instance_size = sizeof (gpointer);
6060 mono_memory_barrier ();
6061 klass->size_inited = 1;
6063 mono_class_setup_supertypes (klass);
6065 if (count - pos > 0) {
6066 mono_class_setup_vtable (klass->parent);
6067 if (klass->parent->exception_type)
6068 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6070 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6076 #define FAST_CACHE_SIZE 16
6079 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6081 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6082 MonoImage *image = param->image;
6087 if (n < FAST_CACHE_SIZE) {
6089 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6091 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6093 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6094 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6099 * LOCKING: Acquires the loader lock.
6102 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6104 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6105 MonoImage *image = param->image;
6110 if (n < FAST_CACHE_SIZE) {
6112 /* No locking needed */
6113 if (!image->mvar_cache_fast)
6114 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6115 image->mvar_cache_fast [n] = klass;
6117 if (!image->var_cache_fast)
6118 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6119 image->var_cache_fast [n] = klass;
6123 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6125 mono_image_lock (image);
6126 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6128 ht = g_hash_table_new (NULL, NULL);
6129 mono_memory_barrier ();
6131 image->mvar_cache_slow = ht;
6133 image->var_cache_slow = ht;
6135 mono_image_unlock (image);
6138 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6142 * LOCKING: Acquires the loader lock.
6145 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6147 MonoGenericContainer *container = mono_generic_param_owner (param);
6148 MonoGenericParamInfo *pinfo;
6151 mono_loader_lock ();
6154 pinfo = mono_generic_param_info (param);
6155 if (pinfo->pklass) {
6156 mono_loader_unlock ();
6157 return pinfo->pklass;
6163 klass = get_anon_gparam_class (param, is_mvar);
6165 mono_loader_unlock ();
6170 if (!image && container) {
6172 MonoMethod *method = container->owner.method;
6173 image = (method && method->klass) ? method->klass->image : NULL;
6175 MonoClass *klass = container->owner.klass;
6176 // FIXME: 'klass' should not be null
6177 // But, monodis creates GenericContainers without associating a owner to it
6178 image = klass ? klass->image : NULL;
6182 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6184 mono_memory_barrier ();
6187 pinfo->pklass = klass;
6189 set_anon_gparam_class (param, is_mvar, klass);
6191 mono_loader_unlock ();
6193 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6194 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6200 mono_ptr_class_get (MonoType *type)
6203 MonoClass *el_class;
6207 el_class = mono_class_from_mono_type (type);
6208 image = el_class->image;
6210 mono_loader_lock ();
6212 if (!image->ptr_cache)
6213 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6215 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6216 mono_loader_unlock ();
6219 result = mono_image_alloc0 (image, sizeof (MonoClass));
6221 classes_size += sizeof (MonoClass);
6223 result->parent = NULL; /* no parent for PTR types */
6224 result->name_space = el_class->name_space;
6225 name = g_strdup_printf ("%s*", el_class->name);
6226 result->name = mono_image_strdup (image, name);
6229 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6231 result->image = el_class->image;
6232 result->inited = TRUE;
6233 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6234 /* Can pointers get boxed? */
6235 result->instance_size = sizeof (gpointer);
6236 result->cast_class = result->element_class = el_class;
6237 result->blittable = TRUE;
6239 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6240 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6241 result->this_arg.byref = TRUE;
6243 mono_class_setup_supertypes (result);
6245 g_hash_table_insert (image->ptr_cache, el_class, result);
6247 mono_loader_unlock ();
6249 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6255 mono_fnptr_class_get (MonoMethodSignature *sig)
6258 static GHashTable *ptr_hash = NULL;
6260 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6262 mono_loader_lock ();
6265 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6267 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6268 mono_loader_unlock ();
6271 result = g_new0 (MonoClass, 1);
6273 result->parent = NULL; /* no parent for PTR types */
6274 result->name_space = "System";
6275 result->name = "MonoFNPtrFakeClass";
6277 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6279 result->image = mono_defaults.corlib; /* need to fix... */
6280 result->inited = TRUE;
6281 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6282 /* Can pointers get boxed? */
6283 result->instance_size = sizeof (gpointer);
6284 result->cast_class = result->element_class = result;
6285 result->blittable = TRUE;
6287 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6288 result->this_arg.data.method = result->byval_arg.data.method = sig;
6289 result->this_arg.byref = TRUE;
6290 result->blittable = TRUE;
6292 mono_class_setup_supertypes (result);
6294 g_hash_table_insert (ptr_hash, sig, result);
6296 mono_loader_unlock ();
6298 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6304 mono_class_from_mono_type (MonoType *type)
6306 switch (type->type) {
6307 case MONO_TYPE_OBJECT:
6308 return type->data.klass? type->data.klass: mono_defaults.object_class;
6309 case MONO_TYPE_VOID:
6310 return type->data.klass? type->data.klass: mono_defaults.void_class;
6311 case MONO_TYPE_BOOLEAN:
6312 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6313 case MONO_TYPE_CHAR:
6314 return type->data.klass? type->data.klass: mono_defaults.char_class;
6316 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6318 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6320 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6322 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6324 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6326 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6328 return type->data.klass? type->data.klass: mono_defaults.int_class;
6330 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6332 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6334 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6336 return type->data.klass? type->data.klass: mono_defaults.single_class;
6338 return type->data.klass? type->data.klass: mono_defaults.double_class;
6339 case MONO_TYPE_STRING:
6340 return type->data.klass? type->data.klass: mono_defaults.string_class;
6341 case MONO_TYPE_TYPEDBYREF:
6342 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6343 case MONO_TYPE_ARRAY:
6344 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6346 return mono_ptr_class_get (type->data.type);
6347 case MONO_TYPE_FNPTR:
6348 return mono_fnptr_class_get (type->data.method);
6349 case MONO_TYPE_SZARRAY:
6350 return mono_array_class_get (type->data.klass, 1);
6351 case MONO_TYPE_CLASS:
6352 case MONO_TYPE_VALUETYPE:
6353 return type->data.klass;
6354 case MONO_TYPE_GENERICINST:
6355 return mono_generic_class_get_class (type->data.generic_class);
6357 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6358 case MONO_TYPE_MVAR:
6359 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6361 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6362 g_assert_not_reached ();
6369 * mono_type_retrieve_from_typespec
6370 * @image: context where the image is created
6371 * @type_spec: typespec token
6372 * @context: the generic context used to evaluate generic instantiations in
6375 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6377 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6379 *did_inflate = FALSE;
6384 if (context && (context->class_inst || context->method_inst)) {
6385 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6387 if (!mono_error_ok (error)) {
6388 g_assert (!mono_loader_get_last_error ());
6394 *did_inflate = TRUE;
6401 * mono_class_create_from_typespec
6402 * @image: context where the image is created
6403 * @type_spec: typespec token
6404 * @context: the generic context used to evaluate generic instantiations in
6407 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6410 gboolean inflated = FALSE;
6411 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6412 if (!mono_error_ok (error))
6414 ret = mono_class_from_mono_type (t);
6416 mono_metadata_free_type (t);
6421 * mono_bounded_array_class_get:
6422 * @element_class: element class
6423 * @rank: the dimension of the array class
6424 * @bounded: whenever the array has non-zero bounds
6426 * Returns: a class object describing the array with element type @element_type and
6430 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6434 MonoClass *parent = NULL;
6435 GSList *list, *rootlist = NULL;
6438 gboolean corlib_type = FALSE;
6440 g_assert (rank <= 255);
6443 /* bounded only matters for one-dimensional arrays */
6446 image = eclass->image;
6448 if (rank == 1 && !bounded) {
6450 * This case is very frequent not just during compilation because of calls
6451 * from mono_class_from_mono_type (), mono_array_new (),
6452 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6454 mono_mutex_lock (&image->szarray_cache_lock);
6455 if (!image->szarray_cache)
6456 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6457 class = g_hash_table_lookup (image->szarray_cache, eclass);
6458 mono_mutex_unlock (&image->szarray_cache_lock);
6462 mono_loader_lock ();
6464 mono_loader_lock ();
6466 if (!image->array_cache)
6467 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6469 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6470 for (; list; list = list->next) {
6472 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6473 mono_loader_unlock ();
6480 /* for the building corlib use System.Array from it */
6481 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6482 parent = mono_class_from_name (image, "System", "Array");
6485 parent = mono_defaults.array_class;
6486 if (!parent->inited)
6487 mono_class_init (parent);
6490 class = mono_image_alloc0 (image, sizeof (MonoClass));
6492 class->image = image;
6493 class->name_space = eclass->name_space;
6494 nsize = strlen (eclass->name);
6495 name = g_malloc (nsize + 2 + rank + 1);
6496 memcpy (name, eclass->name, nsize);
6499 memset (name + nsize + 1, ',', rank - 1);
6501 name [nsize + rank] = '*';
6502 name [nsize + rank + bounded] = ']';
6503 name [nsize + rank + bounded + 1] = 0;
6504 class->name = mono_image_strdup (image, name);
6507 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6509 classes_size += sizeof (MonoClass);
6511 class->type_token = 0;
6512 /* all arrays are marked serializable and sealed, bug #42779 */
6513 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6514 class->parent = parent;
6515 class->instance_size = mono_class_instance_size (class->parent);
6517 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6518 /*Arrays of those two types are invalid.*/
6519 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6520 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6521 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6522 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6523 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6525 /* element_size -1 is ok as this is not an instantitable type*/
6526 class->sizes.element_size = -1;
6528 class->sizes.element_size = mono_class_array_element_size (eclass);
6530 mono_class_setup_supertypes (class);
6532 if (eclass->generic_class)
6533 mono_class_init (eclass);
6534 if (!eclass->size_inited)
6535 mono_class_setup_fields (eclass);
6536 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6537 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6539 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6543 if (eclass->enumtype)
6544 class->cast_class = eclass->element_class;
6546 class->cast_class = eclass;
6548 switch (class->cast_class->byval_arg.type) {
6550 class->cast_class = mono_defaults.byte_class;
6553 class->cast_class = mono_defaults.int16_class;
6556 #if SIZEOF_VOID_P == 4
6560 class->cast_class = mono_defaults.int32_class;
6563 #if SIZEOF_VOID_P == 8
6567 class->cast_class = mono_defaults.int64_class;
6571 class->element_class = eclass;
6573 if ((rank > 1) || bounded) {
6574 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6575 class->byval_arg.type = MONO_TYPE_ARRAY;
6576 class->byval_arg.data.array = at;
6577 at->eklass = eclass;
6579 /* FIXME: complete.... */
6581 class->byval_arg.type = MONO_TYPE_SZARRAY;
6582 class->byval_arg.data.klass = eclass;
6584 class->this_arg = class->byval_arg;
6585 class->this_arg.byref = 1;
6590 class->generic_container = eclass->generic_container;
6592 if (rank == 1 && !bounded) {
6593 MonoClass *prev_class;
6595 mono_mutex_lock (&image->szarray_cache_lock);
6596 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6598 /* Someone got in before us */
6601 g_hash_table_insert (image->szarray_cache, eclass, class);
6602 mono_mutex_unlock (&image->szarray_cache_lock);
6604 list = g_slist_append (rootlist, class);
6605 g_hash_table_insert (image->array_cache, eclass, list);
6608 mono_loader_unlock ();
6610 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6616 * mono_array_class_get:
6617 * @element_class: element class
6618 * @rank: the dimension of the array class
6620 * Returns: a class object describing the array with element type @element_type and
6624 mono_array_class_get (MonoClass *eclass, guint32 rank)
6626 return mono_bounded_array_class_get (eclass, rank, FALSE);
6630 * mono_class_instance_size:
6633 * Returns: the size of an object instance
6636 mono_class_instance_size (MonoClass *klass)
6638 if (!klass->size_inited)
6639 mono_class_init (klass);
6641 return klass->instance_size;
6645 * mono_class_min_align:
6648 * Returns: minimm alignment requirements
6651 mono_class_min_align (MonoClass *klass)
6653 if (!klass->size_inited)
6654 mono_class_init (klass);
6656 return klass->min_align;
6660 * mono_class_value_size:
6663 * This function is used for value types, and return the
6664 * space and the alignment to store that kind of value object.
6666 * Returns: the size of a value of kind @klass
6669 mono_class_value_size (MonoClass *klass, guint32 *align)
6673 /* fixme: check disable, because we still have external revereces to
6674 * mscorlib and Dummy Objects
6676 /*g_assert (klass->valuetype);*/
6678 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6681 *align = klass->min_align;
6687 * mono_class_data_size:
6690 * Returns: the size of the static class data
6693 mono_class_data_size (MonoClass *klass)
6696 mono_class_init (klass);
6697 /* This can happen with dynamically created types */
6698 if (!klass->fields_inited)
6699 mono_class_setup_fields_locking (klass);
6701 /* in arrays, sizes.class_size is unioned with element_size
6702 * and arrays have no static fields
6706 return klass->sizes.class_size;
6710 * Auxiliary routine to mono_class_get_field
6712 * Takes a field index instead of a field token.
6714 static MonoClassField *
6715 mono_class_get_field_idx (MonoClass *class, int idx)
6717 mono_class_setup_fields_locking (class);
6718 if (class->exception_type)
6722 if (class->image->uncompressed_metadata) {
6724 * class->field.first points to the FieldPtr table, while idx points into the
6725 * Field table, so we have to do a search.
6727 /*FIXME this is broken for types with multiple fields with the same name.*/
6728 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6731 for (i = 0; i < class->field.count; ++i)
6732 if (mono_field_get_name (&class->fields [i]) == name)
6733 return &class->fields [i];
6734 g_assert_not_reached ();
6736 if (class->field.count) {
6737 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6738 return &class->fields [idx - class->field.first];
6742 class = class->parent;
6748 * mono_class_get_field:
6749 * @class: the class to lookup the field.
6750 * @field_token: the field token
6752 * Returns: A MonoClassField representing the type and offset of
6753 * the field, or a NULL value if the field does not belong to this
6757 mono_class_get_field (MonoClass *class, guint32 field_token)
6759 int idx = mono_metadata_token_index (field_token);
6761 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6763 return mono_class_get_field_idx (class, idx - 1);
6767 * mono_class_get_field_from_name:
6768 * @klass: the class to lookup the field.
6769 * @name: the field name
6771 * Search the class @klass and it's parents for a field with the name @name.
6773 * Returns: the MonoClassField pointer of the named field or NULL
6776 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6778 return mono_class_get_field_from_name_full (klass, name, NULL);
6782 * mono_class_get_field_from_name_full:
6783 * @klass: the class to lookup the field.
6784 * @name: the field name
6785 * @type: the type of the fields. This optional.
6787 * Search the class @klass and it's parents for a field with the name @name and type @type.
6789 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6790 * of its generic type definition.
6792 * Returns: the MonoClassField pointer of the named field or NULL
6795 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6799 mono_class_setup_fields_locking (klass);
6800 if (klass->exception_type)
6804 for (i = 0; i < klass->field.count; ++i) {
6805 MonoClassField *field = &klass->fields [i];
6807 if (strcmp (name, mono_field_get_name (field)) != 0)
6811 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6812 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6817 klass = klass->parent;
6823 * mono_class_get_field_token:
6824 * @field: the field we need the token of
6826 * Get the token of a field. Note that the tokesn is only valid for the image
6827 * the field was loaded from. Don't use this function for fields in dynamic types.
6829 * Returns: the token representing the field in the image it was loaded from.
6832 mono_class_get_field_token (MonoClassField *field)
6834 MonoClass *klass = field->parent;
6837 mono_class_setup_fields_locking (klass);
6842 for (i = 0; i < klass->field.count; ++i) {
6843 if (&klass->fields [i] == field) {
6844 int idx = klass->field.first + i + 1;
6846 if (klass->image->uncompressed_metadata)
6847 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6848 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6851 klass = klass->parent;
6854 g_assert_not_reached ();
6859 mono_field_get_index (MonoClassField *field)
6861 int index = field - field->parent->fields;
6863 g_assert (index >= 0 && index < field->parent->field.count);
6869 * mono_class_get_field_default_value:
6871 * Return the default value of the field as a pointer into the metadata blob.
6874 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6877 guint32 constant_cols [MONO_CONSTANT_SIZE];
6879 MonoClass *klass = field->parent;
6881 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6883 if (!klass->ext || !klass->ext->field_def_values) {
6884 MonoFieldDefaultValue *def_values;
6886 mono_class_alloc_ext (klass);
6888 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6890 mono_image_lock (klass->image);
6891 mono_memory_barrier ();
6892 if (!klass->ext->field_def_values)
6893 klass->ext->field_def_values = def_values;
6894 mono_image_unlock (klass->image);
6897 field_index = mono_field_get_index (field);
6899 if (!klass->ext->field_def_values [field_index].data) {
6900 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6904 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6906 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6907 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6908 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6911 *def_type = klass->ext->field_def_values [field_index].def_type;
6912 return klass->ext->field_def_values [field_index].data;
6916 mono_property_get_index (MonoProperty *prop)
6918 int index = prop - prop->parent->ext->properties;
6920 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6926 * mono_class_get_property_default_value:
6928 * Return the default value of the field as a pointer into the metadata blob.
6931 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6934 guint32 constant_cols [MONO_CONSTANT_SIZE];
6935 MonoClass *klass = property->parent;
6937 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6939 * We don't cache here because it is not used by C# so it's quite rare, but
6940 * we still do the lookup in klass->ext because that is where the data
6941 * is stored for dynamic assemblies.
6944 if (image_is_dynamic (klass->image)) {
6945 int prop_index = mono_property_get_index (property);
6946 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6947 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6948 return klass->ext->prop_def_values [prop_index].data;
6952 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6956 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6957 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6958 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6962 mono_class_get_event_token (MonoEvent *event)
6964 MonoClass *klass = event->parent;
6969 for (i = 0; i < klass->ext->event.count; ++i) {
6970 if (&klass->ext->events [i] == event)
6971 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6974 klass = klass->parent;
6977 g_assert_not_reached ();
6982 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6986 gpointer iter = NULL;
6987 while ((p = mono_class_get_properties (klass, &iter))) {
6988 if (! strcmp (name, p->name))
6991 klass = klass->parent;
6997 mono_class_get_property_token (MonoProperty *prop)
6999 MonoClass *klass = prop->parent;
7003 gpointer iter = NULL;
7004 while ((p = mono_class_get_properties (klass, &iter))) {
7005 if (&klass->ext->properties [i] == prop)
7006 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7010 klass = klass->parent;
7013 g_assert_not_reached ();
7018 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7020 const char *name, *nspace;
7021 if (image_is_dynamic (image))
7022 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7024 switch (type_token & 0xff000000){
7025 case MONO_TOKEN_TYPE_DEF: {
7026 guint32 cols [MONO_TYPEDEF_SIZE];
7027 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7028 guint tidx = mono_metadata_token_index (type_token);
7030 if (tidx > tt->rows)
7031 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7033 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7034 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7035 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7036 if (strlen (nspace) == 0)
7037 return g_strdup_printf ("%s", name);
7039 return g_strdup_printf ("%s.%s", nspace, name);
7042 case MONO_TOKEN_TYPE_REF: {
7044 guint32 cols [MONO_TYPEREF_SIZE];
7045 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7046 guint tidx = mono_metadata_token_index (type_token);
7049 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7051 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7052 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7053 mono_error_cleanup (&error);
7057 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7058 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7059 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7060 if (strlen (nspace) == 0)
7061 return g_strdup_printf ("%s", name);
7063 return g_strdup_printf ("%s.%s", nspace, name);
7066 case MONO_TOKEN_TYPE_SPEC:
7067 return g_strdup_printf ("Typespec 0x%08x", type_token);
7069 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7074 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7076 if (image_is_dynamic (image))
7077 return g_strdup_printf ("DynamicAssembly %s", image->name);
7079 switch (type_token & 0xff000000){
7080 case MONO_TOKEN_TYPE_DEF:
7081 if (image->assembly)
7082 return mono_stringify_assembly_name (&image->assembly->aname);
7083 else if (image->assembly_name)
7084 return g_strdup (image->assembly_name);
7085 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7086 case MONO_TOKEN_TYPE_REF: {
7088 MonoAssemblyName aname;
7089 guint32 cols [MONO_TYPEREF_SIZE];
7090 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7091 guint32 idx = mono_metadata_token_index (type_token);
7094 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7096 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7097 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7098 mono_error_cleanup (&error);
7101 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7103 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7104 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7105 case MONO_RESOLTION_SCOPE_MODULE:
7107 return g_strdup ("");
7108 case MONO_RESOLTION_SCOPE_MODULEREF:
7110 return g_strdup ("");
7111 case MONO_RESOLTION_SCOPE_TYPEREF:
7113 return g_strdup ("");
7114 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7115 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7116 return mono_stringify_assembly_name (&aname);
7118 g_assert_not_reached ();
7122 case MONO_TOKEN_TYPE_SPEC:
7124 return g_strdup ("");
7126 g_assert_not_reached ();
7133 * mono_class_get_full:
7134 * @image: the image where the class resides
7135 * @type_token: the token for the class
7136 * @context: the generic context used to evaluate generic instantiations in
7137 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7139 * Returns: the MonoClass that represents @type_token in @image
7142 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7146 class = mono_class_get_checked (image, type_token, &error);
7148 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7149 class = mono_class_inflate_generic_class_checked (class, context, &error);
7152 mono_loader_set_error_from_mono_error (&error);
7153 mono_error_cleanup (&error); /*FIXME don't swallow this error */
7160 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7164 mono_error_init (error);
7165 class = mono_class_get_checked (image, type_token, error);
7167 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7168 class = mono_class_inflate_generic_class_checked (class, context, error);
7173 * mono_class_get_checked:
7174 * @image: the image where the class resides
7175 * @type_token: the token for the class
7176 * @error: error object to return any error
7178 * Returns: the MonoClass that represents @type_token in @image
7181 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7183 MonoClass *class = NULL;
7185 mono_error_init (error);
7187 if (image_is_dynamic (image)) {
7188 int table = mono_metadata_token_table (type_token);
7190 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7191 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7194 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7198 switch (type_token & 0xff000000){
7199 case MONO_TOKEN_TYPE_DEF:
7200 class = mono_class_create_from_typedef (image, type_token, error);
7202 case MONO_TOKEN_TYPE_REF:
7203 class = mono_class_from_typeref_checked (image, type_token, error);
7205 case MONO_TOKEN_TYPE_SPEC:
7206 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7209 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7213 /* Generic case, should be avoided for when a better error is possible. */
7214 if (!class && mono_error_ok (error)) {
7215 char *name = mono_class_name_from_token (image, type_token);
7216 char *assembly = mono_assembly_name_from_token (image, type_token);
7217 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7225 * mono_type_get_checked:
7226 * @image: the image where the type resides
7227 * @type_token: the token for the type
7228 * @context: the generic context used to evaluate generic instantiations in
7229 * @error: Error handling context
7231 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7233 * Returns: the MonoType that represents @type_token in @image
7236 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7238 MonoType *type = NULL;
7239 gboolean inflated = FALSE;
7241 mono_error_init (error);
7243 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7244 if (image_is_dynamic (image))
7245 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7247 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7248 MonoClass *class = mono_class_get_checked (image, type_token, error);
7251 g_assert (!mono_loader_get_last_error ());
7256 return mono_class_get_type (class);
7259 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7262 g_assert (!mono_loader_get_last_error ());
7267 MonoType *tmp = type;
7268 type = mono_class_get_type (mono_class_from_mono_type (type));
7269 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7270 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7271 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7273 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7275 if (type->type != tmp->type)
7278 mono_metadata_free_type (tmp);
7285 mono_class_get (MonoImage *image, guint32 type_token)
7287 return mono_class_get_full (image, type_token, NULL);
7291 * mono_image_init_name_cache:
7293 * Initializes the class name cache stored in image->name_cache.
7295 * LOCKING: Acquires the corresponding image lock.
7298 mono_image_init_name_cache (MonoImage *image)
7300 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7301 guint32 cols [MONO_TYPEDEF_SIZE];
7304 guint32 i, visib, nspace_index;
7305 GHashTable *name_cache2, *nspace_table;
7307 mono_image_lock (image);
7309 if (image->name_cache) {
7310 mono_image_unlock (image);
7314 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7316 if (image_is_dynamic (image)) {
7317 mono_image_unlock (image);
7321 /* Temporary hash table to avoid lookups in the nspace_table */
7322 name_cache2 = g_hash_table_new (NULL, NULL);
7324 for (i = 1; i <= t->rows; ++i) {
7325 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7326 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7328 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7329 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7331 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7333 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7334 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7336 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7337 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7338 if (!nspace_table) {
7339 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7340 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7341 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7344 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7347 /* Load type names from EXPORTEDTYPES table */
7349 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7350 guint32 cols [MONO_EXP_TYPE_SIZE];
7353 for (i = 0; i < t->rows; ++i) {
7354 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7355 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7356 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7358 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7359 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7360 if (!nspace_table) {
7361 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7362 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7363 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7366 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7370 g_hash_table_destroy (name_cache2);
7371 mono_image_unlock (image);
7374 /*FIXME Only dynamic assemblies should allow this operation.*/
7376 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7377 const char *name, guint32 index)
7379 GHashTable *nspace_table;
7380 GHashTable *name_cache;
7383 mono_image_lock (image);
7385 if (!image->name_cache)
7386 mono_image_init_name_cache (image);
7388 name_cache = image->name_cache;
7389 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7390 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7391 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7394 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7395 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7397 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7399 mono_image_unlock (image);
7408 find_nocase (gpointer key, gpointer value, gpointer user_data)
7410 char *name = (char*)key;
7411 FindUserData *data = (FindUserData*)user_data;
7413 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7414 data->value = value;
7418 * mono_class_from_name_case:
7419 * @image: The MonoImage where the type is looked up in
7420 * @name_space: the type namespace
7421 * @name: the type short name.
7422 * @deprecated: use the _checked variant
7424 * Obtains a MonoClass with a given namespace and a given name which
7425 * is located in the given MonoImage. The namespace and name
7426 * lookups are case insensitive.
7429 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7432 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7433 g_assert (!mono_error_ok (&error));
7438 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7440 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7441 guint32 cols [MONO_TYPEDEF_SIZE];
7446 mono_error_init (error);
7448 if (image_is_dynamic (image)) {
7450 FindUserData user_data;
7452 mono_image_lock (image);
7454 if (!image->name_cache)
7455 mono_image_init_name_cache (image);
7457 user_data.key = name_space;
7458 user_data.value = NULL;
7459 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7461 if (user_data.value) {
7462 GHashTable *nspace_table = (GHashTable*)user_data.value;
7464 user_data.key = name;
7465 user_data.value = NULL;
7467 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7469 if (user_data.value)
7470 token = GPOINTER_TO_UINT (user_data.value);
7473 mono_image_unlock (image);
7476 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7482 /* add a cache if needed */
7483 for (i = 1; i <= t->rows; ++i) {
7484 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7485 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7487 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7488 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7490 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7492 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7493 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7494 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7495 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7501 return_nested_in (MonoClass *class, char *nested)
7504 char *s = strchr (nested, '/');
7505 gpointer iter = NULL;
7512 while ((found = mono_class_get_nested_types (class, &iter))) {
7513 if (strcmp (found->name, nested) == 0) {
7515 return return_nested_in (found, s);
7523 search_modules (MonoImage *image, const char *name_space, const char *name)
7525 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7526 MonoImage *file_image;
7531 * The EXPORTEDTYPES table only contains public types, so have to search the
7533 * Note: image->modules contains the contents of the MODULEREF table, while
7534 * the real module list is in the FILE table.
7536 for (i = 0; i < file_table->rows; i++) {
7537 guint32 cols [MONO_FILE_SIZE];
7538 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7539 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7542 file_image = mono_image_load_file_for_image (image, i + 1);
7544 class = mono_class_from_name (file_image, name_space, name);
7554 * mono_class_from_name:
7555 * @image: The MonoImage where the type is looked up in
7556 * @name_space: the type namespace
7557 * @name: the type short name.
7559 * Obtains a MonoClass with a given namespace and a given name which
7560 * is located in the given MonoImage.
7562 * To reference nested classes, use the "/" character as a separator.
7563 * For example use "Foo/Bar" to reference the class Bar that is nested
7564 * inside Foo, like this: "class Foo { class Bar {} }".
7567 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7569 GHashTable *nspace_table;
7570 MonoImage *loaded_image;
7577 if ((nested = strchr (name, '/'))) {
7578 int pos = nested - name;
7579 int len = strlen (name);
7582 memcpy (buf, name, len + 1);
7584 nested = buf + pos + 1;
7588 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7589 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7590 gboolean res = get_class_from_name (image, name_space, name, &class);
7593 class = search_modules (image, name_space, name);
7595 return class ? return_nested_in (class, nested) : NULL;
7601 mono_image_lock (image);
7603 if (!image->name_cache)
7604 mono_image_init_name_cache (image);
7606 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7609 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7611 mono_image_unlock (image);
7613 if (!token && image_is_dynamic (image) && image->modules) {
7614 /* Search modules as well */
7615 for (i = 0; i < image->module_count; ++i) {
7616 MonoImage *module = image->modules [i];
7618 class = mono_class_from_name (module, name_space, name);
7625 class = search_modules (image, name_space, name);
7633 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7634 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7635 guint32 cols [MONO_EXP_TYPE_SIZE];
7638 idx = mono_metadata_token_index (token);
7640 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7642 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7643 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7644 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7647 class = mono_class_from_name (loaded_image, name_space, name);
7649 return return_nested_in (class, nested);
7651 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7652 guint32 assembly_idx;
7654 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7656 mono_assembly_load_reference (image, assembly_idx - 1);
7657 g_assert (image->references [assembly_idx - 1]);
7658 if (image->references [assembly_idx - 1] == (gpointer)-1)
7661 /* FIXME: Cycle detection */
7662 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7664 g_error ("not yet implemented");
7668 token = MONO_TOKEN_TYPE_DEF | token;
7670 class = mono_class_get (image, token);
7672 return return_nested_in (class, nested);
7677 * mono_class_is_subclass_of:
7678 * @klass: class to probe if it is a subclass of another one
7679 * @klassc: the class we suspect is the base class
7680 * @check_interfaces: whether we should perform interface checks
7682 * This method determines whether @klass is a subclass of @klassc.
7684 * If the @check_interfaces flag is set, then if @klassc is an interface
7685 * this method return true if the @klass implements the interface or
7686 * if @klass is an interface, if one of its base classes is @klass.
7688 * If @check_interfaces is false then, then if @klass is not an interface
7689 * then it returns true if the @klass is a subclass of @klassc.
7691 * if @klass is an interface and @klassc is System.Object, then this function
7696 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7697 gboolean check_interfaces)
7699 /*FIXME test for interfaces with variant generic arguments*/
7701 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7702 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7704 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7707 for (i = 0; i < klass->interface_count; i ++) {
7708 MonoClass *ic = klass->interfaces [i];
7713 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7718 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7721 if (klassc == mono_defaults.object_class)
7728 mono_type_is_generic_argument (MonoType *type)
7730 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7734 mono_class_has_variant_generic_params (MonoClass *klass)
7737 MonoGenericContainer *container;
7739 if (!klass->generic_class)
7742 container = klass->generic_class->container_class->generic_container;
7744 for (i = 0; i < container->type_argc; ++i)
7745 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7752 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7754 if (target == candidate)
7757 if (check_for_reference_conv &&
7758 mono_type_is_generic_argument (&target->byval_arg) &&
7759 mono_type_is_generic_argument (&candidate->byval_arg)) {
7760 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7761 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7763 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7766 if (!mono_class_is_assignable_from (target, candidate))
7772 * @container the generic container from the GTD
7773 * @klass: the class to be assigned to
7774 * @oklass: the source class
7776 * Both klass and oklass must be instances of the same generic interface.
7777 * Return true if @klass can be assigned to a @klass variable
7780 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7783 MonoType **klass_argv, **oklass_argv;
7784 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7785 MonoGenericContainer *container = klass_gtd->generic_container;
7787 if (klass == oklass)
7790 /*Viable candidates are instances of the same generic interface*/
7791 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7794 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7795 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7797 for (j = 0; j < container->type_argc; ++j) {
7798 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7799 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7801 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7805 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7806 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7808 if (param1_class != param2_class) {
7809 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7810 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7812 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7813 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7823 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7825 MonoGenericParam *gparam, *ogparam;
7826 MonoGenericParamInfo *tinfo, *cinfo;
7827 MonoClass **candidate_class;
7828 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7831 if (target == candidate)
7833 if (target->byval_arg.type != candidate->byval_arg.type)
7836 gparam = target->byval_arg.data.generic_param;
7837 ogparam = candidate->byval_arg.data.generic_param;
7838 tinfo = mono_generic_param_info (gparam);
7839 cinfo = mono_generic_param_info (ogparam);
7841 class_constraint_satisfied = FALSE;
7842 valuetype_constraint_satisfied = FALSE;
7844 /*candidate must have a super set of target's special constraints*/
7845 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7846 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7848 if (cinfo->constraints) {
7849 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7850 MonoClass *cc = *candidate_class;
7852 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7853 class_constraint_satisfied = TRUE;
7854 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7855 valuetype_constraint_satisfied = TRUE;
7858 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7859 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7861 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7863 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7865 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7866 valuetype_constraint_satisfied)) {
7871 /*candidate type constraints must be a superset of target's*/
7872 if (tinfo->constraints) {
7873 MonoClass **target_class;
7874 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7875 MonoClass *tc = *target_class;
7878 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7879 * check it's constraints since it satisfy the constraint by itself.
7881 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7884 if (!cinfo->constraints)
7887 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7888 MonoClass *cc = *candidate_class;
7890 if (mono_class_is_assignable_from (tc, cc))
7894 * This happens when we have the following:
7896 * Bar<K> where K : IFace
7897 * Foo<T, U> where T : U where U : IFace
7899 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7902 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7903 if (mono_gparam_is_assignable_from (target, cc))
7907 if (!*candidate_class)
7912 /*candidate itself must have a constraint that satisfy target*/
7913 if (cinfo->constraints) {
7914 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7915 MonoClass *cc = *candidate_class;
7916 if (mono_class_is_assignable_from (target, cc))
7924 * mono_class_is_assignable_from:
7925 * @klass: the class to be assigned to
7926 * @oklass: the source class
7928 * Return: true if an instance of object oklass can be assigned to an
7929 * instance of object @klass
7932 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7934 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7936 mono_class_init (klass);
7938 if (!oklass->inited)
7939 mono_class_init (oklass);
7941 if (klass->exception_type || oklass->exception_type)
7944 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7945 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7947 return mono_gparam_is_assignable_from (klass, oklass);
7950 if (MONO_CLASS_IS_INTERFACE (klass)) {
7951 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7952 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7953 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7957 for (i = 0; constraints [i]; ++i) {
7958 if (mono_class_is_assignable_from (klass, constraints [i]))
7966 /* interface_offsets might not be set for dynamic classes */
7967 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7969 * oklass might be a generic type parameter but they have
7970 * interface_offsets set.
7972 return mono_reflection_call_is_assignable_to (oklass, klass);
7973 if (!oklass->interface_bitmap)
7974 /* Happens with generic instances of not-yet created dynamic types */
7976 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7979 if (mono_class_has_variant_generic_params (klass)) {
7982 mono_class_setup_interfaces (oklass, &error);
7983 if (!mono_error_ok (&error)) {
7984 mono_error_cleanup (&error);
7988 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7989 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7990 MonoClass *iface = oklass->interfaces_packed [i];
7992 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7997 } else if (klass->delegate) {
7998 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8000 }else if (klass->rank) {
8001 MonoClass *eclass, *eoclass;
8003 if (oklass->rank != klass->rank)
8006 /* vectors vs. one dimensional arrays */
8007 if (oklass->byval_arg.type != klass->byval_arg.type)
8010 eclass = klass->cast_class;
8011 eoclass = oklass->cast_class;
8014 * a is b does not imply a[] is b[] when a is a valuetype, and
8015 * b is a reference type.
8018 if (eoclass->valuetype) {
8019 if ((eclass == mono_defaults.enum_class) ||
8020 (eclass == mono_defaults.enum_class->parent) ||
8021 (eclass == mono_defaults.object_class))
8025 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8026 } else if (mono_class_is_nullable (klass)) {
8027 if (mono_class_is_nullable (oklass))
8028 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8030 return mono_class_is_assignable_from (klass->cast_class, oklass);
8031 } else if (klass == mono_defaults.object_class)
8034 return mono_class_has_parent (oklass, klass);
8037 /*Check if @oklass is variant compatible with @klass.*/
8039 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8042 MonoType **klass_argv, **oklass_argv;
8043 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8044 MonoGenericContainer *container = klass_gtd->generic_container;
8046 /*Viable candidates are instances of the same generic interface*/
8047 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8050 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8051 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8053 for (j = 0; j < container->type_argc; ++j) {
8054 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8055 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8057 if (param1_class->valuetype != param2_class->valuetype)
8061 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8062 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8064 if (param1_class != param2_class) {
8065 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8066 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8068 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8069 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8077 /*Check if @candidate implements the interface @target*/
8079 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8083 gboolean is_variant = mono_class_has_variant_generic_params (target);
8085 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8086 if (mono_class_is_variant_compatible_slow (target, candidate))
8091 if (candidate == target)
8094 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8095 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8096 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8098 if (tb && tb->interfaces) {
8099 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8100 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8101 MonoClass *iface_class;
8103 /* we can't realize the type here since it can do pretty much anything. */
8106 iface_class = mono_class_from_mono_type (iface->type);
8107 if (iface_class == target)
8109 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8111 if (mono_class_implement_interface_slow (target, iface_class))
8116 /*setup_interfaces don't mono_class_init anything*/
8117 /*FIXME this doesn't handle primitive type arrays.
8118 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8119 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8121 mono_class_setup_interfaces (candidate, &error);
8122 if (!mono_error_ok (&error)) {
8123 mono_error_cleanup (&error);
8127 for (i = 0; i < candidate->interface_count; ++i) {
8128 if (candidate->interfaces [i] == target)
8131 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8134 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8138 candidate = candidate->parent;
8139 } while (candidate);
8145 * Check if @oklass can be assigned to @klass.
8146 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8149 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8151 if (candidate == target)
8153 if (target == mono_defaults.object_class)
8156 if (mono_class_has_parent (candidate, target))
8159 /*If target is not an interface there is no need to check them.*/
8160 if (MONO_CLASS_IS_INTERFACE (target))
8161 return mono_class_implement_interface_slow (target, candidate);
8163 if (target->delegate && mono_class_has_variant_generic_params (target))
8164 return mono_class_is_variant_compatible (target, candidate, FALSE);
8167 MonoClass *eclass, *eoclass;
8169 if (target->rank != candidate->rank)
8172 /* vectors vs. one dimensional arrays */
8173 if (target->byval_arg.type != candidate->byval_arg.type)
8176 eclass = target->cast_class;
8177 eoclass = candidate->cast_class;
8180 * a is b does not imply a[] is b[] when a is a valuetype, and
8181 * b is a reference type.
8184 if (eoclass->valuetype) {
8185 if ((eclass == mono_defaults.enum_class) ||
8186 (eclass == mono_defaults.enum_class->parent) ||
8187 (eclass == mono_defaults.object_class))
8191 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8193 /*FIXME properly handle nullables */
8194 /*FIXME properly handle (M)VAR */
8199 * mono_class_get_cctor:
8200 * @klass: A MonoClass pointer
8202 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8205 mono_class_get_cctor (MonoClass *klass)
8207 MonoCachedClassInfo cached_info;
8209 if (image_is_dynamic (klass->image)) {
8211 * has_cctor is not set for these classes because mono_class_init () is
8214 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8217 if (!klass->has_cctor)
8220 if (mono_class_get_cached_class_info (klass, &cached_info))
8221 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8223 if (klass->generic_class && !klass->methods)
8224 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8226 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8230 * mono_class_get_finalizer:
8231 * @klass: The MonoClass pointer
8233 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8236 mono_class_get_finalizer (MonoClass *klass)
8238 MonoCachedClassInfo cached_info;
8241 mono_class_init (klass);
8242 if (!mono_class_has_finalizer (klass))
8245 if (mono_class_get_cached_class_info (klass, &cached_info))
8246 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8248 mono_class_setup_vtable (klass);
8249 return klass->vtable [finalize_slot];
8254 * mono_class_needs_cctor_run:
8255 * @klass: the MonoClass pointer
8256 * @caller: a MonoMethod describing the caller
8258 * Determines whenever the class has a static constructor and whenever it
8259 * needs to be called when executing CALLER.
8262 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8266 method = mono_class_get_cctor (klass);
8268 return (method == caller) ? FALSE : TRUE;
8274 * mono_class_array_element_size:
8277 * Returns: the number of bytes an element of type @klass
8278 * uses when stored into an array.
8281 mono_class_array_element_size (MonoClass *klass)
8283 MonoType *type = &klass->byval_arg;
8286 switch (type->type) {
8289 case MONO_TYPE_BOOLEAN:
8293 case MONO_TYPE_CHAR:
8302 case MONO_TYPE_CLASS:
8303 case MONO_TYPE_STRING:
8304 case MONO_TYPE_OBJECT:
8305 case MONO_TYPE_SZARRAY:
8306 case MONO_TYPE_ARRAY:
8308 case MONO_TYPE_MVAR:
8309 return sizeof (gpointer);
8314 case MONO_TYPE_VALUETYPE:
8315 if (type->data.klass->enumtype) {
8316 type = mono_class_enum_basetype (type->data.klass);
8317 klass = klass->element_class;
8320 return mono_class_instance_size (klass) - sizeof (MonoObject);
8321 case MONO_TYPE_GENERICINST:
8322 type = &type->data.generic_class->container_class->byval_arg;
8325 case MONO_TYPE_VOID:
8329 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8335 * mono_array_element_size:
8336 * @ac: pointer to a #MonoArrayClass
8338 * Returns: the size of single array element.
8341 mono_array_element_size (MonoClass *ac)
8343 g_assert (ac->rank);
8344 return ac->sizes.element_size;
8348 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8349 MonoGenericContext *context)
8351 if (image_is_dynamic (image)) {
8352 MonoClass *tmp_handle_class;
8353 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8355 g_assert (tmp_handle_class);
8357 *handle_class = tmp_handle_class;
8359 if (tmp_handle_class == mono_defaults.typehandle_class)
8360 return &((MonoClass*)obj)->byval_arg;
8365 switch (token & 0xff000000) {
8366 case MONO_TOKEN_TYPE_DEF:
8367 case MONO_TOKEN_TYPE_REF:
8368 case MONO_TOKEN_TYPE_SPEC: {
8372 *handle_class = mono_defaults.typehandle_class;
8373 type = mono_type_get_checked (image, token, context, &error);
8375 mono_loader_set_error_from_mono_error (&error);
8376 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8379 mono_class_init (mono_class_from_mono_type (type));
8380 /* We return a MonoType* as handle */
8383 case MONO_TOKEN_FIELD_DEF: {
8386 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8390 *handle_class = mono_defaults.fieldhandle_class;
8391 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8393 mono_loader_set_error_from_mono_error (&error);
8394 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8397 mono_class_init (class);
8398 return mono_class_get_field (class, token);
8400 case MONO_TOKEN_METHOD_DEF:
8401 case MONO_TOKEN_METHOD_SPEC: {
8403 meth = mono_get_method_full (image, token, NULL, context);
8405 *handle_class = mono_defaults.methodhandle_class;
8408 case MONO_TOKEN_MEMBER_REF: {
8409 guint32 cols [MONO_MEMBERREF_SIZE];
8411 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8412 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8413 mono_metadata_decode_blob_size (sig, &sig);
8414 if (*sig == 0x6) { /* it's a field */
8416 MonoClassField *field;
8417 field = mono_field_from_token (image, token, &klass, context);
8419 *handle_class = mono_defaults.fieldhandle_class;
8423 meth = mono_get_method_full (image, token, NULL, context);
8425 *handle_class = mono_defaults.methodhandle_class;
8430 g_warning ("Unknown token 0x%08x in ldtoken", token);
8437 * This function might need to call runtime functions so it can't be part
8438 * of the metadata library.
8440 static MonoLookupDynamicToken lookup_dynamic = NULL;
8443 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8445 lookup_dynamic = func;
8449 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8451 MonoClass *handle_class;
8453 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8457 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8459 return lookup_dynamic (image, token, valid_token, handle_class, context);
8462 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8465 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8467 get_cached_class_info = func;
8471 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8473 if (!get_cached_class_info)
8476 return get_cached_class_info (klass, res);
8480 mono_install_get_class_from_name (MonoGetClassFromName func)
8482 get_class_from_name = func;
8486 mono_class_get_image (MonoClass *klass)
8488 return klass->image;
8492 * mono_class_get_element_class:
8493 * @klass: the MonoClass to act on
8495 * Returns: the element class of an array or an enumeration.
8498 mono_class_get_element_class (MonoClass *klass)
8500 return klass->element_class;
8504 * mono_class_is_valuetype:
8505 * @klass: the MonoClass to act on
8507 * Returns: true if the MonoClass represents a ValueType.
8510 mono_class_is_valuetype (MonoClass *klass)
8512 return klass->valuetype;
8516 * mono_class_is_enum:
8517 * @klass: the MonoClass to act on
8519 * Returns: true if the MonoClass represents an enumeration.
8522 mono_class_is_enum (MonoClass *klass)
8524 return klass->enumtype;
8528 * mono_class_enum_basetype:
8529 * @klass: the MonoClass to act on
8531 * Returns: the underlying type representation for an enumeration.
8534 mono_class_enum_basetype (MonoClass *klass)
8536 if (klass->element_class == klass)
8537 /* SRE or broken types */
8540 return &klass->element_class->byval_arg;
8544 * mono_class_get_parent
8545 * @klass: the MonoClass to act on
8547 * Returns: the parent class for this class.
8550 mono_class_get_parent (MonoClass *klass)
8552 return klass->parent;
8556 * mono_class_get_nesting_type;
8557 * @klass: the MonoClass to act on
8559 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8562 mono_class_get_nesting_type (MonoClass *klass)
8564 return klass->nested_in;
8568 * mono_class_get_rank:
8569 * @klass: the MonoClass to act on
8571 * Returns: the rank for the array (the number of dimensions).
8574 mono_class_get_rank (MonoClass *klass)
8580 * mono_class_get_flags:
8581 * @klass: the MonoClass to act on
8583 * The type flags from the TypeDef table from the metadata.
8584 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8587 * Returns: the flags from the TypeDef table.
8590 mono_class_get_flags (MonoClass *klass)
8592 return klass->flags;
8596 * mono_class_get_name
8597 * @klass: the MonoClass to act on
8599 * Returns: the name of the class.
8602 mono_class_get_name (MonoClass *klass)
8608 * mono_class_get_namespace:
8609 * @klass: the MonoClass to act on
8611 * Returns: the namespace of the class.
8614 mono_class_get_namespace (MonoClass *klass)
8616 return klass->name_space;
8620 * mono_class_get_type:
8621 * @klass: the MonoClass to act on
8623 * This method returns the internal Type representation for the class.
8625 * Returns: the MonoType from the class.
8628 mono_class_get_type (MonoClass *klass)
8630 return &klass->byval_arg;
8634 * mono_class_get_type_token
8635 * @klass: the MonoClass to act on
8637 * This method returns type token for the class.
8639 * Returns: the type token for the class.
8642 mono_class_get_type_token (MonoClass *klass)
8644 return klass->type_token;
8648 * mono_class_get_byref_type:
8649 * @klass: the MonoClass to act on
8654 mono_class_get_byref_type (MonoClass *klass)
8656 return &klass->this_arg;
8660 * mono_class_num_fields:
8661 * @klass: the MonoClass to act on
8663 * Returns: the number of static and instance fields in the class.
8666 mono_class_num_fields (MonoClass *klass)
8668 return klass->field.count;
8672 * mono_class_num_methods:
8673 * @klass: the MonoClass to act on
8675 * Returns: the number of methods in the class.
8678 mono_class_num_methods (MonoClass *klass)
8680 return klass->method.count;
8684 * mono_class_num_properties
8685 * @klass: the MonoClass to act on
8687 * Returns: the number of properties in the class.
8690 mono_class_num_properties (MonoClass *klass)
8692 mono_class_setup_properties (klass);
8694 return klass->ext->property.count;
8698 * mono_class_num_events:
8699 * @klass: the MonoClass to act on
8701 * Returns: the number of events in the class.
8704 mono_class_num_events (MonoClass *klass)
8706 mono_class_setup_events (klass);
8708 return klass->ext->event.count;
8712 * mono_class_get_fields:
8713 * @klass: the MonoClass to act on
8715 * This routine is an iterator routine for retrieving the fields in a class.
8717 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8718 * iterate over all of the elements. When no more values are
8719 * available, the return value is NULL.
8721 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8724 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8726 MonoClassField* field;
8730 mono_class_setup_fields_locking (klass);
8731 if (klass->exception_type)
8733 /* start from the first */
8734 if (klass->field.count) {
8735 return *iter = &klass->fields [0];
8743 if (field < &klass->fields [klass->field.count]) {
8744 return *iter = field;
8750 * mono_class_get_methods
8751 * @klass: the MonoClass to act on
8753 * This routine is an iterator routine for retrieving the fields in a class.
8755 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8756 * iterate over all of the elements. When no more values are
8757 * available, the return value is NULL.
8759 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8762 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8764 MonoMethod** method;
8768 mono_class_setup_methods (klass);
8771 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8772 * FIXME we should better report this error to the caller
8774 if (!klass->methods)
8776 /* start from the first */
8777 if (klass->method.count) {
8778 *iter = &klass->methods [0];
8779 return klass->methods [0];
8787 if (method < &klass->methods [klass->method.count]) {
8795 * mono_class_get_virtual_methods:
8797 * Iterate over the virtual methods of KLASS.
8799 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8802 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8804 MonoMethod** method;
8807 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8809 mono_class_setup_methods (klass);
8811 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8812 * FIXME we should better report this error to the caller
8814 if (!klass->methods)
8816 /* start from the first */
8817 method = &klass->methods [0];
8822 while (method < &klass->methods [klass->method.count]) {
8823 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8827 if (method < &klass->methods [klass->method.count]) {
8834 /* Search directly in metadata to avoid calling setup_methods () */
8835 MonoMethod *res = NULL;
8841 start_index = GPOINTER_TO_UINT (*iter);
8844 for (i = start_index; i < klass->method.count; ++i) {
8847 /* class->method.first points into the methodptr table */
8848 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8850 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8854 if (i < klass->method.count) {
8855 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8856 /* Add 1 here so the if (*iter) check fails */
8857 *iter = GUINT_TO_POINTER (i + 1);
8866 * mono_class_get_properties:
8867 * @klass: the MonoClass to act on
8869 * This routine is an iterator routine for retrieving the properties in a class.
8871 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8872 * iterate over all of the elements. When no more values are
8873 * available, the return value is NULL.
8875 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8878 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8880 MonoProperty* property;
8884 mono_class_setup_properties (klass);
8885 /* start from the first */
8886 if (klass->ext->property.count) {
8887 return *iter = &klass->ext->properties [0];
8895 if (property < &klass->ext->properties [klass->ext->property.count]) {
8896 return *iter = property;
8902 * mono_class_get_events:
8903 * @klass: the MonoClass to act on
8905 * This routine is an iterator routine for retrieving the properties in a class.
8907 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8908 * iterate over all of the elements. When no more values are
8909 * available, the return value is NULL.
8911 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8914 mono_class_get_events (MonoClass* klass, gpointer *iter)
8920 mono_class_setup_events (klass);
8921 /* start from the first */
8922 if (klass->ext->event.count) {
8923 return *iter = &klass->ext->events [0];
8931 if (event < &klass->ext->events [klass->ext->event.count]) {
8932 return *iter = event;
8938 * mono_class_get_interfaces
8939 * @klass: the MonoClass to act on
8941 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8943 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8944 * iterate over all of the elements. When no more values are
8945 * available, the return value is NULL.
8947 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8950 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8958 mono_class_init (klass);
8959 if (!klass->interfaces_inited) {
8960 mono_class_setup_interfaces (klass, &error);
8961 if (!mono_error_ok (&error)) {
8962 mono_error_cleanup (&error);
8966 /* start from the first */
8967 if (klass->interface_count) {
8968 *iter = &klass->interfaces [0];
8969 return klass->interfaces [0];
8977 if (iface < &klass->interfaces [klass->interface_count]) {
8985 setup_nested_types (MonoClass *klass)
8988 GList *classes, *nested_classes, *l;
8991 if (klass->nested_classes_inited)
8994 if (!klass->type_token)
8995 klass->nested_classes_inited = TRUE;
8997 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9001 guint32 cols [MONO_NESTED_CLASS_SIZE];
9002 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9003 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9004 if (!mono_error_ok (&error)) {
9005 /*FIXME don't swallow the error message*/
9006 mono_error_cleanup (&error);
9008 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9012 classes = g_list_prepend (classes, nclass);
9014 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9017 mono_class_alloc_ext (klass);
9019 nested_classes = NULL;
9020 for (l = classes; l; l = l->next)
9021 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9022 g_list_free (classes);
9024 mono_image_lock (klass->image);
9026 mono_memory_barrier ();
9027 if (!klass->nested_classes_inited) {
9028 klass->ext->nested_classes = nested_classes;
9029 mono_memory_barrier ();
9030 klass->nested_classes_inited = TRUE;
9033 mono_image_unlock (klass->image);
9037 * mono_class_get_nested_types
9038 * @klass: the MonoClass to act on
9040 * This routine is an iterator routine for retrieving the nested types of a class.
9041 * This works only if @klass is non-generic, or a generic type definition.
9043 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9044 * iterate over all of the elements. When no more values are
9045 * available, the return value is NULL.
9047 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9050 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9056 if (!klass->nested_classes_inited)
9057 setup_nested_types (klass);
9060 /* start from the first */
9061 if (klass->ext && klass->ext->nested_classes) {
9062 *iter = klass->ext->nested_classes;
9063 return klass->ext->nested_classes->data;
9065 /* no nested types */
9080 * mono_class_is_delegate
9081 * @klass: the MonoClass to act on
9083 * Returns: true if the MonoClass represents a System.Delegate.
9086 mono_class_is_delegate (MonoClass *klass)
9088 return klass->delegate;
9092 * mono_class_implements_interface
9093 * @klass: The MonoClass to act on
9094 * @interface: The interface to check if @klass implements.
9096 * Returns: true if @klass implements @interface.
9099 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9101 return mono_class_is_assignable_from (iface, klass);
9105 * mono_field_get_name:
9106 * @field: the MonoClassField to act on
9108 * Returns: the name of the field.
9111 mono_field_get_name (MonoClassField *field)
9117 * mono_field_get_type:
9118 * @field: the MonoClassField to act on
9120 * Returns: MonoType of the field.
9123 mono_field_get_type (MonoClassField *field)
9126 MonoType *type = mono_field_get_type_checked (field, &error);
9127 if (!mono_error_ok (&error)) {
9128 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9129 mono_error_cleanup (&error);
9136 * mono_field_get_type_checked:
9137 * @field: the MonoClassField to act on
9138 * @error: used to return any erro found while retrieving @field type
9140 * Returns: MonoType of the field.
9143 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9145 mono_error_init (error);
9147 mono_field_resolve_type (field, error);
9152 * mono_field_get_parent:
9153 * @field: the MonoClassField to act on
9155 * Returns: MonoClass where the field was defined.
9158 mono_field_get_parent (MonoClassField *field)
9160 return field->parent;
9164 * mono_field_get_flags;
9165 * @field: the MonoClassField to act on
9167 * The metadata flags for a field are encoded using the
9168 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9170 * Returns: the flags for the field.
9173 mono_field_get_flags (MonoClassField *field)
9176 return mono_field_resolve_flags (field);
9177 return field->type->attrs;
9181 * mono_field_get_offset;
9182 * @field: the MonoClassField to act on
9184 * Returns: the field offset.
9187 mono_field_get_offset (MonoClassField *field)
9189 return field->offset;
9193 mono_field_get_rva (MonoClassField *field)
9197 MonoClass *klass = field->parent;
9198 MonoFieldDefaultValue *field_def_values;
9200 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9202 if (!klass->ext || !klass->ext->field_def_values) {
9203 mono_class_alloc_ext (klass);
9205 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9207 mono_image_lock (klass->image);
9208 if (!klass->ext->field_def_values)
9209 klass->ext->field_def_values = field_def_values;
9210 mono_image_unlock (klass->image);
9213 field_index = mono_field_get_index (field);
9215 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9216 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9218 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9219 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9222 return klass->ext->field_def_values [field_index].data;
9226 * mono_field_get_data;
9227 * @field: the MonoClassField to act on
9229 * Returns: pointer to the metadata constant value or to the field
9230 * data if it has an RVA flag.
9233 mono_field_get_data (MonoClassField *field)
9235 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9236 MonoTypeEnum def_type;
9238 return mono_class_get_field_default_value (field, &def_type);
9239 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9240 return mono_field_get_rva (field);
9247 * mono_property_get_name:
9248 * @prop: the MonoProperty to act on
9250 * Returns: the name of the property
9253 mono_property_get_name (MonoProperty *prop)
9259 * mono_property_get_set_method
9260 * @prop: the MonoProperty to act on.
9262 * Returns: the setter method of the property (A MonoMethod)
9265 mono_property_get_set_method (MonoProperty *prop)
9271 * mono_property_get_get_method
9272 * @prop: the MonoProperty to act on.
9274 * Returns: the setter method of the property (A MonoMethod)
9277 mono_property_get_get_method (MonoProperty *prop)
9283 * mono_property_get_parent:
9284 * @prop: the MonoProperty to act on.
9286 * Returns: the MonoClass where the property was defined.
9289 mono_property_get_parent (MonoProperty *prop)
9291 return prop->parent;
9295 * mono_property_get_flags:
9296 * @prop: the MonoProperty to act on.
9298 * The metadata flags for a property are encoded using the
9299 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9301 * Returns: the flags for the property.
9304 mono_property_get_flags (MonoProperty *prop)
9310 * mono_event_get_name:
9311 * @event: the MonoEvent to act on
9313 * Returns: the name of the event.
9316 mono_event_get_name (MonoEvent *event)
9322 * mono_event_get_add_method:
9323 * @event: The MonoEvent to act on.
9325 * Returns: the @add' method for the event (a MonoMethod).
9328 mono_event_get_add_method (MonoEvent *event)
9334 * mono_event_get_remove_method:
9335 * @event: The MonoEvent to act on.
9337 * Returns: the @remove method for the event (a MonoMethod).
9340 mono_event_get_remove_method (MonoEvent *event)
9342 return event->remove;
9346 * mono_event_get_raise_method:
9347 * @event: The MonoEvent to act on.
9349 * Returns: the @raise method for the event (a MonoMethod).
9352 mono_event_get_raise_method (MonoEvent *event)
9354 return event->raise;
9358 * mono_event_get_parent:
9359 * @event: the MonoEvent to act on.
9361 * Returns: the MonoClass where the event is defined.
9364 mono_event_get_parent (MonoEvent *event)
9366 return event->parent;
9370 * mono_event_get_flags
9371 * @event: the MonoEvent to act on.
9373 * The metadata flags for an event are encoded using the
9374 * EVENT_* constants. See the tabledefs.h file for details.
9376 * Returns: the flags for the event.
9379 mono_event_get_flags (MonoEvent *event)
9381 return event->attrs;
9385 * mono_class_get_method_from_name:
9386 * @klass: where to look for the method
9387 * @name: name of the method
9388 * @param_count: number of parameters. -1 for any number.
9390 * Obtains a MonoMethod with a given name and number of parameters.
9391 * It only works if there are no multiple signatures for any given method name.
9394 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9396 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9400 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9402 MonoMethod *res = NULL;
9405 /* Search directly in the metadata to avoid calling setup_methods () */
9406 for (i = 0; i < klass->method.count; ++i) {
9407 guint32 cols [MONO_METHOD_SIZE];
9409 MonoMethodSignature *sig;
9411 /* class->method.first points into the methodptr table */
9412 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9414 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9415 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9416 if (param_count == -1) {
9420 sig = mono_method_signature (method);
9421 if (sig && sig->param_count == param_count) {
9432 * mono_class_get_method_from_name_flags:
9433 * @klass: where to look for the method
9434 * @name_space: name of the method
9435 * @param_count: number of parameters. -1 for any number.
9436 * @flags: flags which must be set in the method
9438 * Obtains a MonoMethod with a given name and number of parameters.
9439 * It only works if there are no multiple signatures for any given method name.
9442 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9444 MonoMethod *res = NULL;
9447 mono_class_init (klass);
9449 if (klass->generic_class && !klass->methods) {
9450 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9452 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9456 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9457 mono_class_setup_methods (klass);
9459 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9460 See mono/tests/array_load_exception.il
9461 FIXME we should better report this error to the caller
9463 if (!klass->methods)
9465 for (i = 0; i < klass->method.count; ++i) {
9466 MonoMethod *method = klass->methods [i];
9468 if (method->name[0] == name [0] &&
9469 !strcmp (name, method->name) &&
9470 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9471 ((method->flags & flags) == flags)) {
9478 res = find_method_in_metadata (klass, name, param_count, flags);
9485 * mono_class_set_failure:
9486 * @klass: class in which the failure was detected
9487 * @ex_type: the kind of exception/error to be thrown (later)
9488 * @ex_data: exception data (specific to each type of exception/error)
9490 * Keep a detected failure informations in the class for later processing.
9491 * Note that only the first failure is kept.
9493 * LOCKING: Acquires the loader lock.
9496 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9498 if (klass->exception_type)
9501 mono_loader_lock ();
9502 klass->exception_type = ex_type;
9504 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9505 mono_loader_unlock ();
9511 * mono_class_get_exception_data:
9513 * Return the exception_data property of KLASS.
9515 * LOCKING: Acquires the loader lock.
9518 mono_class_get_exception_data (MonoClass *klass)
9520 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9524 * mono_classes_init:
9526 * Initialize the resources used by this module.
9529 mono_classes_init (void)
9531 mono_mutex_init (&classes_mutex);
9533 mono_counters_register ("Inflated methods size",
9534 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9535 mono_counters_register ("Inflated classes",
9536 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9537 mono_counters_register ("Inflated classes size",
9538 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9539 mono_counters_register ("MonoClass size",
9540 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9541 mono_counters_register ("MonoClassExt size",
9542 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9546 * mono_classes_cleanup:
9548 * Free the resources used by this module.
9551 mono_classes_cleanup (void)
9553 if (global_interface_bitset)
9554 mono_bitset_free (global_interface_bitset);
9555 global_interface_bitset = NULL;
9556 mono_mutex_destroy (&classes_mutex);
9560 * mono_class_get_exception_for_failure:
9561 * @klass: class in which the failure was detected
9563 * Return a constructed MonoException than the caller can then throw
9564 * using mono_raise_exception - or NULL if no failure is present (or
9565 * doesn't result in an exception).
9568 mono_class_get_exception_for_failure (MonoClass *klass)
9570 gpointer exception_data = mono_class_get_exception_data (klass);
9572 switch (klass->exception_type) {
9573 #ifndef DISABLE_SECURITY
9574 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9575 MonoDomain *domain = mono_domain_get ();
9576 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9577 MonoMethod *method = exception_data;
9578 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9579 MonoObject *exc = NULL;
9583 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9584 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9585 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9587 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9588 return (MonoException*) exc;
9591 case MONO_EXCEPTION_TYPE_LOAD: {
9594 char *str = mono_type_get_full_name (klass);
9595 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9596 name = mono_string_new (mono_domain_get (), str);
9598 ex = mono_get_exception_type_load (name, astr);
9602 case MONO_EXCEPTION_MISSING_METHOD: {
9603 char *class_name = exception_data;
9604 char *assembly_name = class_name + strlen (class_name) + 1;
9606 return mono_get_exception_missing_method (class_name, assembly_name);
9608 case MONO_EXCEPTION_MISSING_FIELD: {
9609 char *class_name = exception_data;
9610 char *member_name = class_name + strlen (class_name) + 1;
9612 return mono_get_exception_missing_field (class_name, member_name);
9614 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9615 char *msg_format = exception_data;
9616 char *assembly_name = msg_format + strlen (msg_format) + 1;
9617 char *msg = g_strdup_printf (msg_format, assembly_name);
9620 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9626 case MONO_EXCEPTION_BAD_IMAGE: {
9627 return mono_get_exception_bad_image_format (exception_data);
9630 MonoLoaderError *error;
9633 error = mono_loader_get_last_error ();
9635 ex = mono_loader_error_prepare_exception (error);
9639 /* TODO - handle other class related failures */
9646 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9648 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9649 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9651 if (outer_klass == inner_klass)
9653 inner_klass = inner_klass->nested_in;
9654 } while (inner_klass);
9659 mono_class_get_generic_type_definition (MonoClass *klass)
9661 return klass->generic_class ? klass->generic_class->container_class : klass;
9665 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9667 * Generic instantiations are ignored for all super types of @klass.
9669 * Visibility checks ignoring generic instantiations.
9672 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9675 klass = mono_class_get_generic_type_definition (klass);
9676 parent = mono_class_get_generic_type_definition (parent);
9677 mono_class_setup_supertypes (klass);
9679 for (i = 0; i < klass->idepth; ++i) {
9680 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9686 * Subtype can only access parent members with family protection if the site object
9687 * is subclass of Subtype. For example:
9688 * class A { protected int x; }
9690 * void valid_access () {
9694 * void invalid_access () {
9701 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9703 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9706 if (context_klass == NULL)
9708 /*if access_klass is not member_klass context_klass must be type compat*/
9709 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9715 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9718 if (accessing == accessed)
9720 if (!accessed || !accessing)
9723 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9724 * anywhere so untrusted friends are not safe to access platform's code internals */
9725 if (mono_security_core_clr_enabled ()) {
9726 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9730 mono_assembly_load_friends (accessed);
9731 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9732 MonoAssemblyName *friend = tmp->data;
9733 /* Be conservative with checks */
9736 if (strcmp (accessing->aname.name, friend->name))
9738 if (friend->public_key_token [0]) {
9739 if (!accessing->aname.public_key_token [0])
9741 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9750 * If klass is a generic type or if it is derived from a generic type, return the
9751 * MonoClass of the generic definition
9752 * Returns NULL if not found
9755 get_generic_definition_class (MonoClass *klass)
9758 if (klass->generic_class && klass->generic_class->container_class)
9759 return klass->generic_class->container_class;
9760 klass = klass->parent;
9766 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9769 for (i = 0; i < ginst->type_argc; ++i) {
9770 MonoType *type = ginst->type_argv[i];
9771 switch (type->type) {
9772 case MONO_TYPE_SZARRAY:
9773 if (!can_access_type (access_klass, type->data.klass))
9776 case MONO_TYPE_ARRAY:
9777 if (!can_access_type (access_klass, type->data.array->eklass))
9781 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9784 case MONO_TYPE_CLASS:
9785 case MONO_TYPE_VALUETYPE:
9786 case MONO_TYPE_GENERICINST:
9787 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9795 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9799 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9802 if (access_klass->element_class && !access_klass->enumtype)
9803 access_klass = access_klass->element_class;
9805 if (member_klass->element_class && !member_klass->enumtype)
9806 member_klass = member_klass->element_class;
9808 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9810 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9813 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9816 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9819 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9822 /*Non nested type with nested visibility. We just fail it.*/
9823 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9826 switch (access_level) {
9827 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9828 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9830 case TYPE_ATTRIBUTE_PUBLIC:
9833 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9836 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9837 return is_nesting_type (member_klass, access_klass);
9839 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9840 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9842 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9843 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9845 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9846 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9847 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9849 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9850 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9851 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9856 /* FIXME: check visibility of type, too */
9858 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9860 MonoClass *member_generic_def;
9861 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9864 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9865 access_klass->generic_container) &&
9866 (member_generic_def = get_generic_definition_class (member_klass))) {
9867 MonoClass *access_container;
9869 if (access_klass->generic_container)
9870 access_container = access_klass;
9872 access_container = access_klass->generic_class->container_class;
9874 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9878 /* Partition I 8.5.3.2 */
9879 /* the access level values are the same for fields and methods */
9880 switch (access_level) {
9881 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9882 /* same compilation unit */
9883 return access_klass->image == member_klass->image;
9884 case FIELD_ATTRIBUTE_PRIVATE:
9885 return access_klass == member_klass;
9886 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9887 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9888 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9891 case FIELD_ATTRIBUTE_ASSEMBLY:
9892 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9893 case FIELD_ATTRIBUTE_FAMILY:
9894 if (is_valid_family_access (access_klass, member_klass, context_klass))
9897 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9898 if (is_valid_family_access (access_klass, member_klass, context_klass))
9900 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9901 case FIELD_ATTRIBUTE_PUBLIC:
9908 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9910 /* FIXME: check all overlapping fields */
9911 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9913 MonoClass *nested = method->klass->nested_in;
9915 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9918 nested = nested->nested_in;
9925 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9927 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9929 MonoClass *nested = method->klass->nested_in;
9931 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9934 nested = nested->nested_in;
9939 * with generics calls to explicit interface implementations can be expressed
9940 * directly: the method is private, but we must allow it. This may be opening
9941 * a hole or the generics code should handle this differently.
9942 * Maybe just ensure the interface type is public.
9944 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9950 * mono_method_can_access_method_full:
9951 * @method: The caller method
9952 * @called: The called method
9953 * @context_klass: The static type on stack of the owner @called object used
9955 * This function must be used with instance calls, as they have more strict family accessibility.
9956 * It can be used with static methods, but context_klass should be NULL.
9958 * Returns: TRUE if caller have proper visibility and acessibility to @called
9961 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9963 MonoClass *access_class = method->klass;
9964 MonoClass *member_class = called->klass;
9965 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9967 MonoClass *nested = access_class->nested_in;
9969 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9972 nested = nested->nested_in;
9979 can = can_access_type (access_class, member_class);
9981 MonoClass *nested = access_class->nested_in;
9983 can = can_access_type (nested, member_class);
9986 nested = nested->nested_in;
9993 if (called->is_inflated) {
9994 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9995 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10004 * mono_method_can_access_field_full:
10005 * @method: The caller method
10006 * @field: The accessed field
10007 * @context_klass: The static type on stack of the owner @field object used
10009 * This function must be used with instance fields, as they have more strict family accessibility.
10010 * It can be used with static fields, but context_klass should be NULL.
10012 * Returns: TRUE if caller have proper visibility and acessibility to @field
10015 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10017 MonoClass *access_class = method->klass;
10018 MonoClass *member_class = field->parent;
10019 /* FIXME: check all overlapping fields */
10020 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10022 MonoClass *nested = access_class->nested_in;
10024 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10027 nested = nested->nested_in;
10034 can = can_access_type (access_class, member_class);
10036 MonoClass *nested = access_class->nested_in;
10038 can = can_access_type (nested, member_class);
10041 nested = nested->nested_in;
10051 * mono_class_can_access_class:
10052 * @source_class: The source class
10053 * @target_class: The accessed class
10055 * This function returns is @target_class is visible to @source_class
10057 * Returns: TRUE if source have proper visibility and acessibility to target
10060 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10062 return can_access_type (source_class, target_class);
10066 * mono_type_is_valid_enum_basetype:
10067 * @type: The MonoType to check
10069 * Returns: TRUE if the type can be used as the basetype of an enum
10071 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10072 switch (type->type) {
10075 case MONO_TYPE_BOOLEAN:
10078 case MONO_TYPE_CHAR:
10091 * mono_class_is_valid_enum:
10092 * @klass: An enum class to be validated
10094 * This method verify the required properties an enum should have.
10096 * Returns: TRUE if the informed enum class is valid
10098 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10099 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10100 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10102 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10103 MonoClassField * field;
10104 gpointer iter = NULL;
10105 gboolean found_base_field = FALSE;
10107 g_assert (klass->enumtype);
10108 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10109 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10113 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10116 while ((field = mono_class_get_fields (klass, &iter))) {
10117 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10118 if (found_base_field)
10120 found_base_field = TRUE;
10121 if (!mono_type_is_valid_enum_basetype (field->type))
10126 if (!found_base_field)
10129 if (klass->method.count > 0)
10136 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10138 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10142 * mono_class_setup_interface_id:
10144 * Initializes MonoClass::interface_id if required.
10146 * LOCKING: Acquires the loader lock.
10149 mono_class_setup_interface_id (MonoClass *class)
10151 mono_loader_lock ();
10152 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10153 class->interface_id = mono_get_unique_iid (class);
10154 mono_loader_unlock ();
10158 * mono_class_alloc_ext:
10160 * Allocate klass->ext if not already done.
10163 mono_class_alloc_ext (MonoClass *klass)
10170 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10171 mono_image_lock (klass->image);
10172 mono_memory_barrier ();
10175 class_ext_size += sizeof (MonoClassExt);
10176 mono_image_unlock (klass->image);
10180 * mono_class_setup_interfaces:
10182 * Initialize class->interfaces/interfaces_count.
10183 * LOCKING: Acquires the loader lock.
10184 * This function can fail the type.
10187 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10189 int i, interface_count;
10190 MonoClass **interfaces;
10192 mono_error_init (error);
10194 if (klass->interfaces_inited)
10197 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10198 MonoType *args [1];
10200 /* generic IList, ICollection, IEnumerable */
10201 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10202 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10204 args [0] = &klass->element_class->byval_arg;
10205 interfaces [0] = mono_class_bind_generic_parameters (
10206 mono_defaults.generic_ilist_class, 1, args, FALSE);
10207 if (interface_count > 1)
10208 interfaces [1] = mono_class_bind_generic_parameters (
10209 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10210 } else if (klass->generic_class) {
10211 MonoClass *gklass = klass->generic_class->container_class;
10213 mono_class_setup_interfaces (gklass, error);
10214 if (!mono_error_ok (error)) {
10215 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10219 interface_count = gklass->interface_count;
10220 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10221 for (i = 0; i < interface_count; i++) {
10222 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10223 if (!mono_error_ok (error)) {
10224 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10229 interface_count = 0;
10233 mono_image_lock (klass->image);
10235 if (!klass->interfaces_inited) {
10236 klass->interface_count = interface_count;
10237 klass->interfaces = interfaces;
10239 mono_memory_barrier ();
10241 klass->interfaces_inited = TRUE;
10244 mono_image_unlock (klass->image);
10248 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10250 MonoClass *class = field->parent;
10251 MonoImage *image = class->image;
10252 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10253 int field_idx = field - class->fields;
10255 mono_error_init (error);
10258 MonoClassField *gfield = >d->fields [field_idx];
10259 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10260 if (!mono_error_ok (error)) {
10261 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10262 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10266 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10267 if (!mono_error_ok (error)) {
10268 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10269 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10274 guint32 cols [MONO_FIELD_SIZE];
10275 MonoGenericContainer *container = NULL;
10276 int idx = class->field.first + field_idx;
10278 /*FIXME, in theory we do not lazy load SRE fields*/
10279 g_assert (!image_is_dynamic (image));
10281 if (class->generic_container) {
10282 container = class->generic_container;
10284 container = gtd->generic_container;
10285 g_assert (container);
10288 /* class->field.first and idx points into the fieldptr table */
10289 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10291 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10292 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10293 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10297 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10299 mono_metadata_decode_value (sig, &sig);
10300 /* FIELD signature == 0x06 */
10301 g_assert (*sig == 0x06);
10302 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10304 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10309 mono_field_resolve_flags (MonoClassField *field)
10311 MonoClass *class = field->parent;
10312 MonoImage *image = class->image;
10313 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10314 int field_idx = field - class->fields;
10318 MonoClassField *gfield = >d->fields [field_idx];
10319 return mono_field_get_flags (gfield);
10321 int idx = class->field.first + field_idx;
10323 /*FIXME, in theory we do not lazy load SRE fields*/
10324 g_assert (!image_is_dynamic (image));
10326 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10331 * mono_class_setup_basic_field_info:
10332 * @class: The class to initialize
10334 * Initializes the class->fields array of fields.
10335 * Aquires the loader lock.
10338 mono_class_setup_basic_field_info_locking (MonoClass *class)
10340 mono_loader_lock ();
10341 mono_class_setup_basic_field_info (class);
10342 mono_loader_unlock ();
10346 * mono_class_get_fields_lazy:
10347 * @klass: the MonoClass to act on
10349 * This routine is an iterator routine for retrieving the fields in a class.
10350 * Only minimal information about fields are loaded. Accessors must be used
10351 * for all MonoClassField returned.
10353 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10354 * iterate over all of the elements. When no more values are
10355 * available, the return value is NULL.
10357 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10360 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10362 MonoClassField* field;
10366 mono_class_setup_basic_field_info_locking (klass);
10367 if (!klass->fields)
10369 /* start from the first */
10370 if (klass->field.count) {
10371 return *iter = &klass->fields [0];
10379 if (field < &klass->fields [klass->field.count]) {
10380 return *iter = field;
10386 mono_class_full_name (MonoClass *klass)
10388 return mono_type_full_name (&klass->byval_arg);