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.
7423 * Obtains a MonoClass with a given namespace and a given name which
7424 * is located in the given MonoImage. The namespace and name
7425 * lookups are case insensitive.
7428 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7430 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7431 guint32 cols [MONO_TYPEDEF_SIZE];
7436 if (image_is_dynamic (image)) {
7438 FindUserData user_data;
7440 mono_image_lock (image);
7442 if (!image->name_cache)
7443 mono_image_init_name_cache (image);
7445 user_data.key = name_space;
7446 user_data.value = NULL;
7447 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7449 if (user_data.value) {
7450 GHashTable *nspace_table = (GHashTable*)user_data.value;
7452 user_data.key = name;
7453 user_data.value = NULL;
7455 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7457 if (user_data.value)
7458 token = GPOINTER_TO_UINT (user_data.value);
7461 mono_image_unlock (image);
7464 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7470 /* add a cache if needed */
7471 for (i = 1; i <= t->rows; ++i) {
7472 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7473 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7475 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7476 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7478 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7480 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7481 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7482 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7483 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7489 return_nested_in (MonoClass *class, char *nested)
7492 char *s = strchr (nested, '/');
7493 gpointer iter = NULL;
7500 while ((found = mono_class_get_nested_types (class, &iter))) {
7501 if (strcmp (found->name, nested) == 0) {
7503 return return_nested_in (found, s);
7511 search_modules (MonoImage *image, const char *name_space, const char *name)
7513 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7514 MonoImage *file_image;
7519 * The EXPORTEDTYPES table only contains public types, so have to search the
7521 * Note: image->modules contains the contents of the MODULEREF table, while
7522 * the real module list is in the FILE table.
7524 for (i = 0; i < file_table->rows; i++) {
7525 guint32 cols [MONO_FILE_SIZE];
7526 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7527 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7530 file_image = mono_image_load_file_for_image (image, i + 1);
7532 class = mono_class_from_name (file_image, name_space, name);
7542 * mono_class_from_name:
7543 * @image: The MonoImage where the type is looked up in
7544 * @name_space: the type namespace
7545 * @name: the type short name.
7547 * Obtains a MonoClass with a given namespace and a given name which
7548 * is located in the given MonoImage.
7550 * To reference nested classes, use the "/" character as a separator.
7551 * For example use "Foo/Bar" to reference the class Bar that is nested
7552 * inside Foo, like this: "class Foo { class Bar {} }".
7555 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7557 GHashTable *nspace_table;
7558 MonoImage *loaded_image;
7565 if ((nested = strchr (name, '/'))) {
7566 int pos = nested - name;
7567 int len = strlen (name);
7570 memcpy (buf, name, len + 1);
7572 nested = buf + pos + 1;
7576 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7577 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7578 gboolean res = get_class_from_name (image, name_space, name, &class);
7581 class = search_modules (image, name_space, name);
7583 return class ? return_nested_in (class, nested) : NULL;
7589 mono_image_lock (image);
7591 if (!image->name_cache)
7592 mono_image_init_name_cache (image);
7594 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7597 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7599 mono_image_unlock (image);
7601 if (!token && image_is_dynamic (image) && image->modules) {
7602 /* Search modules as well */
7603 for (i = 0; i < image->module_count; ++i) {
7604 MonoImage *module = image->modules [i];
7606 class = mono_class_from_name (module, name_space, name);
7613 class = search_modules (image, name_space, name);
7621 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7622 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7623 guint32 cols [MONO_EXP_TYPE_SIZE];
7626 idx = mono_metadata_token_index (token);
7628 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7630 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7631 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7632 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7635 class = mono_class_from_name (loaded_image, name_space, name);
7637 return return_nested_in (class, nested);
7639 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7640 guint32 assembly_idx;
7642 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7644 mono_assembly_load_reference (image, assembly_idx - 1);
7645 g_assert (image->references [assembly_idx - 1]);
7646 if (image->references [assembly_idx - 1] == (gpointer)-1)
7649 /* FIXME: Cycle detection */
7650 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7652 g_error ("not yet implemented");
7656 token = MONO_TOKEN_TYPE_DEF | token;
7658 class = mono_class_get (image, token);
7660 return return_nested_in (class, nested);
7665 * mono_class_is_subclass_of:
7666 * @klass: class to probe if it is a subclass of another one
7667 * @klassc: the class we suspect is the base class
7668 * @check_interfaces: whether we should perform interface checks
7670 * This method determines whether @klass is a subclass of @klassc.
7672 * If the @check_interfaces flag is set, then if @klassc is an interface
7673 * this method return true if the @klass implements the interface or
7674 * if @klass is an interface, if one of its base classes is @klass.
7676 * If @check_interfaces is false then, then if @klass is not an interface
7677 * then it returns true if the @klass is a subclass of @klassc.
7679 * if @klass is an interface and @klassc is System.Object, then this function
7684 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7685 gboolean check_interfaces)
7687 /*FIXME test for interfaces with variant generic arguments*/
7689 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7690 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7692 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7695 for (i = 0; i < klass->interface_count; i ++) {
7696 MonoClass *ic = klass->interfaces [i];
7701 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7706 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7709 if (klassc == mono_defaults.object_class)
7716 mono_type_is_generic_argument (MonoType *type)
7718 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7722 mono_class_has_variant_generic_params (MonoClass *klass)
7725 MonoGenericContainer *container;
7727 if (!klass->generic_class)
7730 container = klass->generic_class->container_class->generic_container;
7732 for (i = 0; i < container->type_argc; ++i)
7733 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7740 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7742 if (target == candidate)
7745 if (check_for_reference_conv &&
7746 mono_type_is_generic_argument (&target->byval_arg) &&
7747 mono_type_is_generic_argument (&candidate->byval_arg)) {
7748 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7749 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7751 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7754 if (!mono_class_is_assignable_from (target, candidate))
7760 * @container the generic container from the GTD
7761 * @klass: the class to be assigned to
7762 * @oklass: the source class
7764 * Both klass and oklass must be instances of the same generic interface.
7765 * Return true if @klass can be assigned to a @klass variable
7768 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7771 MonoType **klass_argv, **oklass_argv;
7772 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7773 MonoGenericContainer *container = klass_gtd->generic_container;
7775 if (klass == oklass)
7778 /*Viable candidates are instances of the same generic interface*/
7779 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7782 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7783 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7785 for (j = 0; j < container->type_argc; ++j) {
7786 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7787 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7789 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7793 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7794 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7796 if (param1_class != param2_class) {
7797 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7798 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7800 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7801 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7811 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7813 MonoGenericParam *gparam, *ogparam;
7814 MonoGenericParamInfo *tinfo, *cinfo;
7815 MonoClass **candidate_class;
7816 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7819 if (target == candidate)
7821 if (target->byval_arg.type != candidate->byval_arg.type)
7824 gparam = target->byval_arg.data.generic_param;
7825 ogparam = candidate->byval_arg.data.generic_param;
7826 tinfo = mono_generic_param_info (gparam);
7827 cinfo = mono_generic_param_info (ogparam);
7829 class_constraint_satisfied = FALSE;
7830 valuetype_constraint_satisfied = FALSE;
7832 /*candidate must have a super set of target's special constraints*/
7833 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7834 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7836 if (cinfo->constraints) {
7837 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7838 MonoClass *cc = *candidate_class;
7840 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7841 class_constraint_satisfied = TRUE;
7842 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7843 valuetype_constraint_satisfied = TRUE;
7846 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7847 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7849 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7851 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7853 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7854 valuetype_constraint_satisfied)) {
7859 /*candidate type constraints must be a superset of target's*/
7860 if (tinfo->constraints) {
7861 MonoClass **target_class;
7862 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7863 MonoClass *tc = *target_class;
7866 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7867 * check it's constraints since it satisfy the constraint by itself.
7869 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7872 if (!cinfo->constraints)
7875 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7876 MonoClass *cc = *candidate_class;
7878 if (mono_class_is_assignable_from (tc, cc))
7882 * This happens when we have the following:
7884 * Bar<K> where K : IFace
7885 * Foo<T, U> where T : U where U : IFace
7887 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7890 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7891 if (mono_gparam_is_assignable_from (target, cc))
7895 if (!*candidate_class)
7900 /*candidate itself must have a constraint that satisfy target*/
7901 if (cinfo->constraints) {
7902 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7903 MonoClass *cc = *candidate_class;
7904 if (mono_class_is_assignable_from (target, cc))
7912 * mono_class_is_assignable_from:
7913 * @klass: the class to be assigned to
7914 * @oklass: the source class
7916 * Return: true if an instance of object oklass can be assigned to an
7917 * instance of object @klass
7920 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7922 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7924 mono_class_init (klass);
7926 if (!oklass->inited)
7927 mono_class_init (oklass);
7929 if (klass->exception_type || oklass->exception_type)
7932 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7933 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7935 return mono_gparam_is_assignable_from (klass, oklass);
7938 if (MONO_CLASS_IS_INTERFACE (klass)) {
7939 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7940 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7941 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7945 for (i = 0; constraints [i]; ++i) {
7946 if (mono_class_is_assignable_from (klass, constraints [i]))
7954 /* interface_offsets might not be set for dynamic classes */
7955 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7957 * oklass might be a generic type parameter but they have
7958 * interface_offsets set.
7960 return mono_reflection_call_is_assignable_to (oklass, klass);
7961 if (!oklass->interface_bitmap)
7962 /* Happens with generic instances of not-yet created dynamic types */
7964 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7967 if (mono_class_has_variant_generic_params (klass)) {
7970 mono_class_setup_interfaces (oklass, &error);
7971 if (!mono_error_ok (&error)) {
7972 mono_error_cleanup (&error);
7976 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7977 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7978 MonoClass *iface = oklass->interfaces_packed [i];
7980 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7985 } else if (klass->delegate) {
7986 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7988 }else if (klass->rank) {
7989 MonoClass *eclass, *eoclass;
7991 if (oklass->rank != klass->rank)
7994 /* vectors vs. one dimensional arrays */
7995 if (oklass->byval_arg.type != klass->byval_arg.type)
7998 eclass = klass->cast_class;
7999 eoclass = oklass->cast_class;
8002 * a is b does not imply a[] is b[] when a is a valuetype, and
8003 * b is a reference type.
8006 if (eoclass->valuetype) {
8007 if ((eclass == mono_defaults.enum_class) ||
8008 (eclass == mono_defaults.enum_class->parent) ||
8009 (eclass == mono_defaults.object_class))
8013 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8014 } else if (mono_class_is_nullable (klass)) {
8015 if (mono_class_is_nullable (oklass))
8016 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8018 return mono_class_is_assignable_from (klass->cast_class, oklass);
8019 } else if (klass == mono_defaults.object_class)
8022 return mono_class_has_parent (oklass, klass);
8025 /*Check if @oklass is variant compatible with @klass.*/
8027 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8030 MonoType **klass_argv, **oklass_argv;
8031 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8032 MonoGenericContainer *container = klass_gtd->generic_container;
8034 /*Viable candidates are instances of the same generic interface*/
8035 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8038 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8039 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8041 for (j = 0; j < container->type_argc; ++j) {
8042 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8043 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8045 if (param1_class->valuetype != param2_class->valuetype)
8049 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8050 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8052 if (param1_class != param2_class) {
8053 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8054 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8056 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8057 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8065 /*Check if @candidate implements the interface @target*/
8067 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8071 gboolean is_variant = mono_class_has_variant_generic_params (target);
8073 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8074 if (mono_class_is_variant_compatible_slow (target, candidate))
8079 if (candidate == target)
8082 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8083 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8084 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8086 if (tb && tb->interfaces) {
8087 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8088 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8089 MonoClass *iface_class;
8091 /* we can't realize the type here since it can do pretty much anything. */
8094 iface_class = mono_class_from_mono_type (iface->type);
8095 if (iface_class == target)
8097 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8099 if (mono_class_implement_interface_slow (target, iface_class))
8104 /*setup_interfaces don't mono_class_init anything*/
8105 /*FIXME this doesn't handle primitive type arrays.
8106 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8107 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8109 mono_class_setup_interfaces (candidate, &error);
8110 if (!mono_error_ok (&error)) {
8111 mono_error_cleanup (&error);
8115 for (i = 0; i < candidate->interface_count; ++i) {
8116 if (candidate->interfaces [i] == target)
8119 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8122 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8126 candidate = candidate->parent;
8127 } while (candidate);
8133 * Check if @oklass can be assigned to @klass.
8134 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8137 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8139 if (candidate == target)
8141 if (target == mono_defaults.object_class)
8144 if (mono_class_has_parent (candidate, target))
8147 /*If target is not an interface there is no need to check them.*/
8148 if (MONO_CLASS_IS_INTERFACE (target))
8149 return mono_class_implement_interface_slow (target, candidate);
8151 if (target->delegate && mono_class_has_variant_generic_params (target))
8152 return mono_class_is_variant_compatible (target, candidate, FALSE);
8155 MonoClass *eclass, *eoclass;
8157 if (target->rank != candidate->rank)
8160 /* vectors vs. one dimensional arrays */
8161 if (target->byval_arg.type != candidate->byval_arg.type)
8164 eclass = target->cast_class;
8165 eoclass = candidate->cast_class;
8168 * a is b does not imply a[] is b[] when a is a valuetype, and
8169 * b is a reference type.
8172 if (eoclass->valuetype) {
8173 if ((eclass == mono_defaults.enum_class) ||
8174 (eclass == mono_defaults.enum_class->parent) ||
8175 (eclass == mono_defaults.object_class))
8179 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8181 /*FIXME properly handle nullables */
8182 /*FIXME properly handle (M)VAR */
8187 * mono_class_get_cctor:
8188 * @klass: A MonoClass pointer
8190 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8193 mono_class_get_cctor (MonoClass *klass)
8195 MonoCachedClassInfo cached_info;
8197 if (image_is_dynamic (klass->image)) {
8199 * has_cctor is not set for these classes because mono_class_init () is
8202 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8205 if (!klass->has_cctor)
8208 if (mono_class_get_cached_class_info (klass, &cached_info))
8209 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8211 if (klass->generic_class && !klass->methods)
8212 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8214 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8218 * mono_class_get_finalizer:
8219 * @klass: The MonoClass pointer
8221 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8224 mono_class_get_finalizer (MonoClass *klass)
8226 MonoCachedClassInfo cached_info;
8229 mono_class_init (klass);
8230 if (!mono_class_has_finalizer (klass))
8233 if (mono_class_get_cached_class_info (klass, &cached_info))
8234 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8236 mono_class_setup_vtable (klass);
8237 return klass->vtable [finalize_slot];
8242 * mono_class_needs_cctor_run:
8243 * @klass: the MonoClass pointer
8244 * @caller: a MonoMethod describing the caller
8246 * Determines whenever the class has a static constructor and whenever it
8247 * needs to be called when executing CALLER.
8250 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8254 method = mono_class_get_cctor (klass);
8256 return (method == caller) ? FALSE : TRUE;
8262 * mono_class_array_element_size:
8265 * Returns: the number of bytes an element of type @klass
8266 * uses when stored into an array.
8269 mono_class_array_element_size (MonoClass *klass)
8271 MonoType *type = &klass->byval_arg;
8274 switch (type->type) {
8277 case MONO_TYPE_BOOLEAN:
8281 case MONO_TYPE_CHAR:
8290 case MONO_TYPE_CLASS:
8291 case MONO_TYPE_STRING:
8292 case MONO_TYPE_OBJECT:
8293 case MONO_TYPE_SZARRAY:
8294 case MONO_TYPE_ARRAY:
8296 case MONO_TYPE_MVAR:
8297 return sizeof (gpointer);
8302 case MONO_TYPE_VALUETYPE:
8303 if (type->data.klass->enumtype) {
8304 type = mono_class_enum_basetype (type->data.klass);
8305 klass = klass->element_class;
8308 return mono_class_instance_size (klass) - sizeof (MonoObject);
8309 case MONO_TYPE_GENERICINST:
8310 type = &type->data.generic_class->container_class->byval_arg;
8313 case MONO_TYPE_VOID:
8317 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8323 * mono_array_element_size:
8324 * @ac: pointer to a #MonoArrayClass
8326 * Returns: the size of single array element.
8329 mono_array_element_size (MonoClass *ac)
8331 g_assert (ac->rank);
8332 return ac->sizes.element_size;
8336 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8337 MonoGenericContext *context)
8339 if (image_is_dynamic (image)) {
8340 MonoClass *tmp_handle_class;
8341 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8343 g_assert (tmp_handle_class);
8345 *handle_class = tmp_handle_class;
8347 if (tmp_handle_class == mono_defaults.typehandle_class)
8348 return &((MonoClass*)obj)->byval_arg;
8353 switch (token & 0xff000000) {
8354 case MONO_TOKEN_TYPE_DEF:
8355 case MONO_TOKEN_TYPE_REF:
8356 case MONO_TOKEN_TYPE_SPEC: {
8360 *handle_class = mono_defaults.typehandle_class;
8361 type = mono_type_get_checked (image, token, context, &error);
8363 mono_loader_set_error_from_mono_error (&error);
8364 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8367 mono_class_init (mono_class_from_mono_type (type));
8368 /* We return a MonoType* as handle */
8371 case MONO_TOKEN_FIELD_DEF: {
8374 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8378 *handle_class = mono_defaults.fieldhandle_class;
8379 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8381 mono_loader_set_error_from_mono_error (&error);
8382 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8385 mono_class_init (class);
8386 return mono_class_get_field (class, token);
8388 case MONO_TOKEN_METHOD_DEF:
8389 case MONO_TOKEN_METHOD_SPEC: {
8391 meth = mono_get_method_full (image, token, NULL, context);
8393 *handle_class = mono_defaults.methodhandle_class;
8396 case MONO_TOKEN_MEMBER_REF: {
8397 guint32 cols [MONO_MEMBERREF_SIZE];
8399 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8400 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8401 mono_metadata_decode_blob_size (sig, &sig);
8402 if (*sig == 0x6) { /* it's a field */
8404 MonoClassField *field;
8405 field = mono_field_from_token (image, token, &klass, context);
8407 *handle_class = mono_defaults.fieldhandle_class;
8411 meth = mono_get_method_full (image, token, NULL, context);
8413 *handle_class = mono_defaults.methodhandle_class;
8418 g_warning ("Unknown token 0x%08x in ldtoken", token);
8425 * This function might need to call runtime functions so it can't be part
8426 * of the metadata library.
8428 static MonoLookupDynamicToken lookup_dynamic = NULL;
8431 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8433 lookup_dynamic = func;
8437 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8439 MonoClass *handle_class;
8441 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8445 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8447 return lookup_dynamic (image, token, valid_token, handle_class, context);
8450 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8453 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8455 get_cached_class_info = func;
8459 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8461 if (!get_cached_class_info)
8464 return get_cached_class_info (klass, res);
8468 mono_install_get_class_from_name (MonoGetClassFromName func)
8470 get_class_from_name = func;
8474 mono_class_get_image (MonoClass *klass)
8476 return klass->image;
8480 * mono_class_get_element_class:
8481 * @klass: the MonoClass to act on
8483 * Returns: the element class of an array or an enumeration.
8486 mono_class_get_element_class (MonoClass *klass)
8488 return klass->element_class;
8492 * mono_class_is_valuetype:
8493 * @klass: the MonoClass to act on
8495 * Returns: true if the MonoClass represents a ValueType.
8498 mono_class_is_valuetype (MonoClass *klass)
8500 return klass->valuetype;
8504 * mono_class_is_enum:
8505 * @klass: the MonoClass to act on
8507 * Returns: true if the MonoClass represents an enumeration.
8510 mono_class_is_enum (MonoClass *klass)
8512 return klass->enumtype;
8516 * mono_class_enum_basetype:
8517 * @klass: the MonoClass to act on
8519 * Returns: the underlying type representation for an enumeration.
8522 mono_class_enum_basetype (MonoClass *klass)
8524 if (klass->element_class == klass)
8525 /* SRE or broken types */
8528 return &klass->element_class->byval_arg;
8532 * mono_class_get_parent
8533 * @klass: the MonoClass to act on
8535 * Returns: the parent class for this class.
8538 mono_class_get_parent (MonoClass *klass)
8540 return klass->parent;
8544 * mono_class_get_nesting_type;
8545 * @klass: the MonoClass to act on
8547 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8550 mono_class_get_nesting_type (MonoClass *klass)
8552 return klass->nested_in;
8556 * mono_class_get_rank:
8557 * @klass: the MonoClass to act on
8559 * Returns: the rank for the array (the number of dimensions).
8562 mono_class_get_rank (MonoClass *klass)
8568 * mono_class_get_flags:
8569 * @klass: the MonoClass to act on
8571 * The type flags from the TypeDef table from the metadata.
8572 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8575 * Returns: the flags from the TypeDef table.
8578 mono_class_get_flags (MonoClass *klass)
8580 return klass->flags;
8584 * mono_class_get_name
8585 * @klass: the MonoClass to act on
8587 * Returns: the name of the class.
8590 mono_class_get_name (MonoClass *klass)
8596 * mono_class_get_namespace:
8597 * @klass: the MonoClass to act on
8599 * Returns: the namespace of the class.
8602 mono_class_get_namespace (MonoClass *klass)
8604 return klass->name_space;
8608 * mono_class_get_type:
8609 * @klass: the MonoClass to act on
8611 * This method returns the internal Type representation for the class.
8613 * Returns: the MonoType from the class.
8616 mono_class_get_type (MonoClass *klass)
8618 return &klass->byval_arg;
8622 * mono_class_get_type_token
8623 * @klass: the MonoClass to act on
8625 * This method returns type token for the class.
8627 * Returns: the type token for the class.
8630 mono_class_get_type_token (MonoClass *klass)
8632 return klass->type_token;
8636 * mono_class_get_byref_type:
8637 * @klass: the MonoClass to act on
8642 mono_class_get_byref_type (MonoClass *klass)
8644 return &klass->this_arg;
8648 * mono_class_num_fields:
8649 * @klass: the MonoClass to act on
8651 * Returns: the number of static and instance fields in the class.
8654 mono_class_num_fields (MonoClass *klass)
8656 return klass->field.count;
8660 * mono_class_num_methods:
8661 * @klass: the MonoClass to act on
8663 * Returns: the number of methods in the class.
8666 mono_class_num_methods (MonoClass *klass)
8668 return klass->method.count;
8672 * mono_class_num_properties
8673 * @klass: the MonoClass to act on
8675 * Returns: the number of properties in the class.
8678 mono_class_num_properties (MonoClass *klass)
8680 mono_class_setup_properties (klass);
8682 return klass->ext->property.count;
8686 * mono_class_num_events:
8687 * @klass: the MonoClass to act on
8689 * Returns: the number of events in the class.
8692 mono_class_num_events (MonoClass *klass)
8694 mono_class_setup_events (klass);
8696 return klass->ext->event.count;
8700 * mono_class_get_fields:
8701 * @klass: the MonoClass to act on
8703 * This routine is an iterator routine for retrieving the fields in a class.
8705 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8706 * iterate over all of the elements. When no more values are
8707 * available, the return value is NULL.
8709 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8712 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8714 MonoClassField* field;
8718 mono_class_setup_fields_locking (klass);
8719 if (klass->exception_type)
8721 /* start from the first */
8722 if (klass->field.count) {
8723 return *iter = &klass->fields [0];
8731 if (field < &klass->fields [klass->field.count]) {
8732 return *iter = field;
8738 * mono_class_get_methods
8739 * @klass: the MonoClass to act on
8741 * This routine is an iterator routine for retrieving the fields in a class.
8743 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8744 * iterate over all of the elements. When no more values are
8745 * available, the return value is NULL.
8747 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8750 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8752 MonoMethod** method;
8756 mono_class_setup_methods (klass);
8759 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8760 * FIXME we should better report this error to the caller
8762 if (!klass->methods)
8764 /* start from the first */
8765 if (klass->method.count) {
8766 *iter = &klass->methods [0];
8767 return klass->methods [0];
8775 if (method < &klass->methods [klass->method.count]) {
8783 * mono_class_get_virtual_methods:
8785 * Iterate over the virtual methods of KLASS.
8787 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8790 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8792 MonoMethod** method;
8795 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8797 mono_class_setup_methods (klass);
8799 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8800 * FIXME we should better report this error to the caller
8802 if (!klass->methods)
8804 /* start from the first */
8805 method = &klass->methods [0];
8810 while (method < &klass->methods [klass->method.count]) {
8811 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8815 if (method < &klass->methods [klass->method.count]) {
8822 /* Search directly in metadata to avoid calling setup_methods () */
8823 MonoMethod *res = NULL;
8829 start_index = GPOINTER_TO_UINT (*iter);
8832 for (i = start_index; i < klass->method.count; ++i) {
8835 /* class->method.first points into the methodptr table */
8836 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8838 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8842 if (i < klass->method.count) {
8843 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8844 /* Add 1 here so the if (*iter) check fails */
8845 *iter = GUINT_TO_POINTER (i + 1);
8854 * mono_class_get_properties:
8855 * @klass: the MonoClass to act on
8857 * This routine is an iterator routine for retrieving the properties in a class.
8859 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8860 * iterate over all of the elements. When no more values are
8861 * available, the return value is NULL.
8863 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8866 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8868 MonoProperty* property;
8872 mono_class_setup_properties (klass);
8873 /* start from the first */
8874 if (klass->ext->property.count) {
8875 return *iter = &klass->ext->properties [0];
8883 if (property < &klass->ext->properties [klass->ext->property.count]) {
8884 return *iter = property;
8890 * mono_class_get_events:
8891 * @klass: the MonoClass to act on
8893 * This routine is an iterator routine for retrieving the properties in a class.
8895 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8896 * iterate over all of the elements. When no more values are
8897 * available, the return value is NULL.
8899 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8902 mono_class_get_events (MonoClass* klass, gpointer *iter)
8908 mono_class_setup_events (klass);
8909 /* start from the first */
8910 if (klass->ext->event.count) {
8911 return *iter = &klass->ext->events [0];
8919 if (event < &klass->ext->events [klass->ext->event.count]) {
8920 return *iter = event;
8926 * mono_class_get_interfaces
8927 * @klass: the MonoClass to act on
8929 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8931 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8932 * iterate over all of the elements. When no more values are
8933 * available, the return value is NULL.
8935 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8938 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8946 mono_class_init (klass);
8947 if (!klass->interfaces_inited) {
8948 mono_class_setup_interfaces (klass, &error);
8949 if (!mono_error_ok (&error)) {
8950 mono_error_cleanup (&error);
8954 /* start from the first */
8955 if (klass->interface_count) {
8956 *iter = &klass->interfaces [0];
8957 return klass->interfaces [0];
8965 if (iface < &klass->interfaces [klass->interface_count]) {
8973 setup_nested_types (MonoClass *klass)
8976 GList *classes, *nested_classes, *l;
8979 if (klass->nested_classes_inited)
8982 if (!klass->type_token)
8983 klass->nested_classes_inited = TRUE;
8985 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8989 guint32 cols [MONO_NESTED_CLASS_SIZE];
8990 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8991 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8992 if (!mono_error_ok (&error)) {
8993 /*FIXME don't swallow the error message*/
8994 mono_error_cleanup (&error);
8996 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9000 classes = g_list_prepend (classes, nclass);
9002 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9005 mono_class_alloc_ext (klass);
9007 nested_classes = NULL;
9008 for (l = classes; l; l = l->next)
9009 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9010 g_list_free (classes);
9012 mono_image_lock (klass->image);
9014 mono_memory_barrier ();
9015 if (!klass->nested_classes_inited) {
9016 klass->ext->nested_classes = nested_classes;
9017 mono_memory_barrier ();
9018 klass->nested_classes_inited = TRUE;
9021 mono_image_unlock (klass->image);
9025 * mono_class_get_nested_types
9026 * @klass: the MonoClass to act on
9028 * This routine is an iterator routine for retrieving the nested types of a class.
9029 * This works only if @klass is non-generic, or a generic type definition.
9031 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9032 * iterate over all of the elements. When no more values are
9033 * available, the return value is NULL.
9035 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9038 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9044 if (!klass->nested_classes_inited)
9045 setup_nested_types (klass);
9048 /* start from the first */
9049 if (klass->ext && klass->ext->nested_classes) {
9050 *iter = klass->ext->nested_classes;
9051 return klass->ext->nested_classes->data;
9053 /* no nested types */
9068 * mono_class_is_delegate
9069 * @klass: the MonoClass to act on
9071 * Returns: true if the MonoClass represents a System.Delegate.
9074 mono_class_is_delegate (MonoClass *klass)
9076 return klass->delegate;
9080 * mono_class_implements_interface
9081 * @klass: The MonoClass to act on
9082 * @interface: The interface to check if @klass implements.
9084 * Returns: true if @klass implements @interface.
9087 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9089 return mono_class_is_assignable_from (iface, klass);
9093 * mono_field_get_name:
9094 * @field: the MonoClassField to act on
9096 * Returns: the name of the field.
9099 mono_field_get_name (MonoClassField *field)
9105 * mono_field_get_type:
9106 * @field: the MonoClassField to act on
9108 * Returns: MonoType of the field.
9111 mono_field_get_type (MonoClassField *field)
9114 MonoType *type = mono_field_get_type_checked (field, &error);
9115 if (!mono_error_ok (&error)) {
9116 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9117 mono_error_cleanup (&error);
9124 * mono_field_get_type_checked:
9125 * @field: the MonoClassField to act on
9126 * @error: used to return any erro found while retrieving @field type
9128 * Returns: MonoType of the field.
9131 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9133 mono_error_init (error);
9135 mono_field_resolve_type (field, error);
9140 * mono_field_get_parent:
9141 * @field: the MonoClassField to act on
9143 * Returns: MonoClass where the field was defined.
9146 mono_field_get_parent (MonoClassField *field)
9148 return field->parent;
9152 * mono_field_get_flags;
9153 * @field: the MonoClassField to act on
9155 * The metadata flags for a field are encoded using the
9156 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9158 * Returns: the flags for the field.
9161 mono_field_get_flags (MonoClassField *field)
9164 return mono_field_resolve_flags (field);
9165 return field->type->attrs;
9169 * mono_field_get_offset;
9170 * @field: the MonoClassField to act on
9172 * Returns: the field offset.
9175 mono_field_get_offset (MonoClassField *field)
9177 return field->offset;
9181 mono_field_get_rva (MonoClassField *field)
9185 MonoClass *klass = field->parent;
9186 MonoFieldDefaultValue *field_def_values;
9188 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9190 if (!klass->ext || !klass->ext->field_def_values) {
9191 mono_class_alloc_ext (klass);
9193 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9195 mono_image_lock (klass->image);
9196 if (!klass->ext->field_def_values)
9197 klass->ext->field_def_values = field_def_values;
9198 mono_image_unlock (klass->image);
9201 field_index = mono_field_get_index (field);
9203 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9204 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9206 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9207 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9210 return klass->ext->field_def_values [field_index].data;
9214 * mono_field_get_data;
9215 * @field: the MonoClassField to act on
9217 * Returns: pointer to the metadata constant value or to the field
9218 * data if it has an RVA flag.
9221 mono_field_get_data (MonoClassField *field)
9223 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9224 MonoTypeEnum def_type;
9226 return mono_class_get_field_default_value (field, &def_type);
9227 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9228 return mono_field_get_rva (field);
9235 * mono_property_get_name:
9236 * @prop: the MonoProperty to act on
9238 * Returns: the name of the property
9241 mono_property_get_name (MonoProperty *prop)
9247 * mono_property_get_set_method
9248 * @prop: the MonoProperty to act on.
9250 * Returns: the setter method of the property (A MonoMethod)
9253 mono_property_get_set_method (MonoProperty *prop)
9259 * mono_property_get_get_method
9260 * @prop: the MonoProperty to act on.
9262 * Returns: the setter method of the property (A MonoMethod)
9265 mono_property_get_get_method (MonoProperty *prop)
9271 * mono_property_get_parent:
9272 * @prop: the MonoProperty to act on.
9274 * Returns: the MonoClass where the property was defined.
9277 mono_property_get_parent (MonoProperty *prop)
9279 return prop->parent;
9283 * mono_property_get_flags:
9284 * @prop: the MonoProperty to act on.
9286 * The metadata flags for a property are encoded using the
9287 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9289 * Returns: the flags for the property.
9292 mono_property_get_flags (MonoProperty *prop)
9298 * mono_event_get_name:
9299 * @event: the MonoEvent to act on
9301 * Returns: the name of the event.
9304 mono_event_get_name (MonoEvent *event)
9310 * mono_event_get_add_method:
9311 * @event: The MonoEvent to act on.
9313 * Returns: the @add' method for the event (a MonoMethod).
9316 mono_event_get_add_method (MonoEvent *event)
9322 * mono_event_get_remove_method:
9323 * @event: The MonoEvent to act on.
9325 * Returns: the @remove method for the event (a MonoMethod).
9328 mono_event_get_remove_method (MonoEvent *event)
9330 return event->remove;
9334 * mono_event_get_raise_method:
9335 * @event: The MonoEvent to act on.
9337 * Returns: the @raise method for the event (a MonoMethod).
9340 mono_event_get_raise_method (MonoEvent *event)
9342 return event->raise;
9346 * mono_event_get_parent:
9347 * @event: the MonoEvent to act on.
9349 * Returns: the MonoClass where the event is defined.
9352 mono_event_get_parent (MonoEvent *event)
9354 return event->parent;
9358 * mono_event_get_flags
9359 * @event: the MonoEvent to act on.
9361 * The metadata flags for an event are encoded using the
9362 * EVENT_* constants. See the tabledefs.h file for details.
9364 * Returns: the flags for the event.
9367 mono_event_get_flags (MonoEvent *event)
9369 return event->attrs;
9373 * mono_class_get_method_from_name:
9374 * @klass: where to look for the method
9375 * @name: name of the method
9376 * @param_count: number of parameters. -1 for any number.
9378 * Obtains a MonoMethod with a given name and number of parameters.
9379 * It only works if there are no multiple signatures for any given method name.
9382 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9384 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9388 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9390 MonoMethod *res = NULL;
9393 /* Search directly in the metadata to avoid calling setup_methods () */
9394 for (i = 0; i < klass->method.count; ++i) {
9395 guint32 cols [MONO_METHOD_SIZE];
9397 MonoMethodSignature *sig;
9399 /* class->method.first points into the methodptr table */
9400 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9402 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9403 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9404 if (param_count == -1) {
9408 sig = mono_method_signature (method);
9409 if (sig && sig->param_count == param_count) {
9420 * mono_class_get_method_from_name_flags:
9421 * @klass: where to look for the method
9422 * @name_space: name of the method
9423 * @param_count: number of parameters. -1 for any number.
9424 * @flags: flags which must be set in the method
9426 * Obtains a MonoMethod with a given name and number of parameters.
9427 * It only works if there are no multiple signatures for any given method name.
9430 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9432 MonoMethod *res = NULL;
9435 mono_class_init (klass);
9437 if (klass->generic_class && !klass->methods) {
9438 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9440 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9444 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9445 mono_class_setup_methods (klass);
9447 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9448 See mono/tests/array_load_exception.il
9449 FIXME we should better report this error to the caller
9451 if (!klass->methods)
9453 for (i = 0; i < klass->method.count; ++i) {
9454 MonoMethod *method = klass->methods [i];
9456 if (method->name[0] == name [0] &&
9457 !strcmp (name, method->name) &&
9458 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9459 ((method->flags & flags) == flags)) {
9466 res = find_method_in_metadata (klass, name, param_count, flags);
9473 * mono_class_set_failure:
9474 * @klass: class in which the failure was detected
9475 * @ex_type: the kind of exception/error to be thrown (later)
9476 * @ex_data: exception data (specific to each type of exception/error)
9478 * Keep a detected failure informations in the class for later processing.
9479 * Note that only the first failure is kept.
9481 * LOCKING: Acquires the loader lock.
9484 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9486 if (klass->exception_type)
9489 mono_loader_lock ();
9490 klass->exception_type = ex_type;
9492 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9493 mono_loader_unlock ();
9499 * mono_class_get_exception_data:
9501 * Return the exception_data property of KLASS.
9503 * LOCKING: Acquires the loader lock.
9506 mono_class_get_exception_data (MonoClass *klass)
9508 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9512 * mono_classes_init:
9514 * Initialize the resources used by this module.
9517 mono_classes_init (void)
9519 mono_mutex_init (&classes_mutex);
9521 mono_counters_register ("Inflated methods size",
9522 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9523 mono_counters_register ("Inflated classes",
9524 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9525 mono_counters_register ("Inflated classes size",
9526 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9527 mono_counters_register ("MonoClass size",
9528 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9529 mono_counters_register ("MonoClassExt size",
9530 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9534 * mono_classes_cleanup:
9536 * Free the resources used by this module.
9539 mono_classes_cleanup (void)
9541 if (global_interface_bitset)
9542 mono_bitset_free (global_interface_bitset);
9543 global_interface_bitset = NULL;
9544 mono_mutex_destroy (&classes_mutex);
9548 * mono_class_get_exception_for_failure:
9549 * @klass: class in which the failure was detected
9551 * Return a constructed MonoException than the caller can then throw
9552 * using mono_raise_exception - or NULL if no failure is present (or
9553 * doesn't result in an exception).
9556 mono_class_get_exception_for_failure (MonoClass *klass)
9558 gpointer exception_data = mono_class_get_exception_data (klass);
9560 switch (klass->exception_type) {
9561 #ifndef DISABLE_SECURITY
9562 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9563 MonoDomain *domain = mono_domain_get ();
9564 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9565 MonoMethod *method = exception_data;
9566 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9567 MonoObject *exc = NULL;
9571 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9572 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9573 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9575 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9576 return (MonoException*) exc;
9579 case MONO_EXCEPTION_TYPE_LOAD: {
9582 char *str = mono_type_get_full_name (klass);
9583 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9584 name = mono_string_new (mono_domain_get (), str);
9586 ex = mono_get_exception_type_load (name, astr);
9590 case MONO_EXCEPTION_MISSING_METHOD: {
9591 char *class_name = exception_data;
9592 char *assembly_name = class_name + strlen (class_name) + 1;
9594 return mono_get_exception_missing_method (class_name, assembly_name);
9596 case MONO_EXCEPTION_MISSING_FIELD: {
9597 char *class_name = exception_data;
9598 char *member_name = class_name + strlen (class_name) + 1;
9600 return mono_get_exception_missing_field (class_name, member_name);
9602 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9603 char *msg_format = exception_data;
9604 char *assembly_name = msg_format + strlen (msg_format) + 1;
9605 char *msg = g_strdup_printf (msg_format, assembly_name);
9608 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9614 case MONO_EXCEPTION_BAD_IMAGE: {
9615 return mono_get_exception_bad_image_format (exception_data);
9618 MonoLoaderError *error;
9621 error = mono_loader_get_last_error ();
9623 ex = mono_loader_error_prepare_exception (error);
9627 /* TODO - handle other class related failures */
9634 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9636 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9637 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9639 if (outer_klass == inner_klass)
9641 inner_klass = inner_klass->nested_in;
9642 } while (inner_klass);
9647 mono_class_get_generic_type_definition (MonoClass *klass)
9649 return klass->generic_class ? klass->generic_class->container_class : klass;
9653 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9655 * Generic instantiations are ignored for all super types of @klass.
9657 * Visibility checks ignoring generic instantiations.
9660 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9663 klass = mono_class_get_generic_type_definition (klass);
9664 parent = mono_class_get_generic_type_definition (parent);
9665 mono_class_setup_supertypes (klass);
9667 for (i = 0; i < klass->idepth; ++i) {
9668 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9674 * Subtype can only access parent members with family protection if the site object
9675 * is subclass of Subtype. For example:
9676 * class A { protected int x; }
9678 * void valid_access () {
9682 * void invalid_access () {
9689 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9691 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9694 if (context_klass == NULL)
9696 /*if access_klass is not member_klass context_klass must be type compat*/
9697 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9703 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9706 if (accessing == accessed)
9708 if (!accessed || !accessing)
9711 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9712 * anywhere so untrusted friends are not safe to access platform's code internals */
9713 if (mono_security_core_clr_enabled ()) {
9714 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9718 mono_assembly_load_friends (accessed);
9719 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9720 MonoAssemblyName *friend = tmp->data;
9721 /* Be conservative with checks */
9724 if (strcmp (accessing->aname.name, friend->name))
9726 if (friend->public_key_token [0]) {
9727 if (!accessing->aname.public_key_token [0])
9729 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9738 * If klass is a generic type or if it is derived from a generic type, return the
9739 * MonoClass of the generic definition
9740 * Returns NULL if not found
9743 get_generic_definition_class (MonoClass *klass)
9746 if (klass->generic_class && klass->generic_class->container_class)
9747 return klass->generic_class->container_class;
9748 klass = klass->parent;
9754 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9757 for (i = 0; i < ginst->type_argc; ++i) {
9758 MonoType *type = ginst->type_argv[i];
9759 switch (type->type) {
9760 case MONO_TYPE_SZARRAY:
9761 if (!can_access_type (access_klass, type->data.klass))
9764 case MONO_TYPE_ARRAY:
9765 if (!can_access_type (access_klass, type->data.array->eklass))
9769 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9772 case MONO_TYPE_CLASS:
9773 case MONO_TYPE_VALUETYPE:
9774 case MONO_TYPE_GENERICINST:
9775 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9783 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9787 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9790 if (access_klass->element_class && !access_klass->enumtype)
9791 access_klass = access_klass->element_class;
9793 if (member_klass->element_class && !member_klass->enumtype)
9794 member_klass = member_klass->element_class;
9796 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9798 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9801 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9804 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9807 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9810 /*Non nested type with nested visibility. We just fail it.*/
9811 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9814 switch (access_level) {
9815 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9816 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9818 case TYPE_ATTRIBUTE_PUBLIC:
9821 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9824 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9825 return is_nesting_type (member_klass, access_klass);
9827 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9828 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9830 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9831 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9833 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9834 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9835 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9837 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9838 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9839 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9844 /* FIXME: check visibility of type, too */
9846 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9848 MonoClass *member_generic_def;
9849 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9852 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9853 access_klass->generic_container) &&
9854 (member_generic_def = get_generic_definition_class (member_klass))) {
9855 MonoClass *access_container;
9857 if (access_klass->generic_container)
9858 access_container = access_klass;
9860 access_container = access_klass->generic_class->container_class;
9862 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9866 /* Partition I 8.5.3.2 */
9867 /* the access level values are the same for fields and methods */
9868 switch (access_level) {
9869 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9870 /* same compilation unit */
9871 return access_klass->image == member_klass->image;
9872 case FIELD_ATTRIBUTE_PRIVATE:
9873 return access_klass == member_klass;
9874 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9875 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9876 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9879 case FIELD_ATTRIBUTE_ASSEMBLY:
9880 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9881 case FIELD_ATTRIBUTE_FAMILY:
9882 if (is_valid_family_access (access_klass, member_klass, context_klass))
9885 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9886 if (is_valid_family_access (access_klass, member_klass, context_klass))
9888 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9889 case FIELD_ATTRIBUTE_PUBLIC:
9896 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9898 /* FIXME: check all overlapping fields */
9899 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9901 MonoClass *nested = method->klass->nested_in;
9903 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9906 nested = nested->nested_in;
9913 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9915 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9917 MonoClass *nested = method->klass->nested_in;
9919 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9922 nested = nested->nested_in;
9927 * with generics calls to explicit interface implementations can be expressed
9928 * directly: the method is private, but we must allow it. This may be opening
9929 * a hole or the generics code should handle this differently.
9930 * Maybe just ensure the interface type is public.
9932 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9938 * mono_method_can_access_method_full:
9939 * @method: The caller method
9940 * @called: The called method
9941 * @context_klass: The static type on stack of the owner @called object used
9943 * This function must be used with instance calls, as they have more strict family accessibility.
9944 * It can be used with static methods, but context_klass should be NULL.
9946 * Returns: TRUE if caller have proper visibility and acessibility to @called
9949 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9951 MonoClass *access_class = method->klass;
9952 MonoClass *member_class = called->klass;
9953 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9955 MonoClass *nested = access_class->nested_in;
9957 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9960 nested = nested->nested_in;
9967 can = can_access_type (access_class, member_class);
9969 MonoClass *nested = access_class->nested_in;
9971 can = can_access_type (nested, member_class);
9974 nested = nested->nested_in;
9981 if (called->is_inflated) {
9982 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9983 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9992 * mono_method_can_access_field_full:
9993 * @method: The caller method
9994 * @field: The accessed field
9995 * @context_klass: The static type on stack of the owner @field object used
9997 * This function must be used with instance fields, as they have more strict family accessibility.
9998 * It can be used with static fields, but context_klass should be NULL.
10000 * Returns: TRUE if caller have proper visibility and acessibility to @field
10003 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10005 MonoClass *access_class = method->klass;
10006 MonoClass *member_class = field->parent;
10007 /* FIXME: check all overlapping fields */
10008 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10010 MonoClass *nested = access_class->nested_in;
10012 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10015 nested = nested->nested_in;
10022 can = can_access_type (access_class, member_class);
10024 MonoClass *nested = access_class->nested_in;
10026 can = can_access_type (nested, member_class);
10029 nested = nested->nested_in;
10039 * mono_class_can_access_class:
10040 * @source_class: The source class
10041 * @target_class: The accessed class
10043 * This function returns is @target_class is visible to @source_class
10045 * Returns: TRUE if source have proper visibility and acessibility to target
10048 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10050 return can_access_type (source_class, target_class);
10054 * mono_type_is_valid_enum_basetype:
10055 * @type: The MonoType to check
10057 * Returns: TRUE if the type can be used as the basetype of an enum
10059 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10060 switch (type->type) {
10063 case MONO_TYPE_BOOLEAN:
10066 case MONO_TYPE_CHAR:
10079 * mono_class_is_valid_enum:
10080 * @klass: An enum class to be validated
10082 * This method verify the required properties an enum should have.
10084 * Returns: TRUE if the informed enum class is valid
10086 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10087 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10088 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10090 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10091 MonoClassField * field;
10092 gpointer iter = NULL;
10093 gboolean found_base_field = FALSE;
10095 g_assert (klass->enumtype);
10096 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10097 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10101 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10104 while ((field = mono_class_get_fields (klass, &iter))) {
10105 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10106 if (found_base_field)
10108 found_base_field = TRUE;
10109 if (!mono_type_is_valid_enum_basetype (field->type))
10114 if (!found_base_field)
10117 if (klass->method.count > 0)
10124 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10126 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10130 * mono_class_setup_interface_id:
10132 * Initializes MonoClass::interface_id if required.
10134 * LOCKING: Acquires the loader lock.
10137 mono_class_setup_interface_id (MonoClass *class)
10139 mono_loader_lock ();
10140 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10141 class->interface_id = mono_get_unique_iid (class);
10142 mono_loader_unlock ();
10146 * mono_class_alloc_ext:
10148 * Allocate klass->ext if not already done.
10151 mono_class_alloc_ext (MonoClass *klass)
10158 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10159 mono_image_lock (klass->image);
10160 mono_memory_barrier ();
10163 class_ext_size += sizeof (MonoClassExt);
10164 mono_image_unlock (klass->image);
10168 * mono_class_setup_interfaces:
10170 * Initialize class->interfaces/interfaces_count.
10171 * LOCKING: Acquires the loader lock.
10172 * This function can fail the type.
10175 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10177 int i, interface_count;
10178 MonoClass **interfaces;
10180 mono_error_init (error);
10182 if (klass->interfaces_inited)
10185 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10186 MonoType *args [1];
10188 /* generic IList, ICollection, IEnumerable */
10189 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10190 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10192 args [0] = &klass->element_class->byval_arg;
10193 interfaces [0] = mono_class_bind_generic_parameters (
10194 mono_defaults.generic_ilist_class, 1, args, FALSE);
10195 if (interface_count > 1)
10196 interfaces [1] = mono_class_bind_generic_parameters (
10197 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10198 } else if (klass->generic_class) {
10199 MonoClass *gklass = klass->generic_class->container_class;
10201 mono_class_setup_interfaces (gklass, error);
10202 if (!mono_error_ok (error)) {
10203 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10207 interface_count = gklass->interface_count;
10208 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10209 for (i = 0; i < interface_count; i++) {
10210 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10211 if (!mono_error_ok (error)) {
10212 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10217 interface_count = 0;
10221 mono_image_lock (klass->image);
10223 if (!klass->interfaces_inited) {
10224 klass->interface_count = interface_count;
10225 klass->interfaces = interfaces;
10227 mono_memory_barrier ();
10229 klass->interfaces_inited = TRUE;
10232 mono_image_unlock (klass->image);
10236 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10238 MonoClass *class = field->parent;
10239 MonoImage *image = class->image;
10240 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10241 int field_idx = field - class->fields;
10243 mono_error_init (error);
10246 MonoClassField *gfield = >d->fields [field_idx];
10247 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10248 if (!mono_error_ok (error)) {
10249 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10250 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10254 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10255 if (!mono_error_ok (error)) {
10256 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10257 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10262 guint32 cols [MONO_FIELD_SIZE];
10263 MonoGenericContainer *container = NULL;
10264 int idx = class->field.first + field_idx;
10266 /*FIXME, in theory we do not lazy load SRE fields*/
10267 g_assert (!image_is_dynamic (image));
10269 if (class->generic_container) {
10270 container = class->generic_container;
10272 container = gtd->generic_container;
10273 g_assert (container);
10276 /* class->field.first and idx points into the fieldptr table */
10277 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10279 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10280 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10281 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10285 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10287 mono_metadata_decode_value (sig, &sig);
10288 /* FIELD signature == 0x06 */
10289 g_assert (*sig == 0x06);
10290 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10292 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10297 mono_field_resolve_flags (MonoClassField *field)
10299 MonoClass *class = field->parent;
10300 MonoImage *image = class->image;
10301 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10302 int field_idx = field - class->fields;
10306 MonoClassField *gfield = >d->fields [field_idx];
10307 return mono_field_get_flags (gfield);
10309 int idx = class->field.first + field_idx;
10311 /*FIXME, in theory we do not lazy load SRE fields*/
10312 g_assert (!image_is_dynamic (image));
10314 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10319 * mono_class_setup_basic_field_info:
10320 * @class: The class to initialize
10322 * Initializes the class->fields array of fields.
10323 * Aquires the loader lock.
10326 mono_class_setup_basic_field_info_locking (MonoClass *class)
10328 mono_loader_lock ();
10329 mono_class_setup_basic_field_info (class);
10330 mono_loader_unlock ();
10334 * mono_class_get_fields_lazy:
10335 * @klass: the MonoClass to act on
10337 * This routine is an iterator routine for retrieving the fields in a class.
10338 * Only minimal information about fields are loaded. Accessors must be used
10339 * for all MonoClassField returned.
10341 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10342 * iterate over all of the elements. When no more values are
10343 * available, the return value is NULL.
10345 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10348 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10350 MonoClassField* field;
10354 mono_class_setup_basic_field_info_locking (klass);
10355 if (!klass->fields)
10357 /* start from the first */
10358 if (klass->field.count) {
10359 return *iter = &klass->fields [0];
10367 if (field < &klass->fields [klass->field.count]) {
10368 return *iter = field;
10374 mono_class_full_name (MonoClass *klass)
10376 return mono_type_full_name (&klass->byval_arg);