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)
1264 MonoGenericContainer *container = NULL;
1265 MonoImage *m = class->image;
1266 const int top = class->field.count;
1269 g_assert (class->enumtype);
1271 if (class->generic_container)
1272 container = class->generic_container;
1273 else if (class->generic_class) {
1274 MonoClass *gklass = class->generic_class->container_class;
1276 container = gklass->generic_container;
1277 g_assert (container);
1281 * Fetch all the field information.
1283 for (i = 0; i < top; i++){
1285 guint32 cols [MONO_FIELD_SIZE];
1286 int idx = class->field.first + i;
1289 /* class->field.first and idx points into the fieldptr table */
1290 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1292 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1295 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1298 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1299 mono_metadata_decode_value (sig, &sig);
1300 /* FIELD signature == 0x06 */
1304 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1307 if (class->generic_class) {
1308 //FIXME do we leak here?
1309 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1310 ftype->attrs = cols [MONO_FIELD_FLAGS];
1320 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1323 mono_type_has_exceptions (MonoType *type)
1325 switch (type->type) {
1326 case MONO_TYPE_CLASS:
1327 case MONO_TYPE_VALUETYPE:
1328 case MONO_TYPE_SZARRAY:
1329 return type->data.klass->exception_type;
1330 case MONO_TYPE_ARRAY:
1331 return type->data.array->eklass->exception_type;
1332 case MONO_TYPE_GENERICINST:
1333 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1341 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1345 mono_class_alloc (MonoClass *class, int size)
1347 if (class->generic_class)
1348 return mono_image_set_alloc (class->generic_class->owner, size);
1350 return mono_image_alloc (class->image, size);
1354 mono_class_alloc0 (MonoClass *class, int size)
1358 res = mono_class_alloc (class, size);
1359 memset (res, 0, size);
1363 #define mono_class_new0(class,struct_type, n_structs) \
1364 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1367 * mono_class_setup_basic_field_info:
1368 * @class: The class to initialize
1370 * Initializes the class->fields.
1371 * LOCKING: Assumes the loader lock is held.
1374 mono_class_setup_basic_field_info (MonoClass *class)
1376 MonoClassField *field;
1384 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1385 image = class->image;
1386 top = class->field.count;
1388 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1390 * This happens when a generic instance of an unfinished generic typebuilder
1391 * is used as an element type for creating an array type. We can't initialize
1392 * the fields of this class using the fields of gklass, since gklass is not
1393 * finished yet, fields could be added to it later.
1399 mono_class_setup_basic_field_info (gtd);
1401 top = gtd->field.count;
1402 class->field.first = gtd->field.first;
1403 class->field.count = gtd->field.count;
1406 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1409 * Fetch all the field information.
1411 for (i = 0; i < top; i++){
1412 field = &class->fields [i];
1413 field->parent = class;
1416 field->name = mono_field_get_name (>d->fields [i]);
1418 int idx = class->field.first + i;
1419 /* class->field.first and idx points into the fieldptr table */
1420 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1421 /* The name is needed for fieldrefs */
1422 field->name = mono_metadata_string_heap (image, name_idx);
1428 * mono_class_setup_fields:
1429 * @class: The class to initialize
1431 * Initializes the class->fields.
1432 * LOCKING: Assumes the loader lock is held.
1435 mono_class_setup_fields (MonoClass *class)
1438 MonoImage *m = class->image;
1440 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1441 int i, blittable = TRUE;
1442 guint32 real_size = 0;
1443 guint32 packing_size = 0;
1444 gboolean explicit_size;
1445 MonoClassField *field;
1446 MonoGenericContainer *container = NULL;
1447 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1450 * FIXME: We have a race condition here. It's possible that this function returns
1451 * to its caller with `instance_size` set to `0` instead of the actual size. This
1452 * is not a problem when the function is called recursively on the same class,
1453 * because the size will be initialized by the outer invocation. What follows is a
1454 * description of how it can occur in other cases, too. There it is a problem,
1455 * because it can lead to the GC being asked to allocate an object of size `0`,
1456 * which SGen chokes on. The race condition is triggered infrequently by
1457 * `tests/sgen-suspend.cs`.
1459 * This function is called for a class whenever one of its subclasses is inited.
1460 * For example, it's called for every subclass of Object. What it does is this:
1462 * if (class->setup_fields_called)
1465 * class->instance_size = 0;
1467 * class->setup_fields_called = 1;
1468 * ... critical point
1469 * class->instance_size = actual_instance_size;
1471 * The last two steps are sometimes reversed, but that only changes the way in which
1472 * the race condition works.
1474 * Assume thread A goes through this function and makes it to the critical point.
1475 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1476 * immediately, but `instance_size` is incorrect.
1478 * The other case looks like this:
1480 * if (class->setup_fields_called)
1482 * ... critical point X
1483 * class->instance_size = 0;
1484 * ... critical point Y
1485 * class->instance_size = actual_instance_size;
1487 * class->setup_fields_called = 1;
1489 * Assume thread A goes through the function and makes it to critical point X. Now
1490 * thread B runs through the whole of the function, returning, assuming
1491 * `instance_size` is set. At that point thread A gets to run and makes it to
1492 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1495 if (class->setup_fields_called)
1498 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1500 * This happens when a generic instance of an unfinished generic typebuilder
1501 * is used as an element type for creating an array type. We can't initialize
1502 * the fields of this class using the fields of gklass, since gklass is not
1503 * finished yet, fields could be added to it later.
1508 mono_class_setup_basic_field_info (class);
1509 top = class->field.count;
1512 mono_class_setup_fields (gtd);
1513 if (gtd->exception_type) {
1514 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1519 class->instance_size = 0;
1521 class->sizes.class_size = 0;
1523 if (class->parent) {
1524 /* For generic instances, class->parent might not have been initialized */
1525 mono_class_init (class->parent);
1526 if (!class->parent->size_inited) {
1527 mono_class_setup_fields (class->parent);
1528 if (class->parent->exception_type) {
1529 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1533 class->instance_size += class->parent->instance_size;
1534 class->min_align = class->parent->min_align;
1535 /* we use |= since it may have been set already */
1536 class->has_references |= class->parent->has_references;
1537 blittable = class->parent->blittable;
1539 class->instance_size = sizeof (MonoObject);
1540 class->min_align = 1;
1543 /* We can't really enable 16 bytes alignment until the GC supports it.
1544 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1545 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1546 Bug #506144 is an example of this issue.
1548 if (class->simd_type)
1549 class->min_align = 16;
1551 /* Get the real size */
1552 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1554 if (explicit_size) {
1555 if ((packing_size & 0xfffffff0) != 0) {
1556 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1557 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1560 class->packing_size = packing_size;
1561 real_size += class->instance_size;
1565 if (explicit_size && real_size) {
1566 class->instance_size = MAX (real_size, class->instance_size);
1568 class->blittable = blittable;
1569 mono_memory_barrier ();
1570 class->size_inited = 1;
1571 class->fields_inited = 1;
1572 class->setup_fields_called = 1;
1576 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1579 /* Prevent infinite loops if the class references itself */
1580 class->setup_fields_called = 1;
1582 if (class->generic_container) {
1583 container = class->generic_container;
1585 container = gtd->generic_container;
1586 g_assert (container);
1590 * Fetch all the field information.
1592 for (i = 0; i < top; i++){
1593 int idx = class->field.first + i;
1594 field = &class->fields [i];
1596 field->parent = class;
1599 mono_field_resolve_type (field, &error);
1600 if (!mono_error_ok (&error)) {
1601 /*mono_field_resolve_type already failed class*/
1602 mono_error_cleanup (&error);
1606 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1607 g_assert (field->type);
1610 if (mono_field_is_deleted (field))
1613 MonoClassField *gfield = >d->fields [i];
1614 field->offset = gfield->offset;
1616 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1618 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1619 field->offset = offset;
1621 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1622 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1625 if (field->offset < -1) { /*-1 is used to encode special static fields */
1626 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1632 /* Only do these checks if we still think this type is blittable */
1633 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1634 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1637 MonoClass *field_class = mono_class_from_mono_type (field->type);
1639 mono_class_setup_fields (field_class);
1640 if (field_class->exception_type) {
1641 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1645 if (!field_class || !field_class->blittable)
1650 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1651 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1652 blittable = class->element_class->blittable;
1655 if (mono_type_has_exceptions (field->type)) {
1656 char *class_name = mono_type_get_full_name (class);
1657 char *type_name = mono_type_full_name (field->type);
1659 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1660 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1661 g_free (class_name);
1665 /* The def_value of fields is compute lazily during vtable creation */
1668 if (class == mono_defaults.string_class)
1671 class->blittable = blittable;
1673 if (class->enumtype && !mono_class_enum_basetype (class)) {
1674 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1677 if (explicit_size && real_size) {
1678 class->instance_size = MAX (real_size, class->instance_size);
1681 if (class->exception_type)
1683 mono_class_layout_fields (class);
1685 /*valuetypes can't be neither bigger than 1Mb or empty. */
1686 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1687 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1689 mono_memory_barrier ();
1690 class->fields_inited = 1;
1694 * mono_class_setup_fields_locking:
1695 * @class: The class to initialize
1697 * Initializes the class->fields array of fields.
1698 * Aquires the loader lock.
1701 mono_class_setup_fields_locking (MonoClass *class)
1703 /* This can be checked without locks */
1704 if (class->fields_inited)
1706 mono_loader_lock ();
1707 mono_class_setup_fields (class);
1708 mono_loader_unlock ();
1712 * mono_class_has_references:
1714 * Returns whenever @klass->has_references is set, initializing it if needed.
1715 * Aquires the loader lock.
1718 mono_class_has_references (MonoClass *klass)
1720 if (klass->init_pending) {
1721 /* Be conservative */
1724 mono_class_init (klass);
1726 return klass->has_references;
1731 * mono_type_get_basic_type_from_generic:
1734 * Returns a closed type corresponding to the possibly open type
1738 mono_type_get_basic_type_from_generic (MonoType *type)
1740 /* When we do generic sharing we let type variables stand for reference types. */
1741 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1742 return &mono_defaults.object_class->byval_arg;
1747 * mono_class_layout_fields:
1750 * Compute the placement of fields inside an object or struct, according to
1751 * the layout rules and set the following fields in @class:
1752 * - has_references (if the class contains instance references firled or structs that contain references)
1753 * - has_static_refs (same, but for static fields)
1754 * - instance_size (size of the object in memory)
1755 * - class_size (size needed for the static fields)
1756 * - size_inited (flag set when the instance_size is set)
1758 * LOCKING: this is supposed to be called with the loader lock held.
1761 mono_class_layout_fields (MonoClass *class)
1764 const int top = class->field.count;
1765 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1766 guint32 pass, passes, real_size;
1767 gboolean gc_aware_layout = FALSE;
1768 gboolean has_static_fields = FALSE;
1769 MonoClassField *field;
1772 * When we do generic sharing we need to have layout
1773 * information for open generic classes (either with a generic
1774 * context containing type variables or with a generic
1775 * container), so we don't return in that case anymore.
1779 * Enable GC aware auto layout: in this mode, reference
1780 * fields are grouped together inside objects, increasing collector
1782 * Requires that all classes whose layout is known to native code be annotated
1783 * with [StructLayout (LayoutKind.Sequential)]
1784 * Value types have gc_aware_layout disabled by default, as per
1785 * what the default is for other runtimes.
1787 /* corlib is missing [StructLayout] directives in many places */
1788 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1789 if (!class->valuetype)
1790 gc_aware_layout = TRUE;
1793 /* Compute klass->has_references */
1795 * Process non-static fields first, since static fields might recursively
1796 * refer to the class itself.
1798 for (i = 0; i < top; i++) {
1801 field = &class->fields [i];
1803 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1804 ftype = mono_type_get_underlying_type (field->type);
1805 ftype = mono_type_get_basic_type_from_generic (ftype);
1806 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1807 class->has_references = TRUE;
1811 for (i = 0; i < top; i++) {
1814 field = &class->fields [i];
1816 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1817 ftype = mono_type_get_underlying_type (field->type);
1818 ftype = mono_type_get_basic_type_from_generic (ftype);
1819 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1820 class->has_static_refs = TRUE;
1824 for (i = 0; i < top; i++) {
1827 field = &class->fields [i];
1829 ftype = mono_type_get_underlying_type (field->type);
1830 ftype = mono_type_get_basic_type_from_generic (ftype);
1831 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1832 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1833 class->has_static_refs = TRUE;
1835 class->has_references = TRUE;
1840 * Compute field layout and total size (not considering static fields)
1844 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1845 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1847 if (gc_aware_layout)
1852 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1855 if (class->parent) {
1856 mono_class_setup_fields (class->parent);
1857 if (class->parent->exception_type) {
1858 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1861 real_size = class->parent->instance_size;
1863 real_size = sizeof (MonoObject);
1866 for (pass = 0; pass < passes; ++pass) {
1867 for (i = 0; i < top; i++){
1872 field = &class->fields [i];
1874 if (mono_field_is_deleted (field))
1876 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1879 ftype = mono_type_get_underlying_type (field->type);
1880 ftype = mono_type_get_basic_type_from_generic (ftype);
1881 if (gc_aware_layout) {
1882 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1891 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1892 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1893 /* This field is a hack inserted by MCS to empty structures */
1897 size = mono_type_size (field->type, &align);
1899 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1900 align = class->packing_size ? MIN (class->packing_size, align): align;
1901 /* if the field has managed references, we need to force-align it
1904 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1905 align = MAX (align, sizeof (gpointer));
1907 class->min_align = MAX (align, class->min_align);
1908 field->offset = real_size;
1910 field->offset += align - 1;
1911 field->offset &= ~(align - 1);
1913 /*TypeBuilders produce all sort of weird things*/
1914 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1915 real_size = field->offset + size;
1918 class->instance_size = MAX (real_size, class->instance_size);
1920 if (class->instance_size & (class->min_align - 1)) {
1921 class->instance_size += class->min_align - 1;
1922 class->instance_size &= ~(class->min_align - 1);
1926 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1928 for (i = 0; i < top; i++) {
1933 field = &class->fields [i];
1936 * There must be info about all the fields in a type if it
1937 * uses explicit layout.
1940 if (mono_field_is_deleted (field))
1942 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1945 size = mono_type_size (field->type, &align);
1946 align = class->packing_size ? MIN (class->packing_size, align): align;
1947 class->min_align = MAX (align, class->min_align);
1950 * When we get here, field->offset is already set by the
1951 * loader (for either runtime fields or fields loaded from metadata).
1952 * The offset is from the start of the object: this works for both
1953 * classes and valuetypes.
1955 field->offset += sizeof (MonoObject);
1956 ftype = mono_type_get_underlying_type (field->type);
1957 ftype = mono_type_get_basic_type_from_generic (ftype);
1958 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1959 if (field->offset % sizeof (gpointer)) {
1960 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1967 real_size = MAX (real_size, size + field->offset);
1969 class->instance_size = MAX (real_size, class->instance_size);
1970 if (class->instance_size & (class->min_align - 1)) {
1971 class->instance_size += class->min_align - 1;
1972 class->instance_size &= ~(class->min_align - 1);
1977 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1979 * For small structs, set min_align to at least the struct size to improve
1980 * performance, and since the JIT memset/memcpy code assumes this and generates
1981 * unaligned accesses otherwise. See #78990 for a testcase.
1983 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1984 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1987 mono_memory_barrier ();
1988 class->size_inited = 1;
1991 * Compute static field layout and size
1993 for (i = 0; i < top; i++){
1997 field = &class->fields [i];
1999 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2001 if (mono_field_is_deleted (field))
2004 if (mono_type_has_exceptions (field->type)) {
2005 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2009 has_static_fields = TRUE;
2011 size = mono_type_size (field->type, &align);
2012 field->offset = class->sizes.class_size;
2013 /*align is always non-zero here*/
2014 field->offset += align - 1;
2015 field->offset &= ~(align - 1);
2016 class->sizes.class_size = field->offset + size;
2019 if (has_static_fields && class->sizes.class_size == 0)
2020 /* Simplify code which depends on class_size != 0 if the class has static fields */
2021 class->sizes.class_size = 8;
2025 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2029 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2030 method->klass = class;
2031 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2032 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2033 method->signature = sig;
2034 method->name = name;
2037 if (name [0] == '.') {
2038 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2040 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2046 * mono_class_setup_methods:
2049 * Initializes the 'methods' array in CLASS.
2050 * Calling this method should be avoided if possible since it allocates a lot
2051 * of long-living MonoMethod structures.
2052 * Methods belonging to an interface are assigned a sequential slot starting
2055 * On failure this function sets class->exception_type
2058 mono_class_setup_methods (MonoClass *class)
2061 MonoMethod **methods;
2066 if (class->generic_class) {
2068 MonoClass *gklass = class->generic_class->container_class;
2070 mono_class_init (gklass);
2071 if (!gklass->exception_type)
2072 mono_class_setup_methods (gklass);
2073 if (gklass->exception_type) {
2074 /* FIXME make exception_data less opaque so it's possible to dup it here */
2075 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2079 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2080 count = gklass->method.count;
2081 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2083 for (i = 0; i < count; i++) {
2084 methods [i] = mono_class_inflate_generic_method_full_checked (
2085 gklass->methods [i], class, mono_class_get_context (class), &error);
2086 if (!mono_error_ok (&error)) {
2087 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2088 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)));
2091 mono_error_cleanup (&error);
2095 } else if (class->rank) {
2097 MonoMethod *amethod;
2098 MonoMethodSignature *sig;
2099 int count_generic = 0, first_generic = 0;
2102 count = 3 + (class->rank > 1? 2: 1);
2104 mono_class_setup_interfaces (class, &error);
2105 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2107 if (class->interface_count) {
2108 count_generic = generic_array_methods (class);
2109 first_generic = count;
2110 count += class->interface_count * count_generic;
2113 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2115 sig = mono_metadata_signature_alloc (class->image, class->rank);
2116 sig->ret = &mono_defaults.void_class->byval_arg;
2117 sig->pinvoke = TRUE;
2118 sig->hasthis = TRUE;
2119 for (i = 0; i < class->rank; ++i)
2120 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2122 amethod = create_array_method (class, ".ctor", sig);
2123 methods [method_num++] = amethod;
2124 if (class->rank > 1) {
2125 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2126 sig->ret = &mono_defaults.void_class->byval_arg;
2127 sig->pinvoke = TRUE;
2128 sig->hasthis = TRUE;
2129 for (i = 0; i < class->rank * 2; ++i)
2130 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2132 amethod = create_array_method (class, ".ctor", sig);
2133 methods [method_num++] = amethod;
2135 /* element Get (idx11, [idx2, ...]) */
2136 sig = mono_metadata_signature_alloc (class->image, class->rank);
2137 sig->ret = &class->element_class->byval_arg;
2138 sig->pinvoke = TRUE;
2139 sig->hasthis = TRUE;
2140 for (i = 0; i < class->rank; ++i)
2141 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2142 amethod = create_array_method (class, "Get", sig);
2143 methods [method_num++] = amethod;
2144 /* element& Address (idx11, [idx2, ...]) */
2145 sig = mono_metadata_signature_alloc (class->image, class->rank);
2146 sig->ret = &class->element_class->this_arg;
2147 sig->pinvoke = TRUE;
2148 sig->hasthis = TRUE;
2149 for (i = 0; i < class->rank; ++i)
2150 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2151 amethod = create_array_method (class, "Address", sig);
2152 methods [method_num++] = amethod;
2153 /* void Set (idx11, [idx2, ...], element) */
2154 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2155 sig->ret = &mono_defaults.void_class->byval_arg;
2156 sig->pinvoke = TRUE;
2157 sig->hasthis = TRUE;
2158 for (i = 0; i < class->rank; ++i)
2159 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2160 sig->params [i] = &class->element_class->byval_arg;
2161 amethod = create_array_method (class, "Set", sig);
2162 methods [method_num++] = amethod;
2164 for (i = 0; i < class->interface_count; i++)
2165 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2167 count = class->method.count;
2168 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2169 for (i = 0; i < count; ++i) {
2170 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2171 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2175 if (MONO_CLASS_IS_INTERFACE (class)) {
2177 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2178 for (i = 0; i < count; ++i) {
2179 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2180 methods [i]->slot = slot++;
2184 mono_image_lock (class->image);
2186 if (!class->methods) {
2187 class->method.count = count;
2189 /* Needed because of the double-checking locking pattern */
2190 mono_memory_barrier ();
2192 class->methods = methods;
2195 mono_image_unlock (class->image);
2199 * mono_class_get_method_by_index:
2201 * Returns class->methods [index], initializing class->methods if neccesary.
2203 * LOCKING: Acquires the loader lock.
2206 mono_class_get_method_by_index (MonoClass *class, int index)
2208 /* Avoid calling setup_methods () if possible */
2209 if (class->generic_class && !class->methods) {
2210 MonoClass *gklass = class->generic_class->container_class;
2213 m = mono_class_inflate_generic_method_full (
2214 gklass->methods [index], class, mono_class_get_context (class));
2216 * If setup_methods () is called later for this class, no duplicates are created,
2217 * since inflate_generic_method guarantees that only one instance of a method
2218 * is created for each context.
2221 mono_class_setup_methods (class);
2222 g_assert (m == class->methods [index]);
2226 mono_class_setup_methods (class);
2227 if (class->exception_type) /*FIXME do proper error handling*/
2229 g_assert (index >= 0 && index < class->method.count);
2230 return class->methods [index];
2235 * mono_class_get_inflated_method:
2237 * Given an inflated class CLASS and a method METHOD which should be a method of
2238 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2241 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2243 MonoClass *gklass = class->generic_class->container_class;
2246 g_assert (method->klass == gklass);
2248 mono_class_setup_methods (gklass);
2249 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2251 for (i = 0; i < gklass->method.count; ++i) {
2252 if (gklass->methods [i] == method) {
2254 return class->methods [i];
2256 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2264 * mono_class_get_vtable_entry:
2266 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2267 * LOCKING: Acquires the loader lock.
2270 mono_class_get_vtable_entry (MonoClass *class, int offset)
2274 if (class->rank == 1) {
2276 * szarrays do not overwrite any methods of Array, so we can avoid
2277 * initializing their vtables in some cases.
2279 mono_class_setup_vtable (class->parent);
2280 if (offset < class->parent->vtable_size)
2281 return class->parent->vtable [offset];
2284 if (class->generic_class) {
2285 MonoClass *gklass = class->generic_class->container_class;
2286 mono_class_setup_vtable (gklass);
2287 m = gklass->vtable [offset];
2289 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2291 mono_class_setup_vtable (class);
2292 if (class->exception_type)
2294 m = class->vtable [offset];
2301 * mono_class_get_vtable_size:
2303 * Return the vtable size for KLASS.
2306 mono_class_get_vtable_size (MonoClass *klass)
2308 mono_class_setup_vtable (klass);
2310 return klass->vtable_size;
2314 * mono_class_setup_properties:
2316 * Initialize class->ext.property and class->ext.properties.
2318 * This method can fail the class.
2321 mono_class_setup_properties (MonoClass *class)
2323 guint startm, endm, i, j;
2324 guint32 cols [MONO_PROPERTY_SIZE];
2325 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2326 MonoProperty *properties;
2330 if (class->ext && class->ext->properties)
2333 if (class->generic_class) {
2334 MonoClass *gklass = class->generic_class->container_class;
2336 mono_class_init (gklass);
2337 mono_class_setup_properties (gklass);
2338 if (gklass->exception_type) {
2339 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2343 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2345 for (i = 0; i < gklass->ext->property.count; i++) {
2346 MonoProperty *prop = &properties [i];
2348 *prop = gklass->ext->properties [i];
2351 prop->get = mono_class_inflate_generic_method_full (
2352 prop->get, class, mono_class_get_context (class));
2354 prop->set = mono_class_inflate_generic_method_full (
2355 prop->set, class, mono_class_get_context (class));
2357 prop->parent = class;
2360 first = gklass->ext->property.first;
2361 count = gklass->ext->property.count;
2363 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2364 count = last - first;
2367 mono_class_setup_methods (class);
2368 if (class->exception_type)
2372 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2373 for (i = first; i < last; ++i) {
2374 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2375 properties [i - first].parent = class;
2376 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2377 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2379 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2380 for (j = startm; j < endm; ++j) {
2383 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2385 if (class->image->uncompressed_metadata)
2386 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2387 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2389 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2391 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2392 case METHOD_SEMANTIC_SETTER:
2393 properties [i - first].set = method;
2395 case METHOD_SEMANTIC_GETTER:
2396 properties [i - first].get = method;
2405 mono_class_alloc_ext (class);
2407 mono_image_lock (class->image);
2409 if (class->ext->properties) {
2410 /* We leak 'properties' which was allocated from the image mempool */
2411 mono_image_unlock (class->image);
2415 class->ext->property.first = first;
2416 class->ext->property.count = count;
2418 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2419 mono_memory_barrier ();
2421 /* Leave this assignment as the last op in the function */
2422 class->ext->properties = properties;
2424 mono_image_unlock (class->image);
2428 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2430 MonoMethod **om, **retval;
2433 for (om = methods, count = 0; *om; ++om, ++count)
2436 retval = g_new0 (MonoMethod*, count + 1);
2438 for (om = methods, count = 0; *om; ++om, ++count)
2439 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2444 /*This method can fail the class.*/
2446 mono_class_setup_events (MonoClass *class)
2449 guint startm, endm, i, j;
2450 guint32 cols [MONO_EVENT_SIZE];
2451 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2455 if (class->ext && class->ext->events)
2458 if (class->generic_class) {
2459 MonoClass *gklass = class->generic_class->container_class;
2460 MonoGenericContext *context;
2462 mono_class_setup_events (gklass);
2463 if (gklass->exception_type) {
2464 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2468 first = gklass->ext->event.first;
2469 count = gklass->ext->event.count;
2471 events = mono_class_new0 (class, MonoEvent, count);
2474 context = mono_class_get_context (class);
2476 for (i = 0; i < count; i++) {
2477 MonoEvent *event = &events [i];
2478 MonoEvent *gevent = &gklass->ext->events [i];
2480 event->parent = class;
2481 event->name = gevent->name;
2482 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2483 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2484 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2485 #ifndef MONO_SMALL_CONFIG
2486 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2488 event->attrs = gevent->attrs;
2491 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2492 count = last - first;
2495 mono_class_setup_methods (class);
2496 if (class->exception_type) {
2497 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2502 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2503 for (i = first; i < last; ++i) {
2504 MonoEvent *event = &events [i - first];
2506 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2507 event->parent = class;
2508 event->attrs = cols [MONO_EVENT_FLAGS];
2509 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2511 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2512 for (j = startm; j < endm; ++j) {
2515 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2517 if (class->image->uncompressed_metadata)
2518 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2519 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2521 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2523 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2524 case METHOD_SEMANTIC_ADD_ON:
2525 event->add = method;
2527 case METHOD_SEMANTIC_REMOVE_ON:
2528 event->remove = method;
2530 case METHOD_SEMANTIC_FIRE:
2531 event->raise = method;
2533 case METHOD_SEMANTIC_OTHER: {
2534 #ifndef MONO_SMALL_CONFIG
2537 if (event->other == NULL) {
2538 event->other = g_new0 (MonoMethod*, 2);
2540 while (event->other [n])
2542 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2544 event->other [n] = method;
2545 /* NULL terminated */
2546 event->other [n + 1] = NULL;
2557 mono_class_alloc_ext (class);
2559 mono_image_lock (class->image);
2561 if (class->ext->events) {
2562 mono_image_unlock (class->image);
2566 class->ext->event.first = first;
2567 class->ext->event.count = count;
2569 /* Flush any pending writes as we do double checked locking on class->ext.events */
2570 mono_memory_barrier ();
2572 /* Leave this assignment as the last op in the function */
2573 class->ext->events = events;
2575 mono_image_unlock (class->image);
2579 * Global pool of interface IDs, represented as a bitset.
2580 * LOCKING: Protected by the classes lock.
2582 static MonoBitSet *global_interface_bitset = NULL;
2585 * mono_unload_interface_ids:
2586 * @bitset: bit set of interface IDs
2588 * When an image is unloaded, the interface IDs associated with
2589 * the image are put back in the global pool of IDs so the numbers
2593 mono_unload_interface_ids (MonoBitSet *bitset)
2596 mono_bitset_sub (global_interface_bitset, bitset);
2601 mono_unload_interface_id (MonoClass *class)
2603 if (global_interface_bitset && class->interface_id) {
2605 mono_bitset_clear (global_interface_bitset, class->interface_id);
2611 * mono_get_unique_iid:
2614 * Assign a unique integer ID to the interface represented by @class.
2615 * The ID will positive and as small as possible.
2616 * LOCKING: Acquires the classes lock.
2617 * Returns: the new ID.
2620 mono_get_unique_iid (MonoClass *class)
2624 g_assert (MONO_CLASS_IS_INTERFACE (class));
2628 if (!global_interface_bitset) {
2629 global_interface_bitset = mono_bitset_new (128, 0);
2632 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2634 int old_size = mono_bitset_size (global_interface_bitset);
2635 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2636 mono_bitset_free (global_interface_bitset);
2637 global_interface_bitset = new_set;
2640 mono_bitset_set (global_interface_bitset, iid);
2641 /* set the bit also in the per-image set */
2642 if (!class->generic_class) {
2643 if (class->image->interface_bitset) {
2644 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2645 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2646 mono_bitset_free (class->image->interface_bitset);
2647 class->image->interface_bitset = new_set;
2650 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2652 mono_bitset_set (class->image->interface_bitset, iid);
2657 #ifndef MONO_SMALL_CONFIG
2658 if (mono_print_vtable) {
2660 char *type_name = mono_type_full_name (&class->byval_arg);
2661 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2662 generic_id = class->generic_class->context.class_inst->id;
2663 g_assert (generic_id != 0);
2667 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2672 g_assert (iid <= 65535);
2677 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2682 mono_class_setup_interfaces (klass, error);
2683 if (!mono_error_ok (error))
2686 for (i = 0; i < klass->interface_count; i++) {
2687 ic = klass->interfaces [i];
2690 *res = g_ptr_array_new ();
2691 g_ptr_array_add (*res, ic);
2692 mono_class_init (ic);
2693 if (ic->exception_type) {
2694 mono_error_set_type_load_class (error, ic, "Error Loading class");
2698 collect_implemented_interfaces_aux (ic, res, error);
2699 if (!mono_error_ok (error))
2705 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2707 GPtrArray *res = NULL;
2709 collect_implemented_interfaces_aux (klass, &res, error);
2710 if (!mono_error_ok (error)) {
2712 g_ptr_array_free (res, TRUE);
2719 compare_interface_ids (const void *p_key, const void *p_element) {
2720 const MonoClass *key = p_key;
2721 const MonoClass *element = *(MonoClass**) p_element;
2723 return (key->interface_id - element->interface_id);
2726 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2728 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2729 MonoClass **result = mono_binary_search (
2731 klass->interfaces_packed,
2732 klass->interface_offsets_count,
2733 sizeof (MonoClass *),
2734 compare_interface_ids);
2736 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2743 * mono_class_interface_offset_with_variance:
2745 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2746 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2748 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2750 * FIXME figure out MS disambiguation rules and fix this function.
2753 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2754 int i = mono_class_interface_offset (klass, itf);
2755 *non_exact_match = FALSE;
2759 if (!mono_class_has_variant_generic_params (itf))
2762 for (i = 0; i < klass->interface_offsets_count; i++) {
2763 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2764 *non_exact_match = TRUE;
2765 return klass->interface_offsets_packed [i];
2773 print_implemented_interfaces (MonoClass *klass) {
2776 GPtrArray *ifaces = NULL;
2778 int ancestor_level = 0;
2780 name = mono_type_get_full_name (klass);
2781 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2784 for (i = 0; i < klass->interface_offsets_count; i++)
2785 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2786 klass->interfaces_packed [i]->interface_id,
2787 klass->interface_offsets_packed [i],
2788 klass->interfaces_packed [i]->method.count,
2789 klass->interfaces_packed [i]->name_space,
2790 klass->interfaces_packed [i]->name );
2791 printf ("Interface flags: ");
2792 for (i = 0; i <= klass->max_interface_id; i++)
2793 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2794 printf ("(%d,T)", i);
2796 printf ("(%d,F)", i);
2798 printf ("Dump interface flags:");
2799 #ifdef COMPRESSED_INTERFACE_BITMAP
2801 const uint8_t* p = klass->interface_bitmap;
2802 i = klass->max_interface_id;
2804 printf (" %d x 00 %02X", p [0], p [1]);
2810 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2811 printf (" %02X", klass->interface_bitmap [i]);
2814 while (klass != NULL) {
2815 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2816 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2817 if (!mono_error_ok (&error)) {
2818 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2819 mono_error_cleanup (&error);
2820 } else if (ifaces) {
2821 for (i = 0; i < ifaces->len; i++) {
2822 MonoClass *ic = g_ptr_array_index (ifaces, i);
2823 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2824 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2826 mono_class_interface_offset (klass, ic),
2831 g_ptr_array_free (ifaces, TRUE);
2834 klass = klass->parent;
2839 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2842 args [0] = &arg0->byval_arg;
2844 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2848 array_class_get_if_rank (MonoClass *class, guint rank)
2850 return rank ? mono_array_class_get (class, rank) : class;
2854 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2856 valuetype_types [0] = eclass;
2857 if (eclass == mono_defaults.int16_class)
2858 valuetype_types [1] = mono_defaults.uint16_class;
2859 else if (eclass == mono_defaults.uint16_class)
2860 valuetype_types [1] = mono_defaults.int16_class;
2861 else if (eclass == mono_defaults.int32_class)
2862 valuetype_types [1] = mono_defaults.uint32_class;
2863 else if (eclass == mono_defaults.uint32_class)
2864 valuetype_types [1] = mono_defaults.int32_class;
2865 else if (eclass == mono_defaults.int64_class)
2866 valuetype_types [1] = mono_defaults.uint64_class;
2867 else if (eclass == mono_defaults.uint64_class)
2868 valuetype_types [1] = mono_defaults.int64_class;
2869 else if (eclass == mono_defaults.byte_class)
2870 valuetype_types [1] = mono_defaults.sbyte_class;
2871 else if (eclass == mono_defaults.sbyte_class)
2872 valuetype_types [1] = mono_defaults.byte_class;
2873 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2874 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2877 /* this won't be needed once bug #325495 is completely fixed
2878 * though we'll need something similar to know which interfaces to allow
2879 * in arrays when they'll be lazyly created
2881 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2882 * MS returns diferrent types based on which instance is called. For example:
2883 * object obj = new byte[10][];
2884 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2885 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2888 * Fixing this should kill quite some code, save some bits and improve compatibility.
2891 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2893 MonoClass *eclass = class->element_class;
2894 static MonoClass* generic_icollection_class = NULL;
2895 static MonoClass* generic_ienumerable_class = NULL;
2896 static MonoClass* generic_ienumerator_class = NULL;
2897 static MonoClass* generic_ireadonlylist_class = NULL;
2898 static MonoClass* generic_ireadonlycollection_class = NULL;
2899 MonoClass *valuetype_types[2] = { NULL, NULL };
2900 MonoClass **interfaces = NULL;
2901 int i, nifaces, interface_count, real_count, original_rank;
2903 gboolean internal_enumerator;
2904 gboolean eclass_is_valuetype;
2906 if (!mono_defaults.generic_ilist_class) {
2910 internal_enumerator = FALSE;
2911 eclass_is_valuetype = FALSE;
2912 original_rank = eclass->rank;
2913 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2914 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2916 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2918 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2919 original_rank = eclass->rank;
2921 eclass = eclass->element_class;
2922 internal_enumerator = TRUE;
2923 *is_enumerator = TRUE;
2931 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2932 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2934 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2936 if (!generic_icollection_class) {
2937 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2938 "System.Collections.Generic", "ICollection`1");
2939 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2940 "System.Collections.Generic", "IEnumerable`1");
2941 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2942 "System.Collections.Generic", "IEnumerator`1");
2943 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2944 "System.Collections.Generic", "IReadOnlyList`1");
2945 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2946 "System.Collections.Generic", "IReadOnlyCollection`1");
2949 mono_class_init (eclass);
2952 * Arrays in 2.0 need to implement a number of generic interfaces
2953 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2954 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2955 * We collect the types needed to build the
2956 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2957 * the generic interfaces needed to implement.
2959 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2960 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2962 if (eclass->valuetype) {
2963 nifaces = generic_ireadonlylist_class ? 5 : 3;
2964 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2966 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2967 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2968 if (internal_enumerator) {
2970 if (valuetype_types [1])
2974 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2975 interfaces [0] = valuetype_types [0];
2976 if (valuetype_types [1])
2977 interfaces [nifaces] = valuetype_types [1];
2979 eclass_is_valuetype = TRUE;
2982 int idepth = eclass->idepth;
2983 if (!internal_enumerator)
2985 nifaces = generic_ireadonlylist_class ? 2 : 3;
2987 // FIXME: This doesn't seem to work/required for generic params
2988 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
2989 mono_class_setup_interface_offsets (eclass);
2991 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2992 /* we add object for interfaces and the supertypes for the other
2993 * types. The last of the supertypes is the element class itself which we
2994 * already created the explicit interfaces for (so we include it for IEnumerator
2995 * and exclude it for arrays).
2997 if (MONO_CLASS_IS_INTERFACE (eclass))
3000 interface_count += idepth;
3001 if (eclass->rank && eclass->element_class->valuetype) {
3002 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3003 if (valuetype_types [1])
3006 /* IList, ICollection, IEnumerable, IReadOnlyList */
3007 interface_count *= nifaces;
3008 real_count = interface_count;
3009 if (internal_enumerator) {
3010 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3011 if (valuetype_types [1])
3014 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3015 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3016 interfaces [0] = mono_defaults.object_class;
3020 for (i = 0; i < idepth; i++) {
3021 mono_class_init (eclass->supertypes [i]);
3022 interfaces [j] = eclass->supertypes [i];
3026 if (all_interfaces) {
3027 for (i = 0; i < eclass->interface_offsets_count; i++) {
3028 interfaces [j] = eclass->interfaces_packed [i];
3032 for (i = 0; i < eclass->interface_count; i++) {
3033 interfaces [j] = eclass->interfaces [i];
3037 if (valuetype_types [1]) {
3038 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3043 /* instantiate the generic interfaces */
3044 for (i = 0; i < interface_count; i += nifaces) {
3045 MonoClass *iface = interfaces [i];
3047 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3048 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3050 if (eclass->valuetype) {
3051 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3052 if (generic_ireadonlylist_class) {
3053 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3054 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3057 if (!generic_ireadonlylist_class)
3058 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3061 if (internal_enumerator) {
3063 /* instantiate IEnumerator<iface> */
3064 for (i = 0; i < interface_count; i++) {
3065 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3067 j = interface_count;
3068 if (!eclass_is_valuetype) {
3069 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3070 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3073 for (i = 0; i < eclass->idepth; i++) {
3074 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3078 for (i = 0; i < eclass->interface_offsets_count; i++) {
3079 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3083 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3085 if (valuetype_types [1])
3086 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3090 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3091 for (i = 0; i < real_count; ++i) {
3092 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3093 g_print ("%s implements %s\n", type_name, name);
3104 find_array_interface (MonoClass *klass, const char *name)
3107 for (i = 0; i < klass->interface_count; ++i) {
3108 if (strcmp (klass->interfaces [i]->name, name) == 0)
3115 * Return the number of virtual methods.
3116 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3117 * Return -1 on failure.
3118 * FIXME It would be nice if this information could be cached somewhere.
3121 count_virtual_methods (MonoClass *class)
3125 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3127 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3128 mono_class_setup_methods (class);
3129 if (class->exception_type)
3132 for (i = 0; i < class->method.count; ++i) {
3133 flags = class->methods [i]->flags;
3134 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3138 for (i = 0; i < class->method.count; ++i) {
3139 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3141 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3149 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3157 m = (l + num_ifaces) / 2;
3158 if (interfaces_full [m] == ic)
3160 if (l == num_ifaces)
3162 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3171 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3173 int i = find_interface (num_ifaces, interfaces_full, ic);
3175 return interface_offsets_full [i];
3180 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3182 int i = find_interface (num_ifaces, interfaces_full, ic);
3186 interface_offsets_full [i] = offset;
3189 for (i = 0; i < num_ifaces; ++i) {
3190 if (interfaces_full [i]) {
3192 if (interfaces_full [i]->interface_id < ic->interface_id)
3195 while (end < num_ifaces && interfaces_full [end]) end++;
3196 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3197 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3199 interfaces_full [i] = ic;
3200 interface_offsets_full [i] = offset;
3206 #ifdef COMPRESSED_INTERFACE_BITMAP
3209 * Compressed interface bitmap design.
3211 * Interface bitmaps take a large amount of memory, because their size is
3212 * linear with the maximum interface id assigned in the process (each interface
3213 * is assigned a unique id as it is loaded). The number of interface classes
3214 * is high because of the many implicit interfaces implemented by arrays (we'll
3215 * need to lazy-load them in the future).
3216 * Most classes implement a very small number of interfaces, so the bitmap is
3217 * sparse. This bitmap needs to be checked by interface casts, so access to the
3218 * needed bit must be fast and doable with few jit instructions.
3220 * The current compression format is as follows:
3221 * *) it is a sequence of one or more two-byte elements
3222 * *) the first byte in the element is the count of empty bitmap bytes
3223 * at the current bitmap position
3224 * *) the second byte in the element is an actual bitmap byte at the current
3227 * As an example, the following compressed bitmap bytes:
3228 * 0x07 0x01 0x00 0x7
3229 * correspond to the following bitmap:
3230 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3232 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3233 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3234 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3238 * mono_compress_bitmap:
3239 * @dest: destination buffer
3240 * @bitmap: bitmap buffer
3241 * @size: size of @bitmap in bytes
3243 * This is a mono internal function.
3244 * The @bitmap data is compressed into a format that is small but
3245 * still searchable in few instructions by the JIT and runtime.
3246 * The compressed data is stored in the buffer pointed to by the
3247 * @dest array. Passing a #NULL value for @dest allows to just compute
3248 * the size of the buffer.
3249 * This compression algorithm assumes the bits set in the bitmap are
3250 * few and far between, like in interface bitmaps.
3251 * Returns: the size of the compressed bitmap in bytes.
3254 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3258 const uint8_t *end = bitmap + size;
3259 while (bitmap < end) {
3260 if (*bitmap || numz == 255) {
3284 * mono_class_interface_match:
3285 * @bitmap: a compressed bitmap buffer
3286 * @id: the index to check in the bitmap
3288 * This is a mono internal function.
3289 * Checks if a bit is set in a compressed interface bitmap. @id must
3290 * be already checked for being smaller than the maximum id encoded in the
3293 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3297 mono_class_interface_match (const uint8_t *bitmap, int id)
3300 id -= bitmap [0] * 8;
3304 return bitmap [1] & (1 << id);
3313 * LOCKING: this is supposed to be called with the loader lock held.
3314 * Return -1 on failure and set exception_type
3317 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3321 int i, j, max_iid, num_ifaces;
3322 MonoClass **interfaces_full = NULL;
3323 int *interface_offsets_full = NULL;
3325 GPtrArray **ifaces_array = NULL;
3326 int interface_offsets_count;
3327 MonoClass **array_interfaces = NULL;
3328 int num_array_interfaces;
3329 int is_enumerator = FALSE;
3331 mono_class_setup_supertypes (class);
3333 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3334 * implicit interfaces have the property that they are assigned the same slot in the
3335 * vtables for compatible interfaces
3337 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3339 /* compute maximum number of slots and maximum interface id */
3341 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3342 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3343 for (j = 0; j < class->idepth; j++) {
3344 k = class->supertypes [j];
3345 num_ifaces += k->interface_count;
3346 for (i = 0; i < k->interface_count; i++) {
3347 ic = k->interfaces [i];
3350 mono_class_init (ic);
3352 if (max_iid < ic->interface_id)
3353 max_iid = ic->interface_id;
3355 ifaces = mono_class_get_implemented_interfaces (k, &error);
3356 if (!mono_error_ok (&error)) {
3357 char *name = mono_type_get_full_name (k);
3358 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)));
3360 mono_error_cleanup (&error);
3365 num_ifaces += ifaces->len;
3366 for (i = 0; i < ifaces->len; ++i) {
3367 ic = g_ptr_array_index (ifaces, i);
3368 if (max_iid < ic->interface_id)
3369 max_iid = ic->interface_id;
3371 ifaces_array [j] = ifaces;
3375 for (i = 0; i < num_array_interfaces; ++i) {
3376 ic = array_interfaces [i];
3377 mono_class_init (ic);
3378 if (max_iid < ic->interface_id)
3379 max_iid = ic->interface_id;
3382 if (MONO_CLASS_IS_INTERFACE (class)) {
3384 if (max_iid < class->interface_id)
3385 max_iid = class->interface_id;
3387 class->max_interface_id = max_iid;
3388 /* compute vtable offset for interfaces */
3389 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3390 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3392 for (i = 0; i < num_ifaces; i++) {
3393 interface_offsets_full [i] = -1;
3396 /* skip the current class */
3397 for (j = 0; j < class->idepth - 1; j++) {
3398 k = class->supertypes [j];
3399 ifaces = ifaces_array [j];
3402 for (i = 0; i < ifaces->len; ++i) {
3404 ic = g_ptr_array_index (ifaces, i);
3406 /*Force the sharing of interface offsets between parent and subtypes.*/
3407 io = mono_class_interface_offset (k, ic);
3409 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3414 g_assert (class == class->supertypes [class->idepth - 1]);
3415 ifaces = ifaces_array [class->idepth - 1];
3417 for (i = 0; i < ifaces->len; ++i) {
3419 ic = g_ptr_array_index (ifaces, i);
3420 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3422 count = count_virtual_methods (ic);
3424 char *name = mono_type_get_full_name (ic);
3425 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3434 if (MONO_CLASS_IS_INTERFACE (class))
3435 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3437 if (num_array_interfaces) {
3438 if (is_enumerator) {
3439 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3440 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3441 g_assert (ienumerator_offset >= 0);
3442 for (i = 0; i < num_array_interfaces; ++i) {
3443 ic = array_interfaces [i];
3444 if (strcmp (ic->name, "IEnumerator`1") == 0)
3445 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3447 g_assert_not_reached ();
3448 /*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);*/
3451 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3452 int ilist_iface_idx = find_array_interface (class, "IList`1");
3453 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3454 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3455 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3456 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3457 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3458 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3459 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3460 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3461 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3462 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3463 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3464 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3465 for (i = 0; i < num_array_interfaces; ++i) {
3467 ic = array_interfaces [i];
3468 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3469 offset = ilist_offset;
3470 else if (strcmp (ic->name, "ICollection`1") == 0)
3471 offset = icollection_offset;
3472 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3473 offset = ienumerable_offset;
3474 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3475 offset = ireadonlylist_offset;
3476 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3477 offset = ireadonlycollection_offset;
3479 g_assert_not_reached ();
3480 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3481 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3486 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3487 if (interface_offsets_full [i] != -1) {
3488 interface_offsets_count ++;
3493 * We might get called multiple times:
3494 * - mono_class_init ()
3495 * - mono_class_setup_vtable ().
3496 * - mono_class_setup_interface_offsets ().
3497 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3498 * means we have to overwrite those when called from other places (#4440).
3500 if (class->interfaces_packed && !overwrite) {
3501 g_assert (class->interface_offsets_count == interface_offsets_count);
3505 class->interface_offsets_count = interface_offsets_count;
3506 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3507 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3508 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3509 #ifdef COMPRESSED_INTERFACE_BITMAP
3510 bitmap = g_malloc0 (bsize);
3512 bitmap = mono_class_alloc0 (class, bsize);
3514 for (i = 0; i < interface_offsets_count; i++) {
3515 int id = interfaces_full [i]->interface_id;
3516 bitmap [id >> 3] |= (1 << (id & 7));
3517 class->interfaces_packed [i] = interfaces_full [i];
3518 class->interface_offsets_packed [i] = interface_offsets_full [i];
3519 /*if (num_array_interfaces)
3520 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]);*/
3522 #ifdef COMPRESSED_INTERFACE_BITMAP
3523 i = mono_compress_bitmap (NULL, bitmap, bsize);
3524 class->interface_bitmap = mono_class_alloc0 (class, i);
3525 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3528 class->interface_bitmap = bitmap;
3533 g_free (interfaces_full);
3534 g_free (interface_offsets_full);
3535 g_free (array_interfaces);
3536 for (i = 0; i < class->idepth; i++) {
3537 ifaces = ifaces_array [i];
3539 g_ptr_array_free (ifaces, TRUE);
3541 g_free (ifaces_array);
3543 //printf ("JUST DONE: ");
3544 //print_implemented_interfaces (class);
3550 * Setup interface offsets for interfaces.
3552 * - class->max_interface_id
3553 * - class->interface_offsets_count
3554 * - class->interfaces_packed
3555 * - class->interface_offsets_packed
3556 * - class->interface_bitmap
3558 * This function can fail @class.
3561 mono_class_setup_interface_offsets (MonoClass *class)
3563 mono_loader_lock ();
3565 setup_interface_offsets (class, 0, FALSE);
3567 mono_loader_unlock ();
3570 /*Checks if @klass has @parent as one of it's parents type gtd
3574 * Bar<T> : Foo<Bar<Bar<T>>>
3578 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3580 klass = mono_class_get_generic_type_definition (klass);
3581 parent = mono_class_get_generic_type_definition (parent);
3582 mono_class_setup_supertypes (klass);
3583 mono_class_setup_supertypes (parent);
3585 return klass->idepth >= parent->idepth &&
3586 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3590 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3592 MonoGenericInst *ginst;
3594 if (!class->generic_class) {
3595 mono_class_setup_vtable_full (class, in_setup);
3596 return class->exception_type == 0;
3599 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3600 if (class->generic_class->container_class->exception_type) {
3601 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3605 ginst = class->generic_class->context.class_inst;
3606 for (i = 0; i < ginst->type_argc; ++i) {
3608 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3610 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3611 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3612 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3614 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3615 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3623 * mono_class_setup_vtable:
3625 * Creates the generic vtable of CLASS.
3626 * Initializes the following fields in MonoClass:
3629 * Plus all the fields initialized by setup_interface_offsets ().
3630 * If there is an error during vtable construction, class->exception_type is set.
3632 * LOCKING: Acquires the loader lock.
3635 mono_class_setup_vtable (MonoClass *class)
3637 mono_class_setup_vtable_full (class, NULL);
3641 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3643 MonoMethod **overrides;
3644 MonoGenericContext *context;
3652 if (MONO_CLASS_IS_INTERFACE (class)) {
3653 /* This sets method->slot for all methods if this is an interface */
3654 mono_class_setup_methods (class);
3658 if (class->exception_type)
3661 if (g_list_find (in_setup, class))
3664 mono_loader_lock ();
3666 if (class->vtable) {
3667 mono_loader_unlock ();
3671 mono_stats.generic_vtable_count ++;
3672 in_setup = g_list_prepend (in_setup, class);
3674 if (class->generic_class) {
3675 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3676 mono_loader_unlock ();
3677 g_list_remove (in_setup, class);
3681 context = mono_class_get_context (class);
3682 type_token = class->generic_class->container_class->type_token;
3684 context = (MonoGenericContext *) class->generic_container;
3685 type_token = class->type_token;
3688 if (image_is_dynamic (class->image)) {
3689 /* Generic instances can have zero method overrides without causing any harm.
3690 * This is true since we don't do layout all over again for them, we simply inflate
3691 * the layout of the parent.
3693 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3695 /* The following call fails if there are missing methods in the type */
3696 /* FIXME it's probably a good idea to avoid this for generic instances. */
3697 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3701 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3703 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3707 mono_loader_unlock ();
3708 g_list_remove (in_setup, class);
3713 #define DEBUG_INTERFACE_VTABLE_CODE 0
3714 #define TRACE_INTERFACE_VTABLE_CODE 0
3715 #define VERIFY_INTERFACE_VTABLE_CODE 0
3716 #define VTABLE_SELECTOR (1)
3718 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3719 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3720 if (!(VTABLE_SELECTOR)) break; \
3724 #define DEBUG_INTERFACE_VTABLE(stmt)
3727 #if TRACE_INTERFACE_VTABLE_CODE
3728 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3729 if (!(VTABLE_SELECTOR)) break; \
3733 #define TRACE_INTERFACE_VTABLE(stmt)
3736 #if VERIFY_INTERFACE_VTABLE_CODE
3737 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3738 if (!(VTABLE_SELECTOR)) break; \
3742 #define VERIFY_INTERFACE_VTABLE(stmt)
3746 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3748 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3752 GString *res = g_string_new ("");
3754 g_string_append_c (res, '(');
3755 for (i = 0; i < sig->param_count; ++i) {
3757 g_string_append_c (res, ',');
3758 mono_type_get_desc (res, sig->params [i], include_namespace);
3760 g_string_append (res, ")=>");
3761 if (sig->ret != NULL) {
3762 mono_type_get_desc (res, sig->ret, include_namespace);
3764 g_string_append (res, "NULL");
3767 g_string_free (res, FALSE);
3771 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3772 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3773 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3774 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3782 is_wcf_hack_disabled (void)
3784 static gboolean disabled;
3785 static gboolean inited = FALSE;
3787 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3794 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) {
3795 MonoMethodSignature *cmsig, *imsig;
3796 if (strcmp (im->name, cm->name) == 0) {
3797 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3798 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3801 if (! slot_is_empty) {
3802 if (require_newslot) {
3803 if (! interface_is_explicitly_implemented_by_class) {
3804 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3807 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3808 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3812 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3815 cmsig = mono_method_signature (cm);
3816 imsig = mono_method_signature (im);
3817 if (!cmsig || !imsig) {
3818 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3822 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3823 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3824 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3825 TRACE_INTERFACE_VTABLE (printf ("]"));
3828 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3829 /* CAS - SecurityAction.InheritanceDemand on interface */
3830 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3831 mono_secman_inheritancedemand_method (cm, im);
3834 if (mono_security_core_clr_enabled ())
3835 mono_security_core_clr_check_override (class, cm, im);
3837 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3838 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3839 char *body_name = mono_method_full_name (cm, TRUE);
3840 char *decl_name = mono_method_full_name (im, TRUE);
3841 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));
3849 MonoClass *ic = im->klass;
3850 const char *ic_name_space = ic->name_space;
3851 const char *ic_name = ic->name;
3854 if (! require_newslot) {
3855 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3858 if (cm->klass->rank == 0) {
3859 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3862 cmsig = mono_method_signature (cm);
3863 imsig = mono_method_signature (im);
3864 if (!cmsig || !imsig) {
3865 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3869 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3870 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3871 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3872 TRACE_INTERFACE_VTABLE (printf ("]"));
3875 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3876 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3879 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3880 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3883 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))) {
3884 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3888 subname = strstr (cm->name, ic_name_space);
3889 if (subname != cm->name) {
3890 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3893 subname += strlen (ic_name_space);
3894 if (subname [0] != '.') {
3895 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3899 if (strstr (subname, ic_name) != subname) {
3900 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3903 subname += strlen (ic_name);
3904 if (subname [0] != '.') {
3905 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3909 if (strcmp (subname, im->name) != 0) {
3910 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3914 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3915 /* CAS - SecurityAction.InheritanceDemand on interface */
3916 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3917 mono_secman_inheritancedemand_method (cm, im);
3920 if (mono_security_core_clr_enabled ())
3921 mono_security_core_clr_check_override (class, cm, im);
3923 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3924 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3925 char *body_name = mono_method_full_name (cm, TRUE);
3926 char *decl_name = mono_method_full_name (im, TRUE);
3927 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));
3937 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3939 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3940 MonoMethod *method = key;
3941 MonoMethod *override = value;
3942 MonoClass *method_class = mono_method_get_class (method);
3943 MonoClass *override_class = mono_method_get_class (override);
3945 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3946 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3947 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3950 print_overrides (GHashTable *override_map, const char *message) {
3952 printf ("Override map \"%s\" START:\n", message);
3953 g_hash_table_foreach (override_map, foreach_override, NULL);
3954 printf ("Override map \"%s\" END.\n", message);
3956 printf ("Override map \"%s\" EMPTY.\n", message);
3960 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3961 char *full_name = mono_type_full_name (&class->byval_arg);
3965 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3967 if (print_interfaces) {
3968 print_implemented_interfaces (class);
3969 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3972 if (class->parent) {
3973 parent_size = class->parent->vtable_size;
3977 for (i = 0; i < size; ++i) {
3978 MonoMethod *cm = vtable [i];
3979 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3980 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3982 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3990 #if VERIFY_INTERFACE_VTABLE_CODE
3992 mono_method_try_get_vtable_index (MonoMethod *method)
3994 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3995 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3996 if (imethod->declaring->is_generic)
3997 return imethod->declaring->slot;
3999 return method->slot;
4003 mono_class_verify_vtable (MonoClass *class)
4006 char *full_name = mono_type_full_name (&class->byval_arg);
4008 printf ("*** Verifying VTable of class '%s' \n", full_name);
4012 if (!class->methods)
4015 for (i = 0; i < class->method.count; ++i) {
4016 MonoMethod *cm = class->methods [i];
4019 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4023 full_name = mono_method_full_name (cm, TRUE);
4025 slot = mono_method_try_get_vtable_index (cm);
4027 if (slot >= class->vtable_size) {
4028 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4032 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4033 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4034 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4035 g_free (other_name);
4038 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4045 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4047 char *method_signature;
4050 for (index = 0; index < onum; ++index) {
4051 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4052 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4054 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4055 type_name = mono_type_full_name (&class->byval_arg);
4056 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4057 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4058 g_free (method_signature);
4060 mono_class_setup_methods (class);
4061 if (class->exception_type) {
4062 char *name = mono_type_get_full_name (class);
4063 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4067 for (index = 0; index < class->method.count; ++index) {
4068 MonoMethod *cm = class->methods [index];
4069 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4071 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4072 g_free (method_signature);
4077 mono_method_get_method_definition (MonoMethod *method)
4079 while (method->is_inflated)
4080 method = ((MonoMethodInflated*)method)->declaring;
4085 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4089 for (i = 0; i < onum; ++i) {
4090 MonoMethod *decl = overrides [i * 2];
4091 MonoMethod *body = overrides [i * 2 + 1];
4093 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4094 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4098 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4099 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4100 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4102 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4106 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4107 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4108 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4110 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4114 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4115 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4119 body = mono_method_get_method_definition (body);
4120 decl = mono_method_get_method_definition (decl);
4122 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4123 char *body_name = mono_method_full_name (body, TRUE);
4124 char *decl_name = mono_method_full_name (decl, TRUE);
4125 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));
4135 mono_class_need_stelemref_method (MonoClass *class)
4137 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4141 * LOCKING: this is supposed to be called with the loader lock held.
4144 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4148 MonoMethod **vtable;
4149 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4150 GPtrArray *ifaces = NULL;
4151 GHashTable *override_map = NULL;
4152 gboolean security_enabled = mono_security_enabled ();
4154 gpointer class_iter;
4155 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4156 int first_non_interface_slot;
4158 GSList *virt_methods = NULL, *l;
4159 int stelemref_slot = 0;
4164 if (overrides && !verify_class_overrides (class, overrides, onum))
4167 ifaces = mono_class_get_implemented_interfaces (class, &error);
4168 if (!mono_error_ok (&error)) {
4169 char *name = mono_type_get_full_name (class);
4170 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)));
4172 mono_error_cleanup (&error);
4174 } else if (ifaces) {
4175 for (i = 0; i < ifaces->len; i++) {
4176 MonoClass *ic = g_ptr_array_index (ifaces, i);
4177 max_vtsize += ic->method.count;
4179 g_ptr_array_free (ifaces, TRUE);
4183 if (class->parent) {
4184 mono_class_init (class->parent);
4185 mono_class_setup_vtable_full (class->parent, in_setup);
4187 if (class->parent->exception_type) {
4188 char *name = mono_type_get_full_name (class->parent);
4189 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4194 max_vtsize += class->parent->vtable_size;
4195 cur_slot = class->parent->vtable_size;
4198 max_vtsize += class->method.count;
4200 /*Array have a slot for stelemref*/
4201 if (mono_class_need_stelemref_method (class)) {
4202 stelemref_slot = cur_slot;
4207 vtable = alloca (sizeof (gpointer) * max_vtsize);
4208 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4210 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4212 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4213 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4216 max_iid = class->max_interface_id;
4217 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4219 /* Optimized version for generic instances */
4220 if (class->generic_class) {
4222 MonoClass *gklass = class->generic_class->container_class;
4225 mono_class_setup_vtable_full (gklass, in_setup);
4226 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4227 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4231 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4232 class->vtable_size = gklass->vtable_size;
4233 for (i = 0; i < gklass->vtable_size; ++i)
4234 if (gklass->vtable [i]) {
4235 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4236 if (!mono_error_ok (&error)) {
4237 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4238 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4240 mono_error_cleanup (&error);
4244 tmp [i]->slot = gklass->vtable [i]->slot;
4246 mono_memory_barrier ();
4247 class->vtable = tmp;
4249 /* Have to set method->slot for abstract virtual methods */
4250 if (class->methods && gklass->methods) {
4251 for (i = 0; i < class->method.count; ++i)
4252 if (class->methods [i]->slot == -1)
4253 class->methods [i]->slot = gklass->methods [i]->slot;
4259 if (class->parent && class->parent->vtable_size) {
4260 MonoClass *parent = class->parent;
4263 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4265 // Also inherit parent interface vtables, just as a starting point.
4266 // This is needed otherwise bug-77127.exe fails when the property methods
4267 // have different names in the iterface and the class, because for child
4268 // classes the ".override" information is not used anymore.
4269 for (i = 0; i < parent->interface_offsets_count; i++) {
4270 MonoClass *parent_interface = parent->interfaces_packed [i];
4271 int interface_offset = mono_class_interface_offset (class, parent_interface);
4272 /*FIXME this is now dead code as this condition will never hold true.
4273 Since interface offsets are inherited then the offset of an interface implemented
4274 by a parent will never be the out of it's vtable boundary.
4276 if (interface_offset >= parent->vtable_size) {
4277 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4280 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4281 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4282 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4283 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4284 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4285 parent_interface_offset + j, parent_interface_offset, j,
4286 interface_offset + j, interface_offset, j));
4293 /*Array have a slot for stelemref*/
4294 if (mono_class_need_stelemref_method (class)) {
4295 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4297 method->slot = stelemref_slot;
4299 g_assert (method->slot == stelemref_slot);
4301 vtable [stelemref_slot] = method;
4304 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4305 /* override interface methods */
4306 for (i = 0; i < onum; i++) {
4307 MonoMethod *decl = overrides [i*2];
4308 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4310 dslot = mono_method_get_vtable_slot (decl);
4312 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4316 dslot += mono_class_interface_offset (class, decl->klass);
4317 vtable [dslot] = overrides [i*2 + 1];
4318 vtable [dslot]->slot = dslot;
4320 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4322 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4324 if (mono_security_core_clr_enabled ())
4325 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4328 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4329 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4332 * Create a list of virtual methods to avoid calling
4333 * mono_class_get_virtual_methods () which is slow because of the metadata
4337 gpointer iter = NULL;
4340 virt_methods = NULL;
4341 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4342 virt_methods = g_slist_prepend (virt_methods, cm);
4344 if (class->exception_type)
4348 // Loop on all implemented interfaces...
4349 for (i = 0; i < class->interface_offsets_count; i++) {
4350 MonoClass *parent = class->parent;
4352 gboolean interface_is_explicitly_implemented_by_class;
4355 ic = class->interfaces_packed [i];
4356 ic_offset = mono_class_interface_offset (class, ic);
4358 mono_class_setup_methods (ic);
4359 if (ic->exception_type)
4362 // Check if this interface is explicitly implemented (instead of just inherited)
4363 if (parent != NULL) {
4364 int implemented_interfaces_index;
4365 interface_is_explicitly_implemented_by_class = FALSE;
4366 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4367 if (ic == class->interfaces [implemented_interfaces_index]) {
4368 interface_is_explicitly_implemented_by_class = TRUE;
4373 interface_is_explicitly_implemented_by_class = TRUE;
4376 // Loop on all interface methods...
4377 for (im_index = 0; im_index < ic->method.count; im_index++) {
4378 MonoMethod *im = ic->methods [im_index];
4379 int im_slot = ic_offset + im->slot;
4380 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4382 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4385 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4387 // If there is an explicit implementation, just use it right away,
4388 // otherwise look for a matching method
4389 if (override_im == NULL) {
4394 // First look for a suitable method among the class methods
4396 for (l = virt_methods; l; l = l->next) {
4398 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)));
4399 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4400 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4401 vtable [im_slot] = cm;
4402 /* Why do we need this? */
4407 TRACE_INTERFACE_VTABLE (printf ("\n"));
4408 if (class->exception_type) /*Might be set by check_interface_method_override*/
4412 // If the slot is still empty, look in all the inherited virtual methods...
4413 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4414 MonoClass *parent = class->parent;
4415 // Reverse order, so that last added methods are preferred
4416 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4417 MonoMethod *cm = parent->vtable [cm_index];
4419 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));
4420 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4421 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4422 vtable [im_slot] = cm;
4423 /* Why do we need this? */
4429 if (class->exception_type) /*Might be set by check_interface_method_override*/
4431 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4435 g_assert (vtable [im_slot] == override_im);
4440 // If the class is not abstract, check that all its interface slots are full.
4441 // The check is done here and not directly at the end of the loop above because
4442 // it can happen (for injected generic array interfaces) that the same slot is
4443 // processed multiple times (those interfaces have overlapping slots), and it
4444 // will not always be the first pass the one that fills the slot.
4445 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4446 for (i = 0; i < class->interface_offsets_count; i++) {
4450 ic = class->interfaces_packed [i];
4451 ic_offset = mono_class_interface_offset (class, ic);
4453 for (im_index = 0; im_index < ic->method.count; im_index++) {
4454 MonoMethod *im = ic->methods [im_index];
4455 int im_slot = ic_offset + im->slot;
4457 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4460 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4461 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4462 if (vtable [im_slot] == NULL) {
4463 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4470 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4472 for (l = virt_methods; l; l = l->next) {
4475 * If the method is REUSE_SLOT, we must check in the
4476 * base class for a method to override.
4478 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4480 for (k = class->parent; k ; k = k->parent) {
4485 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4486 MonoMethodSignature *cmsig, *m1sig;
4488 cmsig = mono_method_signature (cm);
4489 m1sig = mono_method_signature (m1);
4491 if (!cmsig || !m1sig) {
4492 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4496 if (!strcmp(cm->name, m1->name) &&
4497 mono_metadata_signature_equal (cmsig, m1sig)) {
4499 /* CAS - SecurityAction.InheritanceDemand */
4500 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4501 mono_secman_inheritancedemand_method (cm, m1);
4504 if (mono_security_core_clr_enabled ())
4505 mono_security_core_clr_check_override (class, cm, m1);
4507 slot = mono_method_get_vtable_slot (m1);
4511 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4512 char *body_name = mono_method_full_name (cm, TRUE);
4513 char *decl_name = mono_method_full_name (m1, TRUE);
4514 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));
4520 g_assert (cm->slot < max_vtsize);
4522 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4523 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4524 mono_method_full_name (m1, 1), m1,
4525 mono_method_full_name (cm, 1), cm));
4526 g_hash_table_insert (override_map, m1, cm);
4530 if (k->exception_type)
4540 /*Non final newslot methods must be given a non-interface vtable slot*/
4541 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4545 cm->slot = cur_slot++;
4547 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4548 vtable [cm->slot] = cm;
4551 /* override non interface methods */
4552 for (i = 0; i < onum; i++) {
4553 MonoMethod *decl = overrides [i*2];
4554 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4555 g_assert (decl->slot != -1);
4556 vtable [decl->slot] = overrides [i*2 + 1];
4557 overrides [i * 2 + 1]->slot = decl->slot;
4559 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4560 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4561 mono_method_full_name (decl, 1), decl,
4562 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4563 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4565 if (mono_security_core_clr_enabled ())
4566 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4571 * If a method occupies more than one place in the vtable, and it is
4572 * overriden, then change the other occurances too.
4577 for (i = 0; i < max_vtsize; ++i)
4579 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4581 cm = g_hash_table_lookup (override_map, vtable [i]);
4586 g_hash_table_destroy (override_map);
4587 override_map = NULL;
4590 g_slist_free (virt_methods);
4591 virt_methods = NULL;
4593 /* Ensure that all vtable slots are filled with concrete instance methods */
4594 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4595 for (i = 0; i < cur_slot; ++i) {
4596 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4597 char *type_name = mono_type_get_full_name (class);
4598 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4599 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));
4601 g_free (method_name);
4607 if (class->generic_class) {
4608 MonoClass *gklass = class->generic_class->container_class;
4610 mono_class_init (gklass);
4612 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4614 /* Check that the vtable_size value computed in mono_class_init () is correct */
4615 if (class->vtable_size)
4616 g_assert (cur_slot == class->vtable_size);
4617 class->vtable_size = cur_slot;
4620 /* Try to share the vtable with our parent. */
4621 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4622 mono_memory_barrier ();
4623 class->vtable = class->parent->vtable;
4625 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4626 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4627 mono_memory_barrier ();
4628 class->vtable = tmp;
4631 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4632 if (mono_print_vtable) {
4635 print_implemented_interfaces (class);
4637 for (i = 0; i <= max_iid; i++)
4638 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4641 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4642 class->vtable_size, icount);
4644 for (i = 0; i < cur_slot; ++i) {
4649 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4650 mono_method_full_name (cm, TRUE));
4656 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4657 class->name, max_iid);
4659 for (i = 0; i < class->interface_count; i++) {
4660 ic = class->interfaces [i];
4661 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4662 mono_class_interface_offset (class, ic),
4663 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4666 for (k = class->parent; k ; k = k->parent) {
4667 for (i = 0; i < k->interface_count; i++) {
4668 ic = k->interfaces [i];
4669 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4670 mono_class_interface_offset (class, ic),
4671 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4677 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4682 char *name = mono_type_get_full_name (class);
4683 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4686 g_hash_table_destroy (override_map);
4688 g_slist_free (virt_methods);
4693 * mono_method_get_vtable_slot:
4695 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4696 * LOCKING: Acquires the loader lock.
4698 * FIXME Use proper MonoError machinery here.
4701 mono_method_get_vtable_slot (MonoMethod *method)
4703 if (method->slot == -1) {
4704 mono_class_setup_vtable (method->klass);
4705 if (method->klass->exception_type)
4707 if (method->slot == -1) {
4711 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4712 g_assert (method->klass->generic_class);
4713 gklass = method->klass->generic_class->container_class;
4714 mono_class_setup_methods (method->klass);
4715 g_assert (method->klass->methods);
4716 for (i = 0; i < method->klass->method.count; ++i) {
4717 if (method->klass->methods [i] == method)
4720 g_assert (i < method->klass->method.count);
4721 g_assert (gklass->methods);
4722 method->slot = gklass->methods [i]->slot;
4724 g_assert (method->slot != -1);
4726 return method->slot;
4730 * mono_method_get_vtable_index:
4733 * Returns the index into the runtime vtable to access the method or,
4734 * in the case of a virtual generic method, the virtual generic method
4735 * thunk. Returns -1 on failure.
4737 * FIXME Use proper MonoError machinery here.
4740 mono_method_get_vtable_index (MonoMethod *method)
4742 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4743 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4744 if (imethod->declaring->is_generic)
4745 return mono_method_get_vtable_slot (imethod->declaring);
4747 return mono_method_get_vtable_slot (method);
4750 static MonoMethod *default_ghc = NULL;
4751 static MonoMethod *default_finalize = NULL;
4752 static int finalize_slot = -1;
4753 static int ghc_slot = -1;
4756 initialize_object_slots (MonoClass *class)
4761 if (class == mono_defaults.object_class) {
4762 mono_class_setup_vtable (class);
4763 for (i = 0; i < class->vtable_size; ++i) {
4764 MonoMethod *cm = class->vtable [i];
4766 if (!strcmp (cm->name, "GetHashCode"))
4768 else if (!strcmp (cm->name, "Finalize"))
4772 g_assert (ghc_slot > 0);
4773 default_ghc = class->vtable [ghc_slot];
4775 g_assert (finalize_slot > 0);
4776 default_finalize = class->vtable [finalize_slot];
4781 MonoMethod *array_method;
4783 } GenericArrayMethodInfo;
4785 static int generic_array_method_num = 0;
4786 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4789 generic_array_methods (MonoClass *class)
4791 int i, count_generic = 0;
4792 GList *list = NULL, *tmp;
4793 if (generic_array_method_num)
4794 return generic_array_method_num;
4795 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4796 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4797 for (i = 0; i < class->parent->method.count; i++) {
4798 MonoMethod *m = class->parent->methods [i];
4799 if (!strncmp (m->name, "InternalArray__", 15)) {
4801 list = g_list_prepend (list, m);
4804 list = g_list_reverse (list);
4805 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4807 for (tmp = list; tmp; tmp = tmp->next) {
4808 const char *mname, *iname;
4810 MonoMethod *m = tmp->data;
4811 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4812 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4814 generic_array_method_info [i].array_method = m;
4815 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4816 iname = "System.Collections.Generic.ICollection`1.";
4817 mname = m->name + 27;
4818 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4819 iname = "System.Collections.Generic.IEnumerable`1.";
4820 mname = m->name + 27;
4821 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4822 iname = "System.Collections.Generic.IReadOnlyList`1.";
4823 mname = m->name + strlen (ireadonlylist_prefix);
4824 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4825 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4826 mname = m->name + strlen (ireadonlycollection_prefix);
4827 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4828 iname = "System.Collections.Generic.IList`1.";
4829 mname = m->name + 15;
4831 g_assert_not_reached ();
4834 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4835 strcpy (name, iname);
4836 strcpy (name + strlen (iname), mname);
4837 generic_array_method_info [i].name = name;
4840 /*g_print ("array generic methods: %d\n", count_generic);*/
4842 generic_array_method_num = count_generic;
4844 return generic_array_method_num;
4848 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4850 MonoGenericContext tmp_context;
4853 tmp_context.class_inst = NULL;
4854 tmp_context.method_inst = iface->generic_class->context.class_inst;
4855 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4857 for (i = 0; i < generic_array_method_num; i++) {
4858 MonoMethod *m = generic_array_method_info [i].array_method;
4859 MonoMethod *inflated;
4861 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4862 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4867 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4869 int null_length = strlen ("(null)");
4870 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4871 char *s = mono_image_alloc (image, len);
4874 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4875 g_assert (result == len - 1);
4881 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4883 gpointer exception_data = NULL;
4885 switch (error->exception_type) {
4886 case MONO_EXCEPTION_TYPE_LOAD:
4887 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4890 case MONO_EXCEPTION_MISSING_METHOD:
4891 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4894 case MONO_EXCEPTION_MISSING_FIELD: {
4895 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4896 const char *class_name;
4899 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4901 class_name = error->klass->name;
4903 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4906 g_free ((void*)class_name);
4910 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4913 if (error->ref_only)
4914 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.";
4916 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4918 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4922 case MONO_EXCEPTION_BAD_IMAGE:
4923 exception_data = error->msg;
4927 g_assert_not_reached ();
4930 mono_class_set_failure (class, error->exception_type, exception_data);
4935 * @class: the class to initialize
4937 * Compute the instance_size, class_size and other infos that cannot be
4938 * computed at mono_class_get() time. Also compute vtable_size if possible.
4939 * Returns TRUE on success or FALSE if there was a problem in loading
4940 * the type (incorrect assemblies, missing assemblies, methods, etc).
4942 * LOCKING: Acquires the loader lock.
4945 mono_class_init (MonoClass *class)
4948 MonoCachedClassInfo cached_info;
4949 gboolean has_cached_info;
4953 /* Double-checking locking pattern */
4954 if (class->inited || class->exception_type)
4955 return class->exception_type == MONO_EXCEPTION_NONE;
4957 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4959 /* We do everything inside the lock to prevent races */
4960 mono_loader_lock ();
4962 if (class->inited || class->exception_type) {
4963 mono_loader_unlock ();
4964 /* Somebody might have gotten in before us */
4965 return class->exception_type == MONO_EXCEPTION_NONE;
4968 if (class->init_pending) {
4969 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4973 class->init_pending = 1;
4975 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4976 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4981 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4982 MonoClass *element_class = class->element_class;
4983 if (!element_class->inited)
4984 mono_class_init (element_class);
4985 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4986 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4991 /* CAS - SecurityAction.InheritanceDemand */
4992 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4993 mono_secman_inheritancedemand_class (class, class->parent);
4996 mono_stats.initialized_class_count++;
4998 if (class->generic_class && !class->generic_class->is_dynamic) {
4999 MonoClass *gklass = class->generic_class->container_class;
5001 mono_stats.generic_class_count++;
5003 class->method = gklass->method;
5004 class->field = gklass->field;
5006 mono_class_init (gklass);
5007 // FIXME: Why is this needed ?
5008 if (!gklass->exception_type)
5009 mono_class_setup_methods (gklass);
5010 if (gklass->exception_type) {
5011 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5015 if (MONO_CLASS_IS_INTERFACE (class))
5016 class->interface_id = mono_get_unique_iid (class);
5019 if (class->parent && !class->parent->inited)
5020 mono_class_init (class->parent);
5022 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5024 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5025 class->nested_classes_inited = TRUE;
5028 * Computes the size used by the fields, and their locations
5030 if (has_cached_info) {
5031 class->instance_size = cached_info.instance_size;
5032 class->sizes.class_size = cached_info.class_size;
5033 class->packing_size = cached_info.packing_size;
5034 class->min_align = cached_info.min_align;
5035 class->blittable = cached_info.blittable;
5036 class->has_references = cached_info.has_references;
5037 class->has_static_refs = cached_info.has_static_refs;
5038 class->no_special_static_fields = cached_info.no_special_static_fields;
5041 if (!class->size_inited){
5042 mono_class_setup_fields (class);
5043 if (class->exception_type || mono_loader_get_last_error ())
5047 /* Initialize arrays */
5049 class->method.count = 3 + (class->rank > 1? 2: 1);
5051 if (class->interface_count) {
5052 int count_generic = generic_array_methods (class);
5053 class->method.count += class->interface_count * count_generic;
5057 mono_class_setup_supertypes (class);
5060 initialize_object_slots (class);
5063 * Initialize the rest of the data without creating a generic vtable if possible.
5064 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5065 * also avoid computing a generic vtable.
5067 if (has_cached_info) {
5069 class->vtable_size = cached_info.vtable_size;
5070 class->has_finalize = cached_info.has_finalize;
5071 class->has_finalize_inited = TRUE;
5072 class->ghcimpl = cached_info.ghcimpl;
5073 class->has_cctor = cached_info.has_cctor;
5074 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5075 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5076 * The first slot if for array with.
5078 static int szarray_vtable_size[2] = { 0 };
5080 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5083 if (!szarray_vtable_size [slot]) {
5084 mono_class_setup_vtable (class);
5085 szarray_vtable_size [slot] = class->vtable_size;
5087 class->vtable_size = szarray_vtable_size[slot];
5089 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5090 MonoClass *gklass = class->generic_class->container_class;
5092 /* Generic instance case */
5093 class->ghcimpl = gklass->ghcimpl;
5094 class->has_cctor = gklass->has_cctor;
5096 mono_class_setup_vtable (gklass);
5097 if (gklass->exception_type) {
5098 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5102 class->vtable_size = gklass->vtable_size;
5106 /* ghcimpl is not currently used
5108 if (class->parent) {
5109 MonoMethod *cmethod = class->vtable [ghc_slot];
5110 if (cmethod->is_inflated)
5111 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5112 if (cmethod == default_ghc) {
5118 /* C# doesn't allow interfaces to have cctors */
5119 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5120 MonoMethod *cmethod = NULL;
5122 if (class->type_token) {
5123 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5124 /* The find_method function ignores the 'flags' argument */
5125 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5126 class->has_cctor = 1;
5128 mono_class_setup_methods (class);
5129 if (class->exception_type)
5132 for (i = 0; i < class->method.count; ++i) {
5133 MonoMethod *method = class->methods [i];
5134 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5135 (strcmp (".cctor", method->name) == 0)) {
5136 class->has_cctor = 1;
5144 if (class->parent) {
5145 int first_iface_slot;
5146 /* This will compute class->parent->vtable_size for some classes */
5147 mono_class_init (class->parent);
5148 if (class->parent->exception_type) {
5149 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5152 if (mono_loader_get_last_error ())
5154 if (!class->parent->vtable_size) {
5155 /* FIXME: Get rid of this somehow */
5156 mono_class_setup_vtable (class->parent);
5157 if (class->parent->exception_type) {
5158 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5161 if (mono_loader_get_last_error ())
5164 first_iface_slot = class->parent->vtable_size;
5165 if (mono_class_need_stelemref_method (class))
5167 setup_interface_offsets (class, first_iface_slot, TRUE);
5169 setup_interface_offsets (class, 0, TRUE);
5172 if (mono_security_core_clr_enabled ())
5173 mono_security_core_clr_check_inheritance (class);
5175 if (mono_loader_get_last_error ()) {
5176 if (class->exception_type == MONO_EXCEPTION_NONE) {
5177 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5179 mono_loader_clear_error ();
5182 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5183 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5188 /* Because of the double-checking locking pattern */
5189 mono_memory_barrier ();
5191 class->init_pending = 0;
5193 mono_loader_unlock ();
5195 if (mono_debugger_class_init_func)
5196 mono_debugger_class_init_func (class);
5198 return class->exception_type == MONO_EXCEPTION_NONE;
5202 * mono_class_has_finalizer:
5204 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5208 mono_class_has_finalizer (MonoClass *klass)
5210 MonoClass *class = klass;
5211 gboolean has_finalize = FALSE;
5213 if (klass->has_finalize_inited)
5214 return klass->has_finalize;
5216 /* Interfaces and valuetypes are not supposed to have finalizers */
5217 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5218 MonoMethod *cmethod = NULL;
5220 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5221 } else if (class->generic_class) {
5222 MonoClass *gklass = class->generic_class->container_class;
5224 has_finalize = mono_class_has_finalizer (gklass);
5225 } else if (class->parent && class->parent->has_finalize) {
5226 has_finalize = TRUE;
5228 if (class->parent) {
5230 * Can't search in metadata for a method named Finalize, because that
5231 * ignores overrides.
5233 mono_class_setup_vtable (class);
5234 if (class->exception_type || mono_loader_get_last_error ())
5237 cmethod = class->vtable [finalize_slot];
5241 g_assert (class->vtable_size > finalize_slot);
5243 if (class->parent) {
5244 if (cmethod->is_inflated)
5245 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5246 if (cmethod != default_finalize)
5247 has_finalize = TRUE;
5253 mono_image_lock (klass->image);
5255 if (!klass->has_finalize_inited) {
5256 klass->has_finalize = has_finalize ? 1 : 0;
5258 mono_memory_barrier ();
5259 klass->has_finalize_inited = TRUE;
5262 mono_image_unlock (klass->image);
5264 return klass->has_finalize;
5268 mono_is_corlib_image (MonoImage *image)
5270 /* FIXME: allow the dynamic case for our compilers and with full trust */
5271 if (image_is_dynamic (image))
5272 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5274 return image == mono_defaults.corlib;
5278 * LOCKING: this assumes the loader lock is held
5281 mono_class_setup_mono_type (MonoClass *class)
5283 const char *name = class->name;
5284 const char *nspace = class->name_space;
5285 gboolean is_corlib = mono_is_corlib_image (class->image);
5287 class->this_arg.byref = 1;
5288 class->this_arg.data.klass = class;
5289 class->this_arg.type = MONO_TYPE_CLASS;
5290 class->byval_arg.data.klass = class;
5291 class->byval_arg.type = MONO_TYPE_CLASS;
5293 if (is_corlib && !strcmp (nspace, "System")) {
5294 if (!strcmp (name, "ValueType")) {
5296 * do not set the valuetype bit for System.ValueType.
5297 * class->valuetype = 1;
5299 class->blittable = TRUE;
5300 } else if (!strcmp (name, "Enum")) {
5302 * do not set the valuetype bit for System.Enum.
5303 * class->valuetype = 1;
5305 class->valuetype = 0;
5306 class->enumtype = 0;
5307 } else if (!strcmp (name, "Object")) {
5308 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5309 } else if (!strcmp (name, "String")) {
5310 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5311 } else if (!strcmp (name, "TypedReference")) {
5312 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5316 if (class->valuetype) {
5317 int t = MONO_TYPE_VALUETYPE;
5319 if (is_corlib && !strcmp (nspace, "System")) {
5322 if (!strcmp (name, "Boolean")) {
5323 t = MONO_TYPE_BOOLEAN;
5324 } else if (!strcmp(name, "Byte")) {
5326 class->blittable = TRUE;
5330 if (!strcmp (name, "Char")) {
5335 if (!strcmp (name, "Double")) {
5337 class->blittable = TRUE;
5341 if (!strcmp (name, "Int32")) {
5343 class->blittable = TRUE;
5344 } else if (!strcmp(name, "Int16")) {
5346 class->blittable = TRUE;
5347 } else if (!strcmp(name, "Int64")) {
5349 class->blittable = TRUE;
5350 } else if (!strcmp(name, "IntPtr")) {
5352 class->blittable = TRUE;
5356 if (!strcmp (name, "Single")) {
5358 class->blittable = TRUE;
5359 } else if (!strcmp(name, "SByte")) {
5361 class->blittable = TRUE;
5365 if (!strcmp (name, "UInt32")) {
5367 class->blittable = TRUE;
5368 } else if (!strcmp(name, "UInt16")) {
5370 class->blittable = TRUE;
5371 } else if (!strcmp(name, "UInt64")) {
5373 class->blittable = TRUE;
5374 } else if (!strcmp(name, "UIntPtr")) {
5376 class->blittable = TRUE;
5380 if (!strcmp (name, "TypedReference")) {
5381 t = MONO_TYPE_TYPEDBYREF;
5382 class->blittable = TRUE;
5386 if (!strcmp (name, "Void")) {
5394 class->this_arg.type = class->byval_arg.type = t;
5397 if (MONO_CLASS_IS_INTERFACE (class))
5398 class->interface_id = mono_get_unique_iid (class);
5404 * COM initialization is delayed until needed.
5405 * However when a [ComImport] attribute is present on a type it will trigger
5406 * the initialization. This is not a problem unless the BCL being executed
5407 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5410 init_com_from_comimport (MonoClass *class)
5412 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5413 if (mono_security_core_clr_enabled ()) {
5414 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5415 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5416 /* but it can not be made available for application (i.e. user code) since all COM calls
5417 * are considered native calls. In this case we fail with a TypeLoadException (just like
5418 * Silverlight 2 does */
5419 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5424 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5426 #endif /*DISABLE_COM*/
5429 * LOCKING: this assumes the loader lock is held
5432 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5434 gboolean system_namespace;
5435 gboolean is_corlib = mono_is_corlib_image (class->image);
5437 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5439 /* if root of the hierarchy */
5440 if (system_namespace && !strcmp (class->name, "Object")) {
5441 class->parent = NULL;
5442 class->instance_size = sizeof (MonoObject);
5445 if (!strcmp (class->name, "<Module>")) {
5446 class->parent = NULL;
5447 class->instance_size = 0;
5451 if (!MONO_CLASS_IS_INTERFACE (class)) {
5452 /* Imported COM Objects always derive from __ComObject. */
5454 if (MONO_CLASS_IS_IMPORT (class)) {
5455 init_com_from_comimport (class);
5456 if (parent == mono_defaults.object_class)
5457 parent = mono_class_get_com_object_class ();
5461 /* set the parent to something useful and safe, but mark the type as broken */
5462 parent = mono_defaults.object_class;
5463 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5466 class->parent = parent;
5468 if (parent->generic_class && !parent->name) {
5470 * If the parent is a generic instance, we may get
5471 * called before it is fully initialized, especially
5472 * before it has its name.
5477 #ifndef DISABLE_REMOTING
5478 class->marshalbyref = parent->marshalbyref;
5479 class->contextbound = parent->contextbound;
5482 class->delegate = parent->delegate;
5484 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5485 mono_class_set_is_com_object (class);
5487 if (system_namespace) {
5488 #ifndef DISABLE_REMOTING
5489 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5490 class->marshalbyref = 1;
5492 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5493 class->contextbound = 1;
5495 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5496 class->delegate = 1;
5499 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5500 (strcmp (class->parent->name_space, "System") == 0)))
5501 class->valuetype = 1;
5502 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5503 class->valuetype = class->enumtype = 1;
5505 /*class->enumtype = class->parent->enumtype; */
5507 /* initialize com types if COM interfaces are present */
5509 if (MONO_CLASS_IS_IMPORT (class))
5510 init_com_from_comimport (class);
5512 class->parent = NULL;
5518 * mono_class_setup_supertypes:
5521 * Build the data structure needed to make fast type checks work.
5522 * This currently sets two fields in @class:
5523 * - idepth: distance between @class and System.Object in the type
5525 * - supertypes: array of classes: each element has a class in the hierarchy
5526 * starting from @class up to System.Object
5528 * LOCKING: This function is atomic, in case of contention we waste memory.
5531 mono_class_setup_supertypes (MonoClass *class)
5534 MonoClass **supertypes;
5536 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5540 if (class->parent && !class->parent->supertypes)
5541 mono_class_setup_supertypes (class->parent);
5543 class->idepth = class->parent->idepth + 1;
5547 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5548 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5550 if (class->parent) {
5551 supertypes [class->idepth - 1] = class;
5552 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5554 supertypes [0] = class;
5557 mono_atomic_store_release (&class->supertypes, supertypes);
5561 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5563 MonoClass *gtd = (MonoClass*)user_data;
5564 /* Only try to fix generic instances of @gtd */
5565 if (gclass->generic_class->container_class != gtd)
5568 /* Check if the generic instance has no parent. */
5569 if (gtd->parent && !gclass->parent)
5570 mono_generic_class_setup_parent (gclass, gtd);
5576 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5578 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5579 mono_error_set_type_load_class (error, class, msg);
5583 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5585 MonoLoaderError *lerror = mono_loader_get_last_error ();
5588 set_failure_from_loader_error (class, lerror);
5589 mono_error_set_from_loader_error (error);
5593 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5594 mono_error_set_type_load_class (error, class, msg);
5599 * mono_class_create_from_typedef:
5600 * @image: image where the token is valid
5601 * @type_token: typedef token
5602 * @error: used to return any error found while creating the type
5604 * Create the MonoClass* representing the specified type token.
5605 * @type_token must be a TypeDef token.
5607 * FIXME: don't return NULL on failure, just the the caller figure it out.
5610 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5612 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5613 MonoClass *class, *parent = NULL;
5614 guint32 cols [MONO_TYPEDEF_SIZE];
5615 guint32 cols_next [MONO_TYPEDEF_SIZE];
5616 guint tidx = mono_metadata_token_index (type_token);
5617 MonoGenericContext *context = NULL;
5618 const char *name, *nspace;
5620 MonoClass **interfaces;
5621 guint32 field_last, method_last;
5622 guint32 nesting_tokeen;
5624 mono_error_init (error);
5626 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5627 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5628 g_assert (!mono_loader_get_last_error ());
5632 mono_loader_lock ();
5634 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5635 mono_loader_unlock ();
5636 g_assert (!mono_loader_get_last_error ());
5640 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5642 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5643 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5645 class = mono_image_alloc0 (image, sizeof (MonoClass));
5648 class->name_space = nspace;
5650 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5652 class->image = image;
5653 class->type_token = type_token;
5654 class->flags = cols [MONO_TYPEDEF_FLAGS];
5656 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5658 classes_size += sizeof (MonoClass);
5661 * Check whether we're a generic type definition.
5663 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5664 if (class->generic_container) {
5665 class->is_generic = 1;
5666 class->generic_container->owner.klass = class;
5667 context = &class->generic_container->context;
5670 if (class->generic_container)
5671 enable_gclass_recording ();
5673 if (cols [MONO_TYPEDEF_EXTENDS]) {
5675 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5677 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5678 /*WARNING: this must satisfy mono_metadata_type_hash*/
5679 class->this_arg.byref = 1;
5680 class->this_arg.data.klass = class;
5681 class->this_arg.type = MONO_TYPE_CLASS;
5682 class->byval_arg.data.klass = class;
5683 class->byval_arg.type = MONO_TYPE_CLASS;
5685 parent = mono_class_get_full (image, parent_token, context);
5687 if (parent == NULL) {
5688 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5689 goto parent_failure;
5692 for (tmp = parent; tmp; tmp = tmp->parent) {
5694 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5695 goto parent_failure;
5697 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5698 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5699 goto parent_failure;
5704 mono_class_setup_parent (class, parent);
5706 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5707 mono_class_setup_mono_type (class);
5709 if (class->generic_container)
5710 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5713 * This might access class->byval_arg for recursion generated by generic constraints,
5714 * so it has to come after setup_mono_type ().
5716 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5717 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5718 if (!mono_error_ok (error)) {
5719 /*FIXME implement a mono_class_set_failure_from_mono_error */
5720 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5721 mono_loader_unlock ();
5722 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5723 g_assert (!mono_loader_get_last_error ());
5728 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5732 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5736 class->cast_class = class->element_class = class;
5738 if (!class->enumtype) {
5739 if (!mono_metadata_interfaces_from_typedef_full (
5740 image, type_token, &interfaces, &icount, FALSE, context)){
5741 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5742 mono_loader_unlock ();
5743 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5747 class->interfaces = interfaces;
5748 class->interface_count = icount;
5749 class->interfaces_inited = 1;
5752 /*g_print ("Load class %s\n", name);*/
5755 * Compute the field and method lists
5757 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5758 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5760 if (tt->rows > tidx){
5761 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5762 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5763 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5765 field_last = image->tables [MONO_TABLE_FIELD].rows;
5766 method_last = image->tables [MONO_TABLE_METHOD].rows;
5769 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5770 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5771 class->field.count = field_last - class->field.first;
5773 class->field.count = 0;
5775 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5776 class->method.count = method_last - class->method.first;
5778 class->method.count = 0;
5780 /* reserve space to store vector pointer in arrays */
5781 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5782 class->instance_size += 2 * sizeof (gpointer);
5783 g_assert (class->field.count == 0);
5786 if (class->enumtype) {
5787 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5788 if (!enum_basetype) {
5789 /*set it to a default value as the whole runtime can't handle this to be null*/
5790 class->cast_class = class->element_class = mono_defaults.int32_class;
5791 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5792 mono_loader_unlock ();
5793 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5794 g_assert (!mono_loader_get_last_error ());
5797 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5801 * If we're a generic type definition, load the constraints.
5802 * We must do this after the class has been constructed to make certain recursive scenarios
5805 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5806 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5807 mono_loader_unlock ();
5808 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5809 g_assert (!mono_loader_get_last_error ());
5813 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5814 if (!strncmp (name, "Vector", 6))
5815 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");
5818 mono_loader_unlock ();
5820 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5821 g_assert (!mono_loader_get_last_error ());
5826 mono_class_setup_mono_type (class);
5827 mono_loader_unlock ();
5828 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5829 g_assert (!mono_loader_get_last_error ());
5833 /** is klass Nullable<T>? */
5835 mono_class_is_nullable (MonoClass *klass)
5837 return klass->generic_class != NULL &&
5838 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5842 /** if klass is T? return T */
5844 mono_class_get_nullable_param (MonoClass *klass)
5846 g_assert (mono_class_is_nullable (klass));
5847 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5851 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5855 MonoGenericClass *gclass = klass->generic_class;
5857 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5858 if (!mono_error_ok (&error)) {
5859 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5860 klass->parent = mono_defaults.object_class;
5861 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5862 mono_error_cleanup (&error);
5866 mono_class_setup_parent (klass, klass->parent);
5868 if (klass->enumtype) {
5869 klass->cast_class = gtd->cast_class;
5870 klass->element_class = gtd->element_class;
5876 * Create the `MonoClass' for an instantiation of a generic type.
5877 * We only do this if we actually need it.
5880 mono_generic_class_get_class (MonoGenericClass *gclass)
5882 MonoClass *klass, *gklass;
5884 if (gclass->cached_class)
5885 return gclass->cached_class;
5887 mono_loader_lock ();
5888 if (gclass->cached_class) {
5889 mono_loader_unlock ();
5890 return gclass->cached_class;
5893 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5895 gklass = gclass->container_class;
5897 if (record_gclass_instantiation > 0)
5898 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5900 if (gklass->nested_in) {
5901 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5902 klass->nested_in = gklass->nested_in;
5905 klass->name = gklass->name;
5906 klass->name_space = gklass->name_space;
5908 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5910 klass->image = gklass->image;
5911 klass->flags = gklass->flags;
5912 klass->type_token = gklass->type_token;
5913 klass->field.count = gklass->field.count;
5915 klass->is_inflated = 1;
5916 klass->generic_class = gclass;
5918 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5919 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5920 klass->this_arg.byref = TRUE;
5921 klass->enumtype = gklass->enumtype;
5922 klass->valuetype = gklass->valuetype;
5924 klass->cast_class = klass->element_class = klass;
5926 if (mono_class_is_nullable (klass))
5927 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5930 * We're not interested in the nested classes of a generic instance.
5931 * We use the generic type definition to look for nested classes.
5934 mono_generic_class_setup_parent (klass, gklass);
5936 if (gclass->is_dynamic) {
5939 mono_class_setup_supertypes (klass);
5941 if (klass->enumtype) {
5943 * For enums, gklass->fields might not been set, but instance_size etc. is
5944 * already set in mono_reflection_create_internal_class (). For non-enums,
5945 * these will be computed normally in mono_class_layout_fields ().
5947 klass->instance_size = gklass->instance_size;
5948 klass->sizes.class_size = gklass->sizes.class_size;
5949 mono_memory_barrier ();
5950 klass->size_inited = 1;
5954 mono_memory_barrier ();
5955 gclass->cached_class = klass;
5957 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5959 inflated_classes ++;
5960 inflated_classes_size += sizeof (MonoClass);
5962 mono_loader_unlock ();
5968 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5970 MonoClass *klass, **ptr;
5972 MonoGenericContainer *container = mono_generic_param_owner (param);
5976 image = mono_defaults.corlib;
5978 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5979 classes_size += sizeof (MonoClass);
5982 klass->name = pinfo->name;
5984 int n = mono_generic_param_num (param);
5985 klass->name = mono_image_alloc0 (image, 16);
5986 sprintf ((char*)klass->name, "%d", n);
5991 MonoMethod *omethod = container->owner.method;
5992 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5994 MonoClass *oklass = container->owner.klass;
5995 klass->name_space = oklass ? oklass->name_space : "";
5998 klass->name_space = "";
6001 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6005 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6009 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6010 klass->parent = pinfo->constraints [0];
6012 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6013 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6015 klass->parent = mono_defaults.object_class;
6018 if (count - pos > 0) {
6019 klass->interface_count = count - pos;
6020 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6021 klass->interfaces_inited = TRUE;
6022 for (i = pos; i < count; i++)
6023 klass->interfaces [i - pos] = pinfo->constraints [i];
6026 klass->image = image;
6028 klass->inited = TRUE;
6029 klass->cast_class = klass->element_class = klass;
6030 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6032 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6033 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6034 klass->this_arg.byref = TRUE;
6036 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6037 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6039 /*Init these fields to sane values*/
6040 klass->min_align = 1;
6041 klass->instance_size = sizeof (gpointer);
6042 mono_memory_barrier ();
6043 klass->size_inited = 1;
6045 mono_class_setup_supertypes (klass);
6047 if (count - pos > 0) {
6048 mono_class_setup_vtable (klass->parent);
6049 if (klass->parent->exception_type)
6050 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6052 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6058 #define FAST_CACHE_SIZE 16
6061 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6063 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6064 MonoImage *image = param->image;
6069 if (n < FAST_CACHE_SIZE) {
6071 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6073 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6075 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6076 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6081 * LOCKING: Acquires the loader lock.
6084 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6086 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6087 MonoImage *image = param->image;
6092 if (n < FAST_CACHE_SIZE) {
6094 /* No locking needed */
6095 if (!image->mvar_cache_fast)
6096 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6097 image->mvar_cache_fast [n] = klass;
6099 if (!image->var_cache_fast)
6100 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6101 image->var_cache_fast [n] = klass;
6105 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6107 mono_image_lock (image);
6108 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6110 ht = g_hash_table_new (NULL, NULL);
6111 mono_memory_barrier ();
6113 image->mvar_cache_slow = ht;
6115 image->var_cache_slow = ht;
6117 mono_image_unlock (image);
6120 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6124 * LOCKING: Acquires the loader lock.
6127 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6129 MonoGenericContainer *container = mono_generic_param_owner (param);
6130 MonoGenericParamInfo *pinfo;
6133 mono_loader_lock ();
6136 pinfo = mono_generic_param_info (param);
6137 if (pinfo->pklass) {
6138 mono_loader_unlock ();
6139 return pinfo->pklass;
6145 klass = get_anon_gparam_class (param, is_mvar);
6147 mono_loader_unlock ();
6152 if (!image && container) {
6154 MonoMethod *method = container->owner.method;
6155 image = (method && method->klass) ? method->klass->image : NULL;
6157 MonoClass *klass = container->owner.klass;
6158 // FIXME: 'klass' should not be null
6159 // But, monodis creates GenericContainers without associating a owner to it
6160 image = klass ? klass->image : NULL;
6164 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6166 mono_memory_barrier ();
6169 pinfo->pklass = klass;
6171 set_anon_gparam_class (param, is_mvar, klass);
6173 mono_loader_unlock ();
6175 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6176 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6182 mono_ptr_class_get (MonoType *type)
6185 MonoClass *el_class;
6189 el_class = mono_class_from_mono_type (type);
6190 image = el_class->image;
6192 mono_loader_lock ();
6194 if (!image->ptr_cache)
6195 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6197 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6198 mono_loader_unlock ();
6201 result = mono_image_alloc0 (image, sizeof (MonoClass));
6203 classes_size += sizeof (MonoClass);
6205 result->parent = NULL; /* no parent for PTR types */
6206 result->name_space = el_class->name_space;
6207 name = g_strdup_printf ("%s*", el_class->name);
6208 result->name = mono_image_strdup (image, name);
6211 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6213 result->image = el_class->image;
6214 result->inited = TRUE;
6215 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6216 /* Can pointers get boxed? */
6217 result->instance_size = sizeof (gpointer);
6218 result->cast_class = result->element_class = el_class;
6219 result->blittable = TRUE;
6221 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6222 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6223 result->this_arg.byref = TRUE;
6225 mono_class_setup_supertypes (result);
6227 g_hash_table_insert (image->ptr_cache, el_class, result);
6229 mono_loader_unlock ();
6231 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6237 mono_fnptr_class_get (MonoMethodSignature *sig)
6240 static GHashTable *ptr_hash = NULL;
6242 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6244 mono_loader_lock ();
6247 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6249 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6250 mono_loader_unlock ();
6253 result = g_new0 (MonoClass, 1);
6255 result->parent = NULL; /* no parent for PTR types */
6256 result->name_space = "System";
6257 result->name = "MonoFNPtrFakeClass";
6259 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6261 result->image = mono_defaults.corlib; /* need to fix... */
6262 result->inited = TRUE;
6263 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6264 /* Can pointers get boxed? */
6265 result->instance_size = sizeof (gpointer);
6266 result->cast_class = result->element_class = result;
6267 result->blittable = TRUE;
6269 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6270 result->this_arg.data.method = result->byval_arg.data.method = sig;
6271 result->this_arg.byref = TRUE;
6272 result->blittable = TRUE;
6274 mono_class_setup_supertypes (result);
6276 g_hash_table_insert (ptr_hash, sig, result);
6278 mono_loader_unlock ();
6280 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6286 mono_class_from_mono_type (MonoType *type)
6288 switch (type->type) {
6289 case MONO_TYPE_OBJECT:
6290 return type->data.klass? type->data.klass: mono_defaults.object_class;
6291 case MONO_TYPE_VOID:
6292 return type->data.klass? type->data.klass: mono_defaults.void_class;
6293 case MONO_TYPE_BOOLEAN:
6294 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6295 case MONO_TYPE_CHAR:
6296 return type->data.klass? type->data.klass: mono_defaults.char_class;
6298 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6300 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6302 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6304 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6306 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6308 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6310 return type->data.klass? type->data.klass: mono_defaults.int_class;
6312 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6314 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6316 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6318 return type->data.klass? type->data.klass: mono_defaults.single_class;
6320 return type->data.klass? type->data.klass: mono_defaults.double_class;
6321 case MONO_TYPE_STRING:
6322 return type->data.klass? type->data.klass: mono_defaults.string_class;
6323 case MONO_TYPE_TYPEDBYREF:
6324 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6325 case MONO_TYPE_ARRAY:
6326 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6328 return mono_ptr_class_get (type->data.type);
6329 case MONO_TYPE_FNPTR:
6330 return mono_fnptr_class_get (type->data.method);
6331 case MONO_TYPE_SZARRAY:
6332 return mono_array_class_get (type->data.klass, 1);
6333 case MONO_TYPE_CLASS:
6334 case MONO_TYPE_VALUETYPE:
6335 return type->data.klass;
6336 case MONO_TYPE_GENERICINST:
6337 return mono_generic_class_get_class (type->data.generic_class);
6339 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6340 case MONO_TYPE_MVAR:
6341 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6343 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6344 g_assert_not_reached ();
6351 * mono_type_retrieve_from_typespec
6352 * @image: context where the image is created
6353 * @type_spec: typespec token
6354 * @context: the generic context used to evaluate generic instantiations in
6357 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6359 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6361 mono_error_init (error);
6362 *did_inflate = FALSE;
6365 char *name = mono_class_name_from_token (image, type_spec);
6366 char *assembly = mono_assembly_name_from_token (image, type_spec);
6367 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6371 if (context && (context->class_inst || context->method_inst)) {
6372 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6374 if (!mono_error_ok (error))
6379 *did_inflate = TRUE;
6386 * mono_class_create_from_typespec
6387 * @image: context where the image is created
6388 * @type_spec: typespec token
6389 * @context: the generic context used to evaluate generic instantiations in
6392 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6395 gboolean inflated = FALSE;
6396 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6397 if (!mono_error_ok (error))
6399 ret = mono_class_from_mono_type (t);
6401 mono_metadata_free_type (t);
6406 * mono_bounded_array_class_get:
6407 * @element_class: element class
6408 * @rank: the dimension of the array class
6409 * @bounded: whenever the array has non-zero bounds
6411 * Returns: a class object describing the array with element type @element_type and
6415 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6419 MonoClass *parent = NULL;
6420 GSList *list, *rootlist = NULL;
6423 gboolean corlib_type = FALSE;
6425 g_assert (rank <= 255);
6428 /* bounded only matters for one-dimensional arrays */
6431 image = eclass->image;
6433 if (rank == 1 && !bounded) {
6435 * This case is very frequent not just during compilation because of calls
6436 * from mono_class_from_mono_type (), mono_array_new (),
6437 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6439 mono_mutex_lock (&image->szarray_cache_lock);
6440 if (!image->szarray_cache)
6441 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6442 class = g_hash_table_lookup (image->szarray_cache, eclass);
6443 mono_mutex_unlock (&image->szarray_cache_lock);
6447 mono_loader_lock ();
6449 mono_loader_lock ();
6451 if (!image->array_cache)
6452 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6454 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6455 for (; list; list = list->next) {
6457 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6458 mono_loader_unlock ();
6465 /* for the building corlib use System.Array from it */
6466 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6467 parent = mono_class_from_name (image, "System", "Array");
6470 parent = mono_defaults.array_class;
6471 if (!parent->inited)
6472 mono_class_init (parent);
6475 class = mono_image_alloc0 (image, sizeof (MonoClass));
6477 class->image = image;
6478 class->name_space = eclass->name_space;
6479 nsize = strlen (eclass->name);
6480 name = g_malloc (nsize + 2 + rank + 1);
6481 memcpy (name, eclass->name, nsize);
6484 memset (name + nsize + 1, ',', rank - 1);
6486 name [nsize + rank] = '*';
6487 name [nsize + rank + bounded] = ']';
6488 name [nsize + rank + bounded + 1] = 0;
6489 class->name = mono_image_strdup (image, name);
6492 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6494 classes_size += sizeof (MonoClass);
6496 class->type_token = 0;
6497 /* all arrays are marked serializable and sealed, bug #42779 */
6498 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6499 class->parent = parent;
6500 class->instance_size = mono_class_instance_size (class->parent);
6502 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6503 /*Arrays of those two types are invalid.*/
6504 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6505 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6506 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6507 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6508 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6510 /* element_size -1 is ok as this is not an instantitable type*/
6511 class->sizes.element_size = -1;
6513 class->sizes.element_size = mono_class_array_element_size (eclass);
6515 mono_class_setup_supertypes (class);
6517 if (eclass->generic_class)
6518 mono_class_init (eclass);
6519 if (!eclass->size_inited)
6520 mono_class_setup_fields (eclass);
6521 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6522 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6524 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6528 if (eclass->enumtype)
6529 class->cast_class = eclass->element_class;
6531 class->cast_class = eclass;
6533 switch (class->cast_class->byval_arg.type) {
6535 class->cast_class = mono_defaults.byte_class;
6538 class->cast_class = mono_defaults.int16_class;
6541 #if SIZEOF_VOID_P == 4
6545 class->cast_class = mono_defaults.int32_class;
6548 #if SIZEOF_VOID_P == 8
6552 class->cast_class = mono_defaults.int64_class;
6556 class->element_class = eclass;
6558 if ((rank > 1) || bounded) {
6559 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6560 class->byval_arg.type = MONO_TYPE_ARRAY;
6561 class->byval_arg.data.array = at;
6562 at->eklass = eclass;
6564 /* FIXME: complete.... */
6566 class->byval_arg.type = MONO_TYPE_SZARRAY;
6567 class->byval_arg.data.klass = eclass;
6569 class->this_arg = class->byval_arg;
6570 class->this_arg.byref = 1;
6575 class->generic_container = eclass->generic_container;
6577 if (rank == 1 && !bounded) {
6578 MonoClass *prev_class;
6580 mono_mutex_lock (&image->szarray_cache_lock);
6581 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6583 /* Someone got in before us */
6586 g_hash_table_insert (image->szarray_cache, eclass, class);
6587 mono_mutex_unlock (&image->szarray_cache_lock);
6589 list = g_slist_append (rootlist, class);
6590 g_hash_table_insert (image->array_cache, eclass, list);
6593 mono_loader_unlock ();
6595 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6601 * mono_array_class_get:
6602 * @element_class: element class
6603 * @rank: the dimension of the array class
6605 * Returns: a class object describing the array with element type @element_type and
6609 mono_array_class_get (MonoClass *eclass, guint32 rank)
6611 return mono_bounded_array_class_get (eclass, rank, FALSE);
6615 * mono_class_instance_size:
6618 * Returns: the size of an object instance
6621 mono_class_instance_size (MonoClass *klass)
6623 if (!klass->size_inited)
6624 mono_class_init (klass);
6626 return klass->instance_size;
6630 * mono_class_min_align:
6633 * Returns: minimm alignment requirements
6636 mono_class_min_align (MonoClass *klass)
6638 if (!klass->size_inited)
6639 mono_class_init (klass);
6641 return klass->min_align;
6645 * mono_class_value_size:
6648 * This function is used for value types, and return the
6649 * space and the alignment to store that kind of value object.
6651 * Returns: the size of a value of kind @klass
6654 mono_class_value_size (MonoClass *klass, guint32 *align)
6658 /* fixme: check disable, because we still have external revereces to
6659 * mscorlib and Dummy Objects
6661 /*g_assert (klass->valuetype);*/
6663 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6666 *align = klass->min_align;
6672 * mono_class_data_size:
6675 * Returns: the size of the static class data
6678 mono_class_data_size (MonoClass *klass)
6681 mono_class_init (klass);
6682 /* This can happen with dynamically created types */
6683 if (!klass->fields_inited)
6684 mono_class_setup_fields_locking (klass);
6686 /* in arrays, sizes.class_size is unioned with element_size
6687 * and arrays have no static fields
6691 return klass->sizes.class_size;
6695 * Auxiliary routine to mono_class_get_field
6697 * Takes a field index instead of a field token.
6699 static MonoClassField *
6700 mono_class_get_field_idx (MonoClass *class, int idx)
6702 mono_class_setup_fields_locking (class);
6703 if (class->exception_type)
6707 if (class->image->uncompressed_metadata) {
6709 * class->field.first points to the FieldPtr table, while idx points into the
6710 * Field table, so we have to do a search.
6712 /*FIXME this is broken for types with multiple fields with the same name.*/
6713 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6716 for (i = 0; i < class->field.count; ++i)
6717 if (mono_field_get_name (&class->fields [i]) == name)
6718 return &class->fields [i];
6719 g_assert_not_reached ();
6721 if (class->field.count) {
6722 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6723 return &class->fields [idx - class->field.first];
6727 class = class->parent;
6733 * mono_class_get_field:
6734 * @class: the class to lookup the field.
6735 * @field_token: the field token
6737 * Returns: A MonoClassField representing the type and offset of
6738 * the field, or a NULL value if the field does not belong to this
6742 mono_class_get_field (MonoClass *class, guint32 field_token)
6744 int idx = mono_metadata_token_index (field_token);
6746 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6748 return mono_class_get_field_idx (class, idx - 1);
6752 * mono_class_get_field_from_name:
6753 * @klass: the class to lookup the field.
6754 * @name: the field name
6756 * Search the class @klass and it's parents for a field with the name @name.
6758 * Returns: the MonoClassField pointer of the named field or NULL
6761 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6763 return mono_class_get_field_from_name_full (klass, name, NULL);
6767 * mono_class_get_field_from_name_full:
6768 * @klass: the class to lookup the field.
6769 * @name: the field name
6770 * @type: the type of the fields. This optional.
6772 * Search the class @klass and it's parents for a field with the name @name and type @type.
6774 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6775 * of its generic type definition.
6777 * Returns: the MonoClassField pointer of the named field or NULL
6780 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6784 mono_class_setup_fields_locking (klass);
6785 if (klass->exception_type)
6789 for (i = 0; i < klass->field.count; ++i) {
6790 MonoClassField *field = &klass->fields [i];
6792 if (strcmp (name, mono_field_get_name (field)) != 0)
6796 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6797 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6802 klass = klass->parent;
6808 * mono_class_get_field_token:
6809 * @field: the field we need the token of
6811 * Get the token of a field. Note that the tokesn is only valid for the image
6812 * the field was loaded from. Don't use this function for fields in dynamic types.
6814 * Returns: the token representing the field in the image it was loaded from.
6817 mono_class_get_field_token (MonoClassField *field)
6819 MonoClass *klass = field->parent;
6822 mono_class_setup_fields_locking (klass);
6827 for (i = 0; i < klass->field.count; ++i) {
6828 if (&klass->fields [i] == field) {
6829 int idx = klass->field.first + i + 1;
6831 if (klass->image->uncompressed_metadata)
6832 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6833 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6836 klass = klass->parent;
6839 g_assert_not_reached ();
6844 mono_field_get_index (MonoClassField *field)
6846 int index = field - field->parent->fields;
6848 g_assert (index >= 0 && index < field->parent->field.count);
6854 * mono_class_get_field_default_value:
6856 * Return the default value of the field as a pointer into the metadata blob.
6859 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6862 guint32 constant_cols [MONO_CONSTANT_SIZE];
6864 MonoClass *klass = field->parent;
6866 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6868 if (!klass->ext || !klass->ext->field_def_values) {
6869 MonoFieldDefaultValue *def_values;
6871 mono_class_alloc_ext (klass);
6873 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6875 mono_image_lock (klass->image);
6876 mono_memory_barrier ();
6877 if (!klass->ext->field_def_values)
6878 klass->ext->field_def_values = def_values;
6879 mono_image_unlock (klass->image);
6882 field_index = mono_field_get_index (field);
6884 if (!klass->ext->field_def_values [field_index].data) {
6885 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6889 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6891 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6892 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6893 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6896 *def_type = klass->ext->field_def_values [field_index].def_type;
6897 return klass->ext->field_def_values [field_index].data;
6901 mono_property_get_index (MonoProperty *prop)
6903 int index = prop - prop->parent->ext->properties;
6905 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6911 * mono_class_get_property_default_value:
6913 * Return the default value of the field as a pointer into the metadata blob.
6916 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6919 guint32 constant_cols [MONO_CONSTANT_SIZE];
6920 MonoClass *klass = property->parent;
6922 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6924 * We don't cache here because it is not used by C# so it's quite rare, but
6925 * we still do the lookup in klass->ext because that is where the data
6926 * is stored for dynamic assemblies.
6929 if (image_is_dynamic (klass->image)) {
6930 int prop_index = mono_property_get_index (property);
6931 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6932 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6933 return klass->ext->prop_def_values [prop_index].data;
6937 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6941 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6942 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6943 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6947 mono_class_get_event_token (MonoEvent *event)
6949 MonoClass *klass = event->parent;
6954 for (i = 0; i < klass->ext->event.count; ++i) {
6955 if (&klass->ext->events [i] == event)
6956 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6959 klass = klass->parent;
6962 g_assert_not_reached ();
6967 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6971 gpointer iter = NULL;
6972 while ((p = mono_class_get_properties (klass, &iter))) {
6973 if (! strcmp (name, p->name))
6976 klass = klass->parent;
6982 mono_class_get_property_token (MonoProperty *prop)
6984 MonoClass *klass = prop->parent;
6988 gpointer iter = NULL;
6989 while ((p = mono_class_get_properties (klass, &iter))) {
6990 if (&klass->ext->properties [i] == prop)
6991 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6995 klass = klass->parent;
6998 g_assert_not_reached ();
7003 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7005 const char *name, *nspace;
7006 if (image_is_dynamic (image))
7007 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7009 switch (type_token & 0xff000000){
7010 case MONO_TOKEN_TYPE_DEF: {
7011 guint32 cols [MONO_TYPEDEF_SIZE];
7012 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7013 guint tidx = mono_metadata_token_index (type_token);
7015 if (tidx > tt->rows)
7016 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7018 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7019 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7020 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7021 if (strlen (nspace) == 0)
7022 return g_strdup_printf ("%s", name);
7024 return g_strdup_printf ("%s.%s", nspace, name);
7027 case MONO_TOKEN_TYPE_REF: {
7029 guint32 cols [MONO_TYPEREF_SIZE];
7030 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7031 guint tidx = mono_metadata_token_index (type_token);
7034 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7036 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7037 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7038 mono_error_cleanup (&error);
7042 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7043 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7044 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7045 if (strlen (nspace) == 0)
7046 return g_strdup_printf ("%s", name);
7048 return g_strdup_printf ("%s.%s", nspace, name);
7051 case MONO_TOKEN_TYPE_SPEC:
7052 return g_strdup_printf ("Typespec 0x%08x", type_token);
7054 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7059 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7061 if (image_is_dynamic (image))
7062 return g_strdup_printf ("DynamicAssembly %s", image->name);
7064 switch (type_token & 0xff000000){
7065 case MONO_TOKEN_TYPE_DEF:
7066 if (image->assembly)
7067 return mono_stringify_assembly_name (&image->assembly->aname);
7068 else if (image->assembly_name)
7069 return g_strdup (image->assembly_name);
7070 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7071 case MONO_TOKEN_TYPE_REF: {
7073 MonoAssemblyName aname;
7074 guint32 cols [MONO_TYPEREF_SIZE];
7075 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7076 guint32 idx = mono_metadata_token_index (type_token);
7079 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7081 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7082 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7083 mono_error_cleanup (&error);
7086 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7088 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7089 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7090 case MONO_RESOLTION_SCOPE_MODULE:
7092 return g_strdup ("");
7093 case MONO_RESOLTION_SCOPE_MODULEREF:
7095 return g_strdup ("");
7096 case MONO_RESOLTION_SCOPE_TYPEREF:
7098 return g_strdup ("");
7099 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7100 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7101 return mono_stringify_assembly_name (&aname);
7103 g_assert_not_reached ();
7107 case MONO_TOKEN_TYPE_SPEC:
7109 return g_strdup ("");
7111 g_assert_not_reached ();
7118 * mono_class_get_full:
7119 * @image: the image where the class resides
7120 * @type_token: the token for the class
7121 * @context: the generic context used to evaluate generic instantiations in
7122 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7124 * Returns: the MonoClass that represents @type_token in @image
7127 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7130 MonoClass *class = NULL;
7132 if (image_is_dynamic (image)) {
7133 int table = mono_metadata_token_table (type_token);
7135 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7136 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7139 return mono_lookup_dynamic_token (image, type_token, context);
7142 switch (type_token & 0xff000000){
7143 case MONO_TOKEN_TYPE_DEF:
7144 class = mono_class_create_from_typedef (image, type_token, &error);
7145 if (!mono_error_ok (&error)) {
7146 mono_loader_set_error_from_mono_error (&error);
7147 /*FIXME don't swallow the error message*/
7148 mono_error_cleanup (&error);
7152 case MONO_TOKEN_TYPE_REF:
7153 class = mono_class_from_typeref_checked (image, type_token, &error);
7154 if (!mono_error_ok (&error)) {
7155 /*FIXME don't swallow the error message*/
7156 mono_error_cleanup (&error);
7159 case MONO_TOKEN_TYPE_SPEC:
7160 class = mono_class_create_from_typespec (image, type_token, context, &error);
7161 if (!mono_error_ok (&error)) {
7162 /*FIXME don't swallow the error message*/
7163 mono_error_cleanup (&error);
7167 g_warning ("unknown token type %x", type_token & 0xff000000);
7168 g_assert_not_reached ();
7172 char *name = mono_class_name_from_token (image, type_token);
7173 char *assembly = mono_assembly_name_from_token (image, type_token);
7174 mono_loader_set_error_type_load (name, assembly);
7184 * mono_type_get_full:
7185 * @image: the image where the type resides
7186 * @type_token: the token for the type
7187 * @context: the generic context used to evaluate generic instantiations in
7189 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7191 * Returns: the MonoType that represents @type_token in @image
7194 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7197 MonoType *type = NULL;
7198 gboolean inflated = FALSE;
7200 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7201 if (image_is_dynamic (image))
7202 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7204 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7205 MonoClass *class = mono_class_get_full (image, type_token, context);
7206 return class ? mono_class_get_type (class) : NULL;
7209 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7211 if (!mono_error_ok (&error)) {
7212 /*FIXME don't swalloc the error message.*/
7213 char *name = mono_class_name_from_token (image, type_token);
7214 char *assembly = mono_assembly_name_from_token (image, type_token);
7216 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7218 mono_error_cleanup (&error);
7219 mono_loader_set_error_type_load (name, assembly);
7224 MonoType *tmp = type;
7225 type = mono_class_get_type (mono_class_from_mono_type (type));
7226 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7227 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7228 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7230 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7232 if (type->type != tmp->type)
7235 mono_metadata_free_type (tmp);
7242 mono_class_get (MonoImage *image, guint32 type_token)
7244 return mono_class_get_full (image, type_token, NULL);
7248 * mono_image_init_name_cache:
7250 * Initializes the class name cache stored in image->name_cache.
7252 * LOCKING: Acquires the corresponding image lock.
7255 mono_image_init_name_cache (MonoImage *image)
7257 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7258 guint32 cols [MONO_TYPEDEF_SIZE];
7261 guint32 i, visib, nspace_index;
7262 GHashTable *name_cache2, *nspace_table;
7264 mono_image_lock (image);
7266 if (image->name_cache) {
7267 mono_image_unlock (image);
7271 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7273 if (image_is_dynamic (image)) {
7274 mono_image_unlock (image);
7278 /* Temporary hash table to avoid lookups in the nspace_table */
7279 name_cache2 = g_hash_table_new (NULL, NULL);
7281 for (i = 1; i <= t->rows; ++i) {
7282 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7283 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7285 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7286 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7288 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7290 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7291 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7293 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7294 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7295 if (!nspace_table) {
7296 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7297 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7298 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7301 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7304 /* Load type names from EXPORTEDTYPES table */
7306 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7307 guint32 cols [MONO_EXP_TYPE_SIZE];
7310 for (i = 0; i < t->rows; ++i) {
7311 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7312 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7313 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7315 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7316 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7317 if (!nspace_table) {
7318 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7319 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7320 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7323 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7327 g_hash_table_destroy (name_cache2);
7328 mono_image_unlock (image);
7331 /*FIXME Only dynamic assemblies should allow this operation.*/
7333 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7334 const char *name, guint32 index)
7336 GHashTable *nspace_table;
7337 GHashTable *name_cache;
7340 mono_image_lock (image);
7342 if (!image->name_cache)
7343 mono_image_init_name_cache (image);
7345 name_cache = image->name_cache;
7346 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7347 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7348 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7351 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7352 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7354 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7356 mono_image_unlock (image);
7365 find_nocase (gpointer key, gpointer value, gpointer user_data)
7367 char *name = (char*)key;
7368 FindUserData *data = (FindUserData*)user_data;
7370 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7371 data->value = value;
7375 * mono_class_from_name_case:
7376 * @image: The MonoImage where the type is looked up in
7377 * @name_space: the type namespace
7378 * @name: the type short name.
7380 * Obtains a MonoClass with a given namespace and a given name which
7381 * is located in the given MonoImage. The namespace and name
7382 * lookups are case insensitive.
7385 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7387 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7388 guint32 cols [MONO_TYPEDEF_SIZE];
7393 if (image_is_dynamic (image)) {
7395 FindUserData user_data;
7397 mono_image_lock (image);
7399 if (!image->name_cache)
7400 mono_image_init_name_cache (image);
7402 user_data.key = name_space;
7403 user_data.value = NULL;
7404 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7406 if (user_data.value) {
7407 GHashTable *nspace_table = (GHashTable*)user_data.value;
7409 user_data.key = name;
7410 user_data.value = NULL;
7412 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7414 if (user_data.value)
7415 token = GPOINTER_TO_UINT (user_data.value);
7418 mono_image_unlock (image);
7421 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7427 /* add a cache if needed */
7428 for (i = 1; i <= t->rows; ++i) {
7429 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7430 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7432 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7433 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7435 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7437 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7438 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7439 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7440 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7446 return_nested_in (MonoClass *class, char *nested)
7449 char *s = strchr (nested, '/');
7450 gpointer iter = NULL;
7457 while ((found = mono_class_get_nested_types (class, &iter))) {
7458 if (strcmp (found->name, nested) == 0) {
7460 return return_nested_in (found, s);
7468 search_modules (MonoImage *image, const char *name_space, const char *name)
7470 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7471 MonoImage *file_image;
7476 * The EXPORTEDTYPES table only contains public types, so have to search the
7478 * Note: image->modules contains the contents of the MODULEREF table, while
7479 * the real module list is in the FILE table.
7481 for (i = 0; i < file_table->rows; i++) {
7482 guint32 cols [MONO_FILE_SIZE];
7483 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7484 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7487 file_image = mono_image_load_file_for_image (image, i + 1);
7489 class = mono_class_from_name (file_image, name_space, name);
7499 * mono_class_from_name:
7500 * @image: The MonoImage where the type is looked up in
7501 * @name_space: the type namespace
7502 * @name: the type short name.
7504 * Obtains a MonoClass with a given namespace and a given name which
7505 * is located in the given MonoImage.
7507 * To reference nested classes, use the "/" character as a separator.
7508 * For example use "Foo/Bar" to reference the class Bar that is nested
7509 * inside Foo, like this: "class Foo { class Bar {} }".
7512 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7514 GHashTable *nspace_table;
7515 MonoImage *loaded_image;
7522 if ((nested = strchr (name, '/'))) {
7523 int pos = nested - name;
7524 int len = strlen (name);
7527 memcpy (buf, name, len + 1);
7529 nested = buf + pos + 1;
7533 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7534 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7535 gboolean res = get_class_from_name (image, name_space, name, &class);
7538 class = search_modules (image, name_space, name);
7540 return class ? return_nested_in (class, nested) : NULL;
7546 mono_image_lock (image);
7548 if (!image->name_cache)
7549 mono_image_init_name_cache (image);
7551 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7554 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7556 mono_image_unlock (image);
7558 if (!token && image_is_dynamic (image) && image->modules) {
7559 /* Search modules as well */
7560 for (i = 0; i < image->module_count; ++i) {
7561 MonoImage *module = image->modules [i];
7563 class = mono_class_from_name (module, name_space, name);
7570 class = search_modules (image, name_space, name);
7578 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7579 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7580 guint32 cols [MONO_EXP_TYPE_SIZE];
7583 idx = mono_metadata_token_index (token);
7585 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7587 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7588 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7589 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7592 class = mono_class_from_name (loaded_image, name_space, name);
7594 return return_nested_in (class, nested);
7596 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7597 guint32 assembly_idx;
7599 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7601 mono_assembly_load_reference (image, assembly_idx - 1);
7602 g_assert (image->references [assembly_idx - 1]);
7603 if (image->references [assembly_idx - 1] == (gpointer)-1)
7606 /* FIXME: Cycle detection */
7607 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7609 g_error ("not yet implemented");
7613 token = MONO_TOKEN_TYPE_DEF | token;
7615 class = mono_class_get (image, token);
7617 return return_nested_in (class, nested);
7622 * mono_class_is_subclass_of:
7623 * @klass: class to probe if it is a subclass of another one
7624 * @klassc: the class we suspect is the base class
7625 * @check_interfaces: whether we should perform interface checks
7627 * This method determines whether @klass is a subclass of @klassc.
7629 * If the @check_interfaces flag is set, then if @klassc is an interface
7630 * this method return true if the @klass implements the interface or
7631 * if @klass is an interface, if one of its base classes is @klass.
7633 * If @check_interfaces is false then, then if @klass is not an interface
7634 * then it returns true if the @klass is a subclass of @klassc.
7636 * if @klass is an interface and @klassc is System.Object, then this function
7641 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7642 gboolean check_interfaces)
7644 /*FIXME test for interfaces with variant generic arguments*/
7646 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7647 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7649 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7652 for (i = 0; i < klass->interface_count; i ++) {
7653 MonoClass *ic = klass->interfaces [i];
7658 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7663 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7666 if (klassc == mono_defaults.object_class)
7673 mono_type_is_generic_argument (MonoType *type)
7675 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7679 mono_class_has_variant_generic_params (MonoClass *klass)
7682 MonoGenericContainer *container;
7684 if (!klass->generic_class)
7687 container = klass->generic_class->container_class->generic_container;
7689 for (i = 0; i < container->type_argc; ++i)
7690 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7697 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7699 if (target == candidate)
7702 if (check_for_reference_conv &&
7703 mono_type_is_generic_argument (&target->byval_arg) &&
7704 mono_type_is_generic_argument (&candidate->byval_arg)) {
7705 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7706 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7708 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7711 if (!mono_class_is_assignable_from (target, candidate))
7717 * @container the generic container from the GTD
7718 * @klass: the class to be assigned to
7719 * @oklass: the source class
7721 * Both klass and oklass must be instances of the same generic interface.
7722 * Return true if @klass can be assigned to a @klass variable
7725 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7728 MonoType **klass_argv, **oklass_argv;
7729 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7730 MonoGenericContainer *container = klass_gtd->generic_container;
7732 if (klass == oklass)
7735 /*Viable candidates are instances of the same generic interface*/
7736 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7739 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7740 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7742 for (j = 0; j < container->type_argc; ++j) {
7743 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7744 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7746 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7750 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7751 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7753 if (param1_class != param2_class) {
7754 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7755 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7757 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7758 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7768 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7770 MonoGenericParam *gparam, *ogparam;
7771 MonoGenericParamInfo *tinfo, *cinfo;
7772 MonoClass **candidate_class;
7773 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7776 if (target == candidate)
7778 if (target->byval_arg.type != candidate->byval_arg.type)
7781 gparam = target->byval_arg.data.generic_param;
7782 ogparam = candidate->byval_arg.data.generic_param;
7783 tinfo = mono_generic_param_info (gparam);
7784 cinfo = mono_generic_param_info (ogparam);
7786 class_constraint_satisfied = FALSE;
7787 valuetype_constraint_satisfied = FALSE;
7789 /*candidate must have a super set of target's special constraints*/
7790 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7791 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7793 if (cinfo->constraints) {
7794 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7795 MonoClass *cc = *candidate_class;
7797 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7798 class_constraint_satisfied = TRUE;
7799 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7800 valuetype_constraint_satisfied = TRUE;
7803 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7804 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7806 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7808 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7810 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7811 valuetype_constraint_satisfied)) {
7816 /*candidate type constraints must be a superset of target's*/
7817 if (tinfo->constraints) {
7818 MonoClass **target_class;
7819 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7820 MonoClass *tc = *target_class;
7823 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7824 * check it's constraints since it satisfy the constraint by itself.
7826 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7829 if (!cinfo->constraints)
7832 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7833 MonoClass *cc = *candidate_class;
7835 if (mono_class_is_assignable_from (tc, cc))
7839 * This happens when we have the following:
7841 * Bar<K> where K : IFace
7842 * Foo<T, U> where T : U where U : IFace
7844 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7847 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7848 if (mono_gparam_is_assignable_from (target, cc))
7852 if (!*candidate_class)
7857 /*candidate itself must have a constraint that satisfy target*/
7858 if (cinfo->constraints) {
7859 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7860 MonoClass *cc = *candidate_class;
7861 if (mono_class_is_assignable_from (target, cc))
7869 * mono_class_is_assignable_from:
7870 * @klass: the class to be assigned to
7871 * @oklass: the source class
7873 * Return: true if an instance of object oklass can be assigned to an
7874 * instance of object @klass
7877 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7879 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7881 mono_class_init (klass);
7883 if (!oklass->inited)
7884 mono_class_init (oklass);
7886 if (klass->exception_type || oklass->exception_type)
7889 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7890 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7892 return mono_gparam_is_assignable_from (klass, oklass);
7895 if (MONO_CLASS_IS_INTERFACE (klass)) {
7896 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7897 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7898 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7902 for (i = 0; constraints [i]; ++i) {
7903 if (mono_class_is_assignable_from (klass, constraints [i]))
7911 /* interface_offsets might not be set for dynamic classes */
7912 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7914 * oklass might be a generic type parameter but they have
7915 * interface_offsets set.
7917 return mono_reflection_call_is_assignable_to (oklass, klass);
7918 if (!oklass->interface_bitmap)
7919 /* Happens with generic instances of not-yet created dynamic types */
7921 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7924 if (mono_class_has_variant_generic_params (klass)) {
7927 mono_class_setup_interfaces (oklass, &error);
7928 if (!mono_error_ok (&error)) {
7929 mono_error_cleanup (&error);
7933 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7934 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7935 MonoClass *iface = oklass->interfaces_packed [i];
7937 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7942 } else if (klass->delegate) {
7943 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7945 }else if (klass->rank) {
7946 MonoClass *eclass, *eoclass;
7948 if (oklass->rank != klass->rank)
7951 /* vectors vs. one dimensional arrays */
7952 if (oklass->byval_arg.type != klass->byval_arg.type)
7955 eclass = klass->cast_class;
7956 eoclass = oklass->cast_class;
7959 * a is b does not imply a[] is b[] when a is a valuetype, and
7960 * b is a reference type.
7963 if (eoclass->valuetype) {
7964 if ((eclass == mono_defaults.enum_class) ||
7965 (eclass == mono_defaults.enum_class->parent) ||
7966 (eclass == mono_defaults.object_class))
7970 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7971 } else if (mono_class_is_nullable (klass)) {
7972 if (mono_class_is_nullable (oklass))
7973 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7975 return mono_class_is_assignable_from (klass->cast_class, oklass);
7976 } else if (klass == mono_defaults.object_class)
7979 return mono_class_has_parent (oklass, klass);
7982 /*Check if @oklass is variant compatible with @klass.*/
7984 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7987 MonoType **klass_argv, **oklass_argv;
7988 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7989 MonoGenericContainer *container = klass_gtd->generic_container;
7991 /*Viable candidates are instances of the same generic interface*/
7992 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7995 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7996 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7998 for (j = 0; j < container->type_argc; ++j) {
7999 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8000 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8002 if (param1_class->valuetype != param2_class->valuetype)
8006 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8007 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8009 if (param1_class != param2_class) {
8010 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8011 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8013 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8014 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8022 /*Check if @candidate implements the interface @target*/
8024 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8028 gboolean is_variant = mono_class_has_variant_generic_params (target);
8030 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8031 if (mono_class_is_variant_compatible_slow (target, candidate))
8036 if (candidate == target)
8039 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8040 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8041 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8043 if (tb && tb->interfaces) {
8044 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8045 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8046 MonoClass *iface_class;
8048 /* we can't realize the type here since it can do pretty much anything. */
8051 iface_class = mono_class_from_mono_type (iface->type);
8052 if (iface_class == target)
8054 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8056 if (mono_class_implement_interface_slow (target, iface_class))
8061 /*setup_interfaces don't mono_class_init anything*/
8062 /*FIXME this doesn't handle primitive type arrays.
8063 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8064 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8066 mono_class_setup_interfaces (candidate, &error);
8067 if (!mono_error_ok (&error)) {
8068 mono_error_cleanup (&error);
8072 for (i = 0; i < candidate->interface_count; ++i) {
8073 if (candidate->interfaces [i] == target)
8076 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8079 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8083 candidate = candidate->parent;
8084 } while (candidate);
8090 * Check if @oklass can be assigned to @klass.
8091 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8094 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8096 if (candidate == target)
8098 if (target == mono_defaults.object_class)
8101 if (mono_class_has_parent (candidate, target))
8104 /*If target is not an interface there is no need to check them.*/
8105 if (MONO_CLASS_IS_INTERFACE (target))
8106 return mono_class_implement_interface_slow (target, candidate);
8108 if (target->delegate && mono_class_has_variant_generic_params (target))
8109 return mono_class_is_variant_compatible (target, candidate, FALSE);
8112 MonoClass *eclass, *eoclass;
8114 if (target->rank != candidate->rank)
8117 /* vectors vs. one dimensional arrays */
8118 if (target->byval_arg.type != candidate->byval_arg.type)
8121 eclass = target->cast_class;
8122 eoclass = candidate->cast_class;
8125 * a is b does not imply a[] is b[] when a is a valuetype, and
8126 * b is a reference type.
8129 if (eoclass->valuetype) {
8130 if ((eclass == mono_defaults.enum_class) ||
8131 (eclass == mono_defaults.enum_class->parent) ||
8132 (eclass == mono_defaults.object_class))
8136 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8138 /*FIXME properly handle nullables */
8139 /*FIXME properly handle (M)VAR */
8144 * mono_class_get_cctor:
8145 * @klass: A MonoClass pointer
8147 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8150 mono_class_get_cctor (MonoClass *klass)
8152 MonoCachedClassInfo cached_info;
8154 if (image_is_dynamic (klass->image)) {
8156 * has_cctor is not set for these classes because mono_class_init () is
8159 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8162 if (!klass->has_cctor)
8165 if (mono_class_get_cached_class_info (klass, &cached_info))
8166 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8168 if (klass->generic_class && !klass->methods)
8169 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8171 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8175 * mono_class_get_finalizer:
8176 * @klass: The MonoClass pointer
8178 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8181 mono_class_get_finalizer (MonoClass *klass)
8183 MonoCachedClassInfo cached_info;
8186 mono_class_init (klass);
8187 if (!mono_class_has_finalizer (klass))
8190 if (mono_class_get_cached_class_info (klass, &cached_info))
8191 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8193 mono_class_setup_vtable (klass);
8194 return klass->vtable [finalize_slot];
8199 * mono_class_needs_cctor_run:
8200 * @klass: the MonoClass pointer
8201 * @caller: a MonoMethod describing the caller
8203 * Determines whenever the class has a static constructor and whenever it
8204 * needs to be called when executing CALLER.
8207 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8211 method = mono_class_get_cctor (klass);
8213 return (method == caller) ? FALSE : TRUE;
8219 * mono_class_array_element_size:
8222 * Returns: the number of bytes an element of type @klass
8223 * uses when stored into an array.
8226 mono_class_array_element_size (MonoClass *klass)
8228 MonoType *type = &klass->byval_arg;
8231 switch (type->type) {
8234 case MONO_TYPE_BOOLEAN:
8238 case MONO_TYPE_CHAR:
8247 case MONO_TYPE_CLASS:
8248 case MONO_TYPE_STRING:
8249 case MONO_TYPE_OBJECT:
8250 case MONO_TYPE_SZARRAY:
8251 case MONO_TYPE_ARRAY:
8253 case MONO_TYPE_MVAR:
8254 return sizeof (gpointer);
8259 case MONO_TYPE_VALUETYPE:
8260 if (type->data.klass->enumtype) {
8261 type = mono_class_enum_basetype (type->data.klass);
8262 klass = klass->element_class;
8265 return mono_class_instance_size (klass) - sizeof (MonoObject);
8266 case MONO_TYPE_GENERICINST:
8267 type = &type->data.generic_class->container_class->byval_arg;
8270 case MONO_TYPE_VOID:
8274 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8280 * mono_array_element_size:
8281 * @ac: pointer to a #MonoArrayClass
8283 * Returns: the size of single array element.
8286 mono_array_element_size (MonoClass *ac)
8288 g_assert (ac->rank);
8289 return ac->sizes.element_size;
8293 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8294 MonoGenericContext *context)
8296 if (image_is_dynamic (image)) {
8297 MonoClass *tmp_handle_class;
8298 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8300 g_assert (tmp_handle_class);
8302 *handle_class = tmp_handle_class;
8304 if (tmp_handle_class == mono_defaults.typehandle_class)
8305 return &((MonoClass*)obj)->byval_arg;
8310 switch (token & 0xff000000) {
8311 case MONO_TOKEN_TYPE_DEF:
8312 case MONO_TOKEN_TYPE_REF:
8313 case MONO_TOKEN_TYPE_SPEC: {
8316 *handle_class = mono_defaults.typehandle_class;
8317 type = mono_type_get_full (image, token, context);
8320 mono_class_init (mono_class_from_mono_type (type));
8321 /* We return a MonoType* as handle */
8324 case MONO_TOKEN_FIELD_DEF: {
8326 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8330 *handle_class = mono_defaults.fieldhandle_class;
8331 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8334 mono_class_init (class);
8335 return mono_class_get_field (class, token);
8337 case MONO_TOKEN_METHOD_DEF:
8338 case MONO_TOKEN_METHOD_SPEC: {
8340 meth = mono_get_method_full (image, token, NULL, context);
8342 *handle_class = mono_defaults.methodhandle_class;
8345 case MONO_TOKEN_MEMBER_REF: {
8346 guint32 cols [MONO_MEMBERREF_SIZE];
8348 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8349 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8350 mono_metadata_decode_blob_size (sig, &sig);
8351 if (*sig == 0x6) { /* it's a field */
8353 MonoClassField *field;
8354 field = mono_field_from_token (image, token, &klass, context);
8356 *handle_class = mono_defaults.fieldhandle_class;
8360 meth = mono_get_method_full (image, token, NULL, context);
8362 *handle_class = mono_defaults.methodhandle_class;
8367 g_warning ("Unknown token 0x%08x in ldtoken", token);
8374 * This function might need to call runtime functions so it can't be part
8375 * of the metadata library.
8377 static MonoLookupDynamicToken lookup_dynamic = NULL;
8380 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8382 lookup_dynamic = func;
8386 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8388 MonoClass *handle_class;
8390 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8394 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8396 return lookup_dynamic (image, token, valid_token, handle_class, context);
8399 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8402 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8404 get_cached_class_info = func;
8408 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8410 if (!get_cached_class_info)
8413 return get_cached_class_info (klass, res);
8417 mono_install_get_class_from_name (MonoGetClassFromName func)
8419 get_class_from_name = func;
8423 mono_class_get_image (MonoClass *klass)
8425 return klass->image;
8429 * mono_class_get_element_class:
8430 * @klass: the MonoClass to act on
8432 * Returns: the element class of an array or an enumeration.
8435 mono_class_get_element_class (MonoClass *klass)
8437 return klass->element_class;
8441 * mono_class_is_valuetype:
8442 * @klass: the MonoClass to act on
8444 * Returns: true if the MonoClass represents a ValueType.
8447 mono_class_is_valuetype (MonoClass *klass)
8449 return klass->valuetype;
8453 * mono_class_is_enum:
8454 * @klass: the MonoClass to act on
8456 * Returns: true if the MonoClass represents an enumeration.
8459 mono_class_is_enum (MonoClass *klass)
8461 return klass->enumtype;
8465 * mono_class_enum_basetype:
8466 * @klass: the MonoClass to act on
8468 * Returns: the underlying type representation for an enumeration.
8471 mono_class_enum_basetype (MonoClass *klass)
8473 if (klass->element_class == klass)
8474 /* SRE or broken types */
8477 return &klass->element_class->byval_arg;
8481 * mono_class_get_parent
8482 * @klass: the MonoClass to act on
8484 * Returns: the parent class for this class.
8487 mono_class_get_parent (MonoClass *klass)
8489 return klass->parent;
8493 * mono_class_get_nesting_type;
8494 * @klass: the MonoClass to act on
8496 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8499 mono_class_get_nesting_type (MonoClass *klass)
8501 return klass->nested_in;
8505 * mono_class_get_rank:
8506 * @klass: the MonoClass to act on
8508 * Returns: the rank for the array (the number of dimensions).
8511 mono_class_get_rank (MonoClass *klass)
8517 * mono_class_get_flags:
8518 * @klass: the MonoClass to act on
8520 * The type flags from the TypeDef table from the metadata.
8521 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8524 * Returns: the flags from the TypeDef table.
8527 mono_class_get_flags (MonoClass *klass)
8529 return klass->flags;
8533 * mono_class_get_name
8534 * @klass: the MonoClass to act on
8536 * Returns: the name of the class.
8539 mono_class_get_name (MonoClass *klass)
8545 * mono_class_get_namespace:
8546 * @klass: the MonoClass to act on
8548 * Returns: the namespace of the class.
8551 mono_class_get_namespace (MonoClass *klass)
8553 return klass->name_space;
8557 * mono_class_get_type:
8558 * @klass: the MonoClass to act on
8560 * This method returns the internal Type representation for the class.
8562 * Returns: the MonoType from the class.
8565 mono_class_get_type (MonoClass *klass)
8567 return &klass->byval_arg;
8571 * mono_class_get_type_token
8572 * @klass: the MonoClass to act on
8574 * This method returns type token for the class.
8576 * Returns: the type token for the class.
8579 mono_class_get_type_token (MonoClass *klass)
8581 return klass->type_token;
8585 * mono_class_get_byref_type:
8586 * @klass: the MonoClass to act on
8591 mono_class_get_byref_type (MonoClass *klass)
8593 return &klass->this_arg;
8597 * mono_class_num_fields:
8598 * @klass: the MonoClass to act on
8600 * Returns: the number of static and instance fields in the class.
8603 mono_class_num_fields (MonoClass *klass)
8605 return klass->field.count;
8609 * mono_class_num_methods:
8610 * @klass: the MonoClass to act on
8612 * Returns: the number of methods in the class.
8615 mono_class_num_methods (MonoClass *klass)
8617 return klass->method.count;
8621 * mono_class_num_properties
8622 * @klass: the MonoClass to act on
8624 * Returns: the number of properties in the class.
8627 mono_class_num_properties (MonoClass *klass)
8629 mono_class_setup_properties (klass);
8631 return klass->ext->property.count;
8635 * mono_class_num_events:
8636 * @klass: the MonoClass to act on
8638 * Returns: the number of events in the class.
8641 mono_class_num_events (MonoClass *klass)
8643 mono_class_setup_events (klass);
8645 return klass->ext->event.count;
8649 * mono_class_get_fields:
8650 * @klass: the MonoClass to act on
8652 * This routine is an iterator routine for retrieving the fields in a class.
8654 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8655 * iterate over all of the elements. When no more values are
8656 * available, the return value is NULL.
8658 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8661 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8663 MonoClassField* field;
8667 mono_class_setup_fields_locking (klass);
8668 if (klass->exception_type)
8670 /* start from the first */
8671 if (klass->field.count) {
8672 return *iter = &klass->fields [0];
8680 if (field < &klass->fields [klass->field.count]) {
8681 return *iter = field;
8687 * mono_class_get_methods
8688 * @klass: the MonoClass to act on
8690 * This routine is an iterator routine for retrieving the fields in a class.
8692 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8693 * iterate over all of the elements. When no more values are
8694 * available, the return value is NULL.
8696 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8699 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8701 MonoMethod** method;
8705 mono_class_setup_methods (klass);
8708 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8709 * FIXME we should better report this error to the caller
8711 if (!klass->methods)
8713 /* start from the first */
8714 if (klass->method.count) {
8715 *iter = &klass->methods [0];
8716 return klass->methods [0];
8724 if (method < &klass->methods [klass->method.count]) {
8732 * mono_class_get_virtual_methods:
8734 * Iterate over the virtual methods of KLASS.
8736 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8739 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8741 MonoMethod** method;
8744 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8746 mono_class_setup_methods (klass);
8748 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8749 * FIXME we should better report this error to the caller
8751 if (!klass->methods)
8753 /* start from the first */
8754 method = &klass->methods [0];
8759 while (method < &klass->methods [klass->method.count]) {
8760 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8764 if (method < &klass->methods [klass->method.count]) {
8771 /* Search directly in metadata to avoid calling setup_methods () */
8772 MonoMethod *res = NULL;
8778 start_index = GPOINTER_TO_UINT (*iter);
8781 for (i = start_index; i < klass->method.count; ++i) {
8784 /* class->method.first points into the methodptr table */
8785 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8787 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8791 if (i < klass->method.count) {
8792 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8793 /* Add 1 here so the if (*iter) check fails */
8794 *iter = GUINT_TO_POINTER (i + 1);
8803 * mono_class_get_properties:
8804 * @klass: the MonoClass to act on
8806 * This routine is an iterator routine for retrieving the properties in a class.
8808 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8809 * iterate over all of the elements. When no more values are
8810 * available, the return value is NULL.
8812 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8815 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8817 MonoProperty* property;
8821 mono_class_setup_properties (klass);
8822 /* start from the first */
8823 if (klass->ext->property.count) {
8824 return *iter = &klass->ext->properties [0];
8832 if (property < &klass->ext->properties [klass->ext->property.count]) {
8833 return *iter = property;
8839 * mono_class_get_events:
8840 * @klass: the MonoClass to act on
8842 * This routine is an iterator routine for retrieving the properties in a class.
8844 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8845 * iterate over all of the elements. When no more values are
8846 * available, the return value is NULL.
8848 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8851 mono_class_get_events (MonoClass* klass, gpointer *iter)
8857 mono_class_setup_events (klass);
8858 /* start from the first */
8859 if (klass->ext->event.count) {
8860 return *iter = &klass->ext->events [0];
8868 if (event < &klass->ext->events [klass->ext->event.count]) {
8869 return *iter = event;
8875 * mono_class_get_interfaces
8876 * @klass: the MonoClass to act on
8878 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8880 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8881 * iterate over all of the elements. When no more values are
8882 * available, the return value is NULL.
8884 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8887 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8895 mono_class_init (klass);
8896 if (!klass->interfaces_inited) {
8897 mono_class_setup_interfaces (klass, &error);
8898 if (!mono_error_ok (&error)) {
8899 mono_error_cleanup (&error);
8903 /* start from the first */
8904 if (klass->interface_count) {
8905 *iter = &klass->interfaces [0];
8906 return klass->interfaces [0];
8914 if (iface < &klass->interfaces [klass->interface_count]) {
8922 setup_nested_types (MonoClass *klass)
8925 GList *classes, *nested_classes, *l;
8928 if (klass->nested_classes_inited)
8931 if (!klass->type_token)
8932 klass->nested_classes_inited = TRUE;
8934 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8938 guint32 cols [MONO_NESTED_CLASS_SIZE];
8939 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8940 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8941 if (!mono_error_ok (&error)) {
8942 /*FIXME don't swallow the error message*/
8943 mono_error_cleanup (&error);
8945 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8949 classes = g_list_prepend (classes, nclass);
8951 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8954 mono_class_alloc_ext (klass);
8956 nested_classes = NULL;
8957 for (l = classes; l; l = l->next)
8958 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
8959 g_list_free (classes);
8961 mono_image_lock (klass->image);
8963 mono_memory_barrier ();
8964 if (!klass->nested_classes_inited) {
8965 klass->ext->nested_classes = nested_classes;
8966 mono_memory_barrier ();
8967 klass->nested_classes_inited = TRUE;
8970 mono_image_unlock (klass->image);
8974 * mono_class_get_nested_types
8975 * @klass: the MonoClass to act on
8977 * This routine is an iterator routine for retrieving the nested types of a class.
8978 * This works only if @klass is non-generic, or a generic type definition.
8980 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8981 * iterate over all of the elements. When no more values are
8982 * available, the return value is NULL.
8984 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8987 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8993 if (!klass->nested_classes_inited)
8994 setup_nested_types (klass);
8997 /* start from the first */
8998 if (klass->ext && klass->ext->nested_classes) {
8999 *iter = klass->ext->nested_classes;
9000 return klass->ext->nested_classes->data;
9002 /* no nested types */
9017 * mono_class_is_delegate
9018 * @klass: the MonoClass to act on
9020 * Returns: true if the MonoClass represents a System.Delegate.
9023 mono_class_is_delegate (MonoClass *klass)
9025 return klass->delegate;
9029 * mono_class_implements_interface
9030 * @klass: The MonoClass to act on
9031 * @interface: The interface to check if @klass implements.
9033 * Returns: true if @klass implements @interface.
9036 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9038 return mono_class_is_assignable_from (iface, klass);
9042 * mono_field_get_name:
9043 * @field: the MonoClassField to act on
9045 * Returns: the name of the field.
9048 mono_field_get_name (MonoClassField *field)
9054 * mono_field_get_type:
9055 * @field: the MonoClassField to act on
9057 * Returns: MonoType of the field.
9060 mono_field_get_type (MonoClassField *field)
9063 MonoType *type = mono_field_get_type_checked (field, &error);
9064 if (!mono_error_ok (&error)) {
9065 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9066 mono_error_cleanup (&error);
9073 * mono_field_get_type_checked:
9074 * @field: the MonoClassField to act on
9075 * @error: used to return any erro found while retrieving @field type
9077 * Returns: MonoType of the field.
9080 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9082 mono_error_init (error);
9084 mono_field_resolve_type (field, error);
9089 * mono_field_get_parent:
9090 * @field: the MonoClassField to act on
9092 * Returns: MonoClass where the field was defined.
9095 mono_field_get_parent (MonoClassField *field)
9097 return field->parent;
9101 * mono_field_get_flags;
9102 * @field: the MonoClassField to act on
9104 * The metadata flags for a field are encoded using the
9105 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9107 * Returns: the flags for the field.
9110 mono_field_get_flags (MonoClassField *field)
9113 return mono_field_resolve_flags (field);
9114 return field->type->attrs;
9118 * mono_field_get_offset;
9119 * @field: the MonoClassField to act on
9121 * Returns: the field offset.
9124 mono_field_get_offset (MonoClassField *field)
9126 return field->offset;
9130 mono_field_get_rva (MonoClassField *field)
9134 MonoClass *klass = field->parent;
9135 MonoFieldDefaultValue *field_def_values;
9137 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9139 if (!klass->ext || !klass->ext->field_def_values) {
9140 mono_class_alloc_ext (klass);
9142 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9144 mono_image_lock (klass->image);
9145 if (!klass->ext->field_def_values)
9146 klass->ext->field_def_values = field_def_values;
9147 mono_image_unlock (klass->image);
9150 field_index = mono_field_get_index (field);
9152 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9153 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9155 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9156 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9159 return klass->ext->field_def_values [field_index].data;
9163 * mono_field_get_data;
9164 * @field: the MonoClassField to act on
9166 * Returns: pointer to the metadata constant value or to the field
9167 * data if it has an RVA flag.
9170 mono_field_get_data (MonoClassField *field)
9172 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9173 MonoTypeEnum def_type;
9175 return mono_class_get_field_default_value (field, &def_type);
9176 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9177 return mono_field_get_rva (field);
9184 * mono_property_get_name:
9185 * @prop: the MonoProperty to act on
9187 * Returns: the name of the property
9190 mono_property_get_name (MonoProperty *prop)
9196 * mono_property_get_set_method
9197 * @prop: the MonoProperty to act on.
9199 * Returns: the setter method of the property (A MonoMethod)
9202 mono_property_get_set_method (MonoProperty *prop)
9208 * mono_property_get_get_method
9209 * @prop: the MonoProperty to act on.
9211 * Returns: the setter method of the property (A MonoMethod)
9214 mono_property_get_get_method (MonoProperty *prop)
9220 * mono_property_get_parent:
9221 * @prop: the MonoProperty to act on.
9223 * Returns: the MonoClass where the property was defined.
9226 mono_property_get_parent (MonoProperty *prop)
9228 return prop->parent;
9232 * mono_property_get_flags:
9233 * @prop: the MonoProperty to act on.
9235 * The metadata flags for a property are encoded using the
9236 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9238 * Returns: the flags for the property.
9241 mono_property_get_flags (MonoProperty *prop)
9247 * mono_event_get_name:
9248 * @event: the MonoEvent to act on
9250 * Returns: the name of the event.
9253 mono_event_get_name (MonoEvent *event)
9259 * mono_event_get_add_method:
9260 * @event: The MonoEvent to act on.
9262 * Returns: the @add' method for the event (a MonoMethod).
9265 mono_event_get_add_method (MonoEvent *event)
9271 * mono_event_get_remove_method:
9272 * @event: The MonoEvent to act on.
9274 * Returns: the @remove method for the event (a MonoMethod).
9277 mono_event_get_remove_method (MonoEvent *event)
9279 return event->remove;
9283 * mono_event_get_raise_method:
9284 * @event: The MonoEvent to act on.
9286 * Returns: the @raise method for the event (a MonoMethod).
9289 mono_event_get_raise_method (MonoEvent *event)
9291 return event->raise;
9295 * mono_event_get_parent:
9296 * @event: the MonoEvent to act on.
9298 * Returns: the MonoClass where the event is defined.
9301 mono_event_get_parent (MonoEvent *event)
9303 return event->parent;
9307 * mono_event_get_flags
9308 * @event: the MonoEvent to act on.
9310 * The metadata flags for an event are encoded using the
9311 * EVENT_* constants. See the tabledefs.h file for details.
9313 * Returns: the flags for the event.
9316 mono_event_get_flags (MonoEvent *event)
9318 return event->attrs;
9322 * mono_class_get_method_from_name:
9323 * @klass: where to look for the method
9324 * @name: name of the method
9325 * @param_count: number of parameters. -1 for any number.
9327 * Obtains a MonoMethod with a given name and number of parameters.
9328 * It only works if there are no multiple signatures for any given method name.
9331 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9333 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9337 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9339 MonoMethod *res = NULL;
9342 /* Search directly in the metadata to avoid calling setup_methods () */
9343 for (i = 0; i < klass->method.count; ++i) {
9344 guint32 cols [MONO_METHOD_SIZE];
9346 MonoMethodSignature *sig;
9348 /* class->method.first points into the methodptr table */
9349 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9351 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9352 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9353 if (param_count == -1) {
9357 sig = mono_method_signature (method);
9358 if (sig && sig->param_count == param_count) {
9369 * mono_class_get_method_from_name_flags:
9370 * @klass: where to look for the method
9371 * @name_space: name of the method
9372 * @param_count: number of parameters. -1 for any number.
9373 * @flags: flags which must be set in the method
9375 * Obtains a MonoMethod with a given name and number of parameters.
9376 * It only works if there are no multiple signatures for any given method name.
9379 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9381 MonoMethod *res = NULL;
9384 mono_class_init (klass);
9386 if (klass->generic_class && !klass->methods) {
9387 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9389 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9393 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9394 mono_class_setup_methods (klass);
9396 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9397 See mono/tests/array_load_exception.il
9398 FIXME we should better report this error to the caller
9400 if (!klass->methods)
9402 for (i = 0; i < klass->method.count; ++i) {
9403 MonoMethod *method = klass->methods [i];
9405 if (method->name[0] == name [0] &&
9406 !strcmp (name, method->name) &&
9407 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9408 ((method->flags & flags) == flags)) {
9415 res = find_method_in_metadata (klass, name, param_count, flags);
9422 * mono_class_set_failure:
9423 * @klass: class in which the failure was detected
9424 * @ex_type: the kind of exception/error to be thrown (later)
9425 * @ex_data: exception data (specific to each type of exception/error)
9427 * Keep a detected failure informations in the class for later processing.
9428 * Note that only the first failure is kept.
9430 * LOCKING: Acquires the loader lock.
9433 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9435 if (klass->exception_type)
9438 mono_loader_lock ();
9439 klass->exception_type = ex_type;
9441 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9442 mono_loader_unlock ();
9448 * mono_class_get_exception_data:
9450 * Return the exception_data property of KLASS.
9452 * LOCKING: Acquires the loader lock.
9455 mono_class_get_exception_data (MonoClass *klass)
9457 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9461 * mono_classes_init:
9463 * Initialize the resources used by this module.
9466 mono_classes_init (void)
9468 mono_mutex_init (&classes_mutex);
9470 mono_counters_register ("Inflated methods size",
9471 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9472 mono_counters_register ("Inflated classes",
9473 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9474 mono_counters_register ("Inflated classes size",
9475 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9476 mono_counters_register ("MonoClass size",
9477 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9478 mono_counters_register ("MonoClassExt size",
9479 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9483 * mono_classes_cleanup:
9485 * Free the resources used by this module.
9488 mono_classes_cleanup (void)
9490 if (global_interface_bitset)
9491 mono_bitset_free (global_interface_bitset);
9492 global_interface_bitset = NULL;
9493 mono_mutex_destroy (&classes_mutex);
9497 * mono_class_get_exception_for_failure:
9498 * @klass: class in which the failure was detected
9500 * Return a constructed MonoException than the caller can then throw
9501 * using mono_raise_exception - or NULL if no failure is present (or
9502 * doesn't result in an exception).
9505 mono_class_get_exception_for_failure (MonoClass *klass)
9507 gpointer exception_data = mono_class_get_exception_data (klass);
9509 switch (klass->exception_type) {
9510 #ifndef DISABLE_SECURITY
9511 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9512 MonoDomain *domain = mono_domain_get ();
9513 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9514 MonoMethod *method = exception_data;
9515 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9516 MonoObject *exc = NULL;
9520 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9521 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9522 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9524 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9525 return (MonoException*) exc;
9528 case MONO_EXCEPTION_TYPE_LOAD: {
9531 char *str = mono_type_get_full_name (klass);
9532 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9533 name = mono_string_new (mono_domain_get (), str);
9535 ex = mono_get_exception_type_load (name, astr);
9539 case MONO_EXCEPTION_MISSING_METHOD: {
9540 char *class_name = exception_data;
9541 char *assembly_name = class_name + strlen (class_name) + 1;
9543 return mono_get_exception_missing_method (class_name, assembly_name);
9545 case MONO_EXCEPTION_MISSING_FIELD: {
9546 char *class_name = exception_data;
9547 char *member_name = class_name + strlen (class_name) + 1;
9549 return mono_get_exception_missing_field (class_name, member_name);
9551 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9552 char *msg_format = exception_data;
9553 char *assembly_name = msg_format + strlen (msg_format) + 1;
9554 char *msg = g_strdup_printf (msg_format, assembly_name);
9557 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9563 case MONO_EXCEPTION_BAD_IMAGE: {
9564 return mono_get_exception_bad_image_format (exception_data);
9567 MonoLoaderError *error;
9570 error = mono_loader_get_last_error ();
9572 ex = mono_loader_error_prepare_exception (error);
9576 /* TODO - handle other class related failures */
9583 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9585 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9586 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9588 if (outer_klass == inner_klass)
9590 inner_klass = inner_klass->nested_in;
9591 } while (inner_klass);
9596 mono_class_get_generic_type_definition (MonoClass *klass)
9598 return klass->generic_class ? klass->generic_class->container_class : klass;
9602 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9604 * Generic instantiations are ignored for all super types of @klass.
9606 * Visibility checks ignoring generic instantiations.
9609 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9612 klass = mono_class_get_generic_type_definition (klass);
9613 parent = mono_class_get_generic_type_definition (parent);
9614 mono_class_setup_supertypes (klass);
9616 for (i = 0; i < klass->idepth; ++i) {
9617 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9623 * Subtype can only access parent members with family protection if the site object
9624 * is subclass of Subtype. For example:
9625 * class A { protected int x; }
9627 * void valid_access () {
9631 * void invalid_access () {
9638 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9640 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9643 if (context_klass == NULL)
9645 /*if access_klass is not member_klass context_klass must be type compat*/
9646 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9652 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9655 if (accessing == accessed)
9657 if (!accessed || !accessing)
9660 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9661 * anywhere so untrusted friends are not safe to access platform's code internals */
9662 if (mono_security_core_clr_enabled ()) {
9663 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9667 mono_assembly_load_friends (accessed);
9668 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9669 MonoAssemblyName *friend = tmp->data;
9670 /* Be conservative with checks */
9673 if (strcmp (accessing->aname.name, friend->name))
9675 if (friend->public_key_token [0]) {
9676 if (!accessing->aname.public_key_token [0])
9678 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9687 * If klass is a generic type or if it is derived from a generic type, return the
9688 * MonoClass of the generic definition
9689 * Returns NULL if not found
9692 get_generic_definition_class (MonoClass *klass)
9695 if (klass->generic_class && klass->generic_class->container_class)
9696 return klass->generic_class->container_class;
9697 klass = klass->parent;
9703 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9706 for (i = 0; i < ginst->type_argc; ++i) {
9707 MonoType *type = ginst->type_argv[i];
9708 switch (type->type) {
9709 case MONO_TYPE_SZARRAY:
9710 if (!can_access_type (access_klass, type->data.klass))
9713 case MONO_TYPE_ARRAY:
9714 if (!can_access_type (access_klass, type->data.array->eklass))
9718 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9721 case MONO_TYPE_CLASS:
9722 case MONO_TYPE_VALUETYPE:
9723 case MONO_TYPE_GENERICINST:
9724 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9732 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9736 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9739 if (access_klass->element_class && !access_klass->enumtype)
9740 access_klass = access_klass->element_class;
9742 if (member_klass->element_class && !member_klass->enumtype)
9743 member_klass = member_klass->element_class;
9745 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9747 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9750 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9753 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9756 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9759 /*Non nested type with nested visibility. We just fail it.*/
9760 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9763 switch (access_level) {
9764 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9765 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9767 case TYPE_ATTRIBUTE_PUBLIC:
9770 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9773 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9774 return is_nesting_type (member_klass, access_klass);
9776 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9777 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9779 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9780 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9782 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9783 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9784 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9786 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9787 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9788 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9793 /* FIXME: check visibility of type, too */
9795 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9797 MonoClass *member_generic_def;
9798 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9801 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9802 access_klass->generic_container) &&
9803 (member_generic_def = get_generic_definition_class (member_klass))) {
9804 MonoClass *access_container;
9806 if (access_klass->generic_container)
9807 access_container = access_klass;
9809 access_container = access_klass->generic_class->container_class;
9811 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9815 /* Partition I 8.5.3.2 */
9816 /* the access level values are the same for fields and methods */
9817 switch (access_level) {
9818 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9819 /* same compilation unit */
9820 return access_klass->image == member_klass->image;
9821 case FIELD_ATTRIBUTE_PRIVATE:
9822 return access_klass == member_klass;
9823 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9824 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9825 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9828 case FIELD_ATTRIBUTE_ASSEMBLY:
9829 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9830 case FIELD_ATTRIBUTE_FAMILY:
9831 if (is_valid_family_access (access_klass, member_klass, context_klass))
9834 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9835 if (is_valid_family_access (access_klass, member_klass, context_klass))
9837 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9838 case FIELD_ATTRIBUTE_PUBLIC:
9845 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9847 /* FIXME: check all overlapping fields */
9848 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9850 MonoClass *nested = method->klass->nested_in;
9852 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9855 nested = nested->nested_in;
9862 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9864 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9866 MonoClass *nested = method->klass->nested_in;
9868 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9871 nested = nested->nested_in;
9876 * with generics calls to explicit interface implementations can be expressed
9877 * directly: the method is private, but we must allow it. This may be opening
9878 * a hole or the generics code should handle this differently.
9879 * Maybe just ensure the interface type is public.
9881 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9887 * mono_method_can_access_method_full:
9888 * @method: The caller method
9889 * @called: The called method
9890 * @context_klass: The static type on stack of the owner @called object used
9892 * This function must be used with instance calls, as they have more strict family accessibility.
9893 * It can be used with static methods, but context_klass should be NULL.
9895 * Returns: TRUE if caller have proper visibility and acessibility to @called
9898 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9900 MonoClass *access_class = method->klass;
9901 MonoClass *member_class = called->klass;
9902 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9904 MonoClass *nested = access_class->nested_in;
9906 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9909 nested = nested->nested_in;
9916 can = can_access_type (access_class, member_class);
9918 MonoClass *nested = access_class->nested_in;
9920 can = can_access_type (nested, member_class);
9923 nested = nested->nested_in;
9930 if (called->is_inflated) {
9931 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9932 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9941 * mono_method_can_access_field_full:
9942 * @method: The caller method
9943 * @field: The accessed field
9944 * @context_klass: The static type on stack of the owner @field object used
9946 * This function must be used with instance fields, as they have more strict family accessibility.
9947 * It can be used with static fields, but context_klass should be NULL.
9949 * Returns: TRUE if caller have proper visibility and acessibility to @field
9952 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9954 MonoClass *access_class = method->klass;
9955 MonoClass *member_class = field->parent;
9956 /* FIXME: check all overlapping fields */
9957 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9959 MonoClass *nested = access_class->nested_in;
9961 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9964 nested = nested->nested_in;
9971 can = can_access_type (access_class, member_class);
9973 MonoClass *nested = access_class->nested_in;
9975 can = can_access_type (nested, member_class);
9978 nested = nested->nested_in;
9988 * mono_class_can_access_class:
9989 * @source_class: The source class
9990 * @target_class: The accessed class
9992 * This function returns is @target_class is visible to @source_class
9994 * Returns: TRUE if source have proper visibility and acessibility to target
9997 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9999 return can_access_type (source_class, target_class);
10003 * mono_type_is_valid_enum_basetype:
10004 * @type: The MonoType to check
10006 * Returns: TRUE if the type can be used as the basetype of an enum
10008 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10009 switch (type->type) {
10012 case MONO_TYPE_BOOLEAN:
10015 case MONO_TYPE_CHAR:
10028 * mono_class_is_valid_enum:
10029 * @klass: An enum class to be validated
10031 * This method verify the required properties an enum should have.
10033 * Returns: TRUE if the informed enum class is valid
10035 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10036 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10037 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10039 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10040 MonoClassField * field;
10041 gpointer iter = NULL;
10042 gboolean found_base_field = FALSE;
10044 g_assert (klass->enumtype);
10045 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10046 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10050 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10053 while ((field = mono_class_get_fields (klass, &iter))) {
10054 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10055 if (found_base_field)
10057 found_base_field = TRUE;
10058 if (!mono_type_is_valid_enum_basetype (field->type))
10063 if (!found_base_field)
10066 if (klass->method.count > 0)
10073 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10075 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10079 * mono_class_setup_interface_id:
10081 * Initializes MonoClass::interface_id if required.
10083 * LOCKING: Acquires the loader lock.
10086 mono_class_setup_interface_id (MonoClass *class)
10088 mono_loader_lock ();
10089 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10090 class->interface_id = mono_get_unique_iid (class);
10091 mono_loader_unlock ();
10095 * mono_class_alloc_ext:
10097 * Allocate klass->ext if not already done.
10100 mono_class_alloc_ext (MonoClass *klass)
10107 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10108 mono_image_lock (klass->image);
10109 mono_memory_barrier ();
10112 class_ext_size += sizeof (MonoClassExt);
10113 mono_image_unlock (klass->image);
10117 * mono_class_setup_interfaces:
10119 * Initialize class->interfaces/interfaces_count.
10120 * LOCKING: Acquires the loader lock.
10121 * This function can fail the type.
10124 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10126 int i, interface_count;
10127 MonoClass **interfaces;
10129 mono_error_init (error);
10131 if (klass->interfaces_inited)
10134 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10135 MonoType *args [1];
10137 /* generic IList, ICollection, IEnumerable */
10138 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10139 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10141 args [0] = &klass->element_class->byval_arg;
10142 interfaces [0] = mono_class_bind_generic_parameters (
10143 mono_defaults.generic_ilist_class, 1, args, FALSE);
10144 if (interface_count > 1)
10145 interfaces [1] = mono_class_bind_generic_parameters (
10146 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10147 } else if (klass->generic_class) {
10148 MonoClass *gklass = klass->generic_class->container_class;
10150 mono_class_setup_interfaces (gklass, error);
10151 if (!mono_error_ok (error)) {
10152 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10156 interface_count = gklass->interface_count;
10157 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10158 for (i = 0; i < interface_count; i++) {
10159 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10160 if (!mono_error_ok (error)) {
10161 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10166 interface_count = 0;
10170 mono_image_lock (klass->image);
10172 if (!klass->interfaces_inited) {
10173 klass->interface_count = interface_count;
10174 klass->interfaces = interfaces;
10176 mono_memory_barrier ();
10178 klass->interfaces_inited = TRUE;
10181 mono_image_unlock (klass->image);
10185 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10187 MonoClass *class = field->parent;
10188 MonoImage *image = class->image;
10189 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10190 int field_idx = field - class->fields;
10192 mono_error_init (error);
10195 MonoClassField *gfield = >d->fields [field_idx];
10196 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10197 if (!mono_error_ok (error)) {
10198 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10199 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10203 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10204 if (!mono_error_ok (error)) {
10205 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10206 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10211 guint32 cols [MONO_FIELD_SIZE];
10212 MonoGenericContainer *container = NULL;
10213 int idx = class->field.first + field_idx;
10215 /*FIXME, in theory we do not lazy load SRE fields*/
10216 g_assert (!image_is_dynamic (image));
10218 if (class->generic_container) {
10219 container = class->generic_container;
10221 container = gtd->generic_container;
10222 g_assert (container);
10225 /* class->field.first and idx points into the fieldptr table */
10226 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10228 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10229 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10230 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10234 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10236 mono_metadata_decode_value (sig, &sig);
10237 /* FIELD signature == 0x06 */
10238 g_assert (*sig == 0x06);
10239 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10241 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10246 mono_field_resolve_flags (MonoClassField *field)
10248 MonoClass *class = field->parent;
10249 MonoImage *image = class->image;
10250 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10251 int field_idx = field - class->fields;
10255 MonoClassField *gfield = >d->fields [field_idx];
10256 return mono_field_get_flags (gfield);
10258 int idx = class->field.first + field_idx;
10260 /*FIXME, in theory we do not lazy load SRE fields*/
10261 g_assert (!image_is_dynamic (image));
10263 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10268 * mono_class_setup_basic_field_info:
10269 * @class: The class to initialize
10271 * Initializes the class->fields array of fields.
10272 * Aquires the loader lock.
10275 mono_class_setup_basic_field_info_locking (MonoClass *class)
10277 mono_loader_lock ();
10278 mono_class_setup_basic_field_info (class);
10279 mono_loader_unlock ();
10283 * mono_class_get_fields_lazy:
10284 * @klass: the MonoClass to act on
10286 * This routine is an iterator routine for retrieving the fields in a class.
10287 * Only minimal information about fields are loaded. Accessors must be used
10288 * for all MonoClassField returned.
10290 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10291 * iterate over all of the elements. When no more values are
10292 * available, the return value is NULL.
10294 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10297 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10299 MonoClassField* field;
10303 mono_class_setup_basic_field_info_locking (klass);
10304 if (!klass->fields)
10306 /* start from the first */
10307 if (klass->field.count) {
10308 return *iter = &klass->fields [0];
10316 if (field < &klass->fields [klass->field.count]) {
10317 return *iter = field;
10323 mono_class_full_name (MonoClass *klass)
10325 return mono_type_full_name (&klass->byval_arg);