2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001-2006 Novell, Inc.
17 #include <mono/io-layer/atomic.h>
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/cil-coff.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/metadata-internals.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/os/gc_wrapper.h>
36 #include <mono/utils/mono-counters.h>
40 gboolean mono_print_vtable = FALSE;
42 /* Function supplied by the runtime to find classes by name using information from the AOT file */
43 static MonoGetClassFromName get_class_from_name = NULL;
45 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
46 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
48 void (*mono_debugger_start_class_init_func) (MonoClass *klass) = NULL;
49 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
52 * mono_class_from_typeref:
54 * @type_token: a TypeRef token
56 * Creates the MonoClass* structure representing the type defined by
57 * the typeref token valid inside @image.
58 * Returns: the MonoClass* representing the typeref token, NULL ifcould
62 mono_class_from_typeref (MonoImage *image, guint32 type_token)
64 guint32 cols [MONO_TYPEREF_SIZE];
65 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
67 const char *name, *nspace;
71 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
73 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
74 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
76 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
77 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
78 case MONO_RESOLTION_SCOPE_MODULE:
80 g_error ("null ResolutionScope not yet handled");
81 /* a typedef in disguise */
82 return mono_class_from_name (image, nspace, name);
83 case MONO_RESOLTION_SCOPE_MODULEREF:
84 module = mono_image_load_module (image, idx);
86 return mono_class_from_name (module, nspace, name);
88 char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
91 human_name = mono_stringify_assembly_name (&image->assembly->aname);
92 mono_loader_set_error_type_load (msg, human_name);
98 case MONO_RESOLTION_SCOPE_TYPEREF: {
99 MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
102 if (enclosing->inited) {
103 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
104 for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
106 if (strcmp (res->name, name) == 0)
110 /* Don't call mono_class_init as we might've been called by it recursively */
111 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
113 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
114 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
115 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
117 if (strcmp (nname, name) == 0)
118 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
120 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
123 g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
126 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
130 if (!image->references || !image->references [idx - 1])
131 mono_assembly_load_reference (image, idx - 1);
132 g_assert (image->references [idx - 1]);
134 /* If the assembly did not load, register this as a type load exception */
135 if (image->references [idx - 1] == REFERENCE_MISSING){
136 MonoAssemblyName aname;
139 mono_assembly_get_assemblyref (image, idx - 1, &aname);
140 human_name = mono_stringify_assembly_name (&aname);
141 mono_loader_set_error_assembly_load (human_name, image->assembly->ref_only);
147 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
150 /* Copy everything mono_metadata_free_array free. */
152 mono_dup_array_type (MonoArrayType *a)
154 a = g_memdup (a, sizeof (MonoArrayType));
156 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
158 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
162 /* Copy everything mono_metadata_free_method_signature free. */
164 mono_metadata_signature_deep_dup (MonoMethodSignature *sig)
168 sig = mono_metadata_signature_dup (sig);
170 sig->ret = mono_metadata_type_dup (NULL, sig->ret);
171 for (i = 0; i < sig->param_count; ++i)
172 sig->params [i] = mono_metadata_type_dup (NULL, sig->params [i]);
178 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
180 MonoAssembly *ta = klass->image->assembly;
182 g_string_append_printf (
183 str, ", %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
185 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
186 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
187 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
191 mono_type_name_check_byref (MonoType *type, GString *str)
194 g_string_append_c (str, '&');
198 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
199 MonoTypeNameFormat format)
203 switch (type->type) {
204 case MONO_TYPE_ARRAY: {
205 int i, rank = type->data.array->rank;
206 MonoTypeNameFormat nested_format;
208 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
209 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
211 mono_type_get_name_recurse (
212 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
213 g_string_append_c (str, '[');
215 g_string_append_c (str, '*');
216 for (i = 1; i < rank; i++)
217 g_string_append_c (str, ',');
218 g_string_append_c (str, ']');
220 mono_type_name_check_byref (type, str);
222 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
223 _mono_type_get_assembly_name (type->data.array->eklass, str);
226 case MONO_TYPE_SZARRAY: {
227 MonoTypeNameFormat nested_format;
229 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
230 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
232 mono_type_get_name_recurse (
233 &type->data.klass->byval_arg, str, FALSE, nested_format);
234 g_string_append (str, "[]");
236 mono_type_name_check_byref (type, str);
238 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
239 _mono_type_get_assembly_name (type->data.klass, str);
242 case MONO_TYPE_PTR: {
243 MonoTypeNameFormat nested_format;
245 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
246 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
248 mono_type_get_name_recurse (
249 type->data.type, str, FALSE, nested_format);
250 g_string_append_c (str, '*');
252 mono_type_name_check_byref (type, str);
254 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
255 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
260 g_assert (type->data.generic_param->name);
261 g_string_append (str, type->data.generic_param->name);
263 mono_type_name_check_byref (type, str);
267 klass = mono_class_from_mono_type (type);
268 if (klass->nested_in) {
269 mono_type_get_name_recurse (
270 &klass->nested_in->byval_arg, str, TRUE, format);
271 if (format == MONO_TYPE_NAME_FORMAT_IL)
272 g_string_append_c (str, '.');
274 g_string_append_c (str, '+');
275 } else if (*klass->name_space) {
276 g_string_append (str, klass->name_space);
277 g_string_append_c (str, '.');
279 if (format == MONO_TYPE_NAME_FORMAT_IL) {
280 char *s = strchr (klass->name, '`');
281 int len = s ? s - klass->name : strlen (klass->name);
283 g_string_append_len (str, klass->name, len);
285 g_string_append (str, klass->name);
288 if (klass->generic_class) {
289 MonoGenericClass *gclass = klass->generic_class;
290 MonoGenericInst *inst = gclass->context.class_inst;
291 MonoTypeNameFormat nested_format;
294 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
295 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
297 if (format == MONO_TYPE_NAME_FORMAT_IL)
298 g_string_append_c (str, '<');
300 g_string_append_c (str, '[');
301 for (i = 0; i < inst->type_argc; i++) {
302 MonoType *t = inst->type_argv [i];
305 g_string_append_c (str, ',');
306 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
307 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
308 g_string_append_c (str, '[');
309 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
310 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
311 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
312 g_string_append_c (str, ']');
314 if (format == MONO_TYPE_NAME_FORMAT_IL)
315 g_string_append_c (str, '>');
317 g_string_append_c (str, ']');
318 } else if (klass->generic_container &&
319 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
320 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
323 if (format == MONO_TYPE_NAME_FORMAT_IL)
324 g_string_append_c (str, '<');
326 g_string_append_c (str, '[');
327 for (i = 0; i < klass->generic_container->type_argc; i++) {
329 g_string_append_c (str, ',');
330 g_string_append (str, klass->generic_container->type_params [i].name);
332 if (format == MONO_TYPE_NAME_FORMAT_IL)
333 g_string_append_c (str, '>');
335 g_string_append_c (str, ']');
338 mono_type_name_check_byref (type, str);
340 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
341 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
342 _mono_type_get_assembly_name (klass, str);
348 * mono_type_get_name:
350 * @format: the format for the return string.
353 * Returns: the string representation in a number of formats:
355 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
356 * returned in the formatrequired by System.Reflection, this is the
357 * inverse of mono_reflection_parse_type ().
359 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
360 * be used by the IL assembler.
362 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
364 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
367 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
371 result = g_string_new ("");
373 mono_type_get_name_recurse (type, result, FALSE, format);
375 return g_string_free (result, FALSE);
379 * mono_type_get_full_name:
382 * Returns: the string representation for type as required by System.Reflection.
383 * The inverse of mono_reflection_parse_type ().
386 mono_type_get_full_name (MonoClass *class)
388 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
392 * mono_type_get_name:
395 * Returns: the string representation for type as it would be represented in IL code.
398 mono_type_get_name (MonoType *type)
400 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
404 * mono_type_get_underlying_type:
407 * Returns: the MonoType for the underlying integer type if @type
408 * is an enum and byref is false, otherwise the type itself.
411 mono_type_get_underlying_type (MonoType *type)
413 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
414 return type->data.klass->enum_basetype;
415 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
416 return type->data.generic_class->container_class->enum_basetype;
421 * mono_class_is_open_constructed_type:
424 * Returns TRUE if type represents a generics open constructed type
425 * (not all the type parameters required for the instantiation have
429 mono_class_is_open_constructed_type (MonoType *t)
435 case MONO_TYPE_SZARRAY:
436 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
437 case MONO_TYPE_ARRAY:
438 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
440 return mono_class_is_open_constructed_type (t->data.type);
441 case MONO_TYPE_GENERICINST:
442 return t->data.generic_class->context.class_inst->is_open;
449 inflate_generic_type (MonoType *type, MonoGenericContext *context)
451 switch (type->type) {
452 case MONO_TYPE_MVAR: {
454 int num = type->data.generic_param->num;
455 MonoGenericInst *inst = context->method_inst;
456 if (!inst || !inst->type_argv)
458 if (num >= inst->type_argc)
459 g_error ("MVAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc);
462 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
463 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
464 * ->byref and ->attrs from @type are propagated to the returned type.
466 nt = mono_metadata_type_dup (NULL, inst->type_argv [num]);
467 nt->byref = type->byref;
468 nt->attrs = type->attrs;
471 case MONO_TYPE_VAR: {
473 int num = type->data.generic_param->num;
474 MonoGenericInst *inst = context->class_inst;
477 if (num >= inst->type_argc)
478 g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc);
479 nt = mono_metadata_type_dup (NULL, inst->type_argv [num]);
480 nt->byref = type->byref;
481 nt->attrs = type->attrs;
484 case MONO_TYPE_SZARRAY: {
485 MonoClass *eclass = type->data.klass;
486 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
489 nt = mono_metadata_type_dup (NULL, type);
490 nt->data.klass = mono_class_from_mono_type (inflated);
493 case MONO_TYPE_ARRAY: {
494 MonoClass *eclass = type->data.array->eklass;
495 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
498 nt = mono_metadata_type_dup (NULL, type);
499 nt->data.array = g_memdup (nt->data.array, sizeof (MonoArrayType));
500 nt->data.array->eklass = mono_class_from_mono_type (inflated);
503 case MONO_TYPE_GENERICINST: {
504 MonoGenericClass *gclass = type->data.generic_class;
505 MonoGenericInst *inst;
507 if (!gclass->context.class_inst->is_open)
510 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context);
511 if (inst != gclass->context.class_inst)
512 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
514 if (gclass == type->data.generic_class)
517 nt = mono_metadata_type_dup (NULL, type);
518 nt->data.generic_class = gclass;
521 case MONO_TYPE_CLASS:
522 case MONO_TYPE_VALUETYPE: {
523 MonoClass *klass = type->data.klass;
524 MonoGenericContainer *container = klass->generic_container;
525 MonoGenericInst *inst;
526 MonoGenericClass *gclass = NULL;
532 /* We can't use context->class_inst directly, since it can have more elements */
533 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context);
534 gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
536 nt = mono_metadata_type_dup (NULL, type);
537 nt->type = MONO_TYPE_GENERICINST;
538 nt->data.generic_class = gclass;
548 mono_generic_class_get_context (MonoGenericClass *gclass)
550 return &gclass->context;
554 mono_class_get_context (MonoClass *class)
556 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
560 * mono_class_inflate_generic_type:
562 * @context: a generics context
564 * Instantiate the generic type @type, using the generics context @context.
566 * Returns: the instantiated type
569 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
571 MonoType *inflated = inflate_generic_type (type, context);
574 return mono_metadata_type_dup (NULL, type);
576 mono_stats.inflated_type_count++;
580 static MonoGenericContext
581 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
583 MonoGenericInst *class_inst = NULL;
584 MonoGenericInst *method_inst = NULL;
585 MonoGenericContext res;
587 if (context->class_inst)
588 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with);
590 if (context->method_inst)
591 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with);
593 res.class_inst = class_inst;
594 res.method_inst = method_inst;
600 * mono_class_inflate_generic_method:
601 * @method: a generic method
602 * @context: a generics context
604 * Instantiate the generic method @method using the generics context @context.
606 * Returns: the new instantiated method
609 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
611 return mono_class_inflate_generic_method_full (method, NULL, context);
615 * mono_class_inflate_generic_method:
617 * Instantiate method @method with the generic context @context.
618 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
619 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
622 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
625 MonoMethodInflated *iresult, *cached;
626 MonoMethodSignature *sig;
627 MonoGenericContext tmp_context;
629 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
630 while (method->is_inflated) {
631 MonoGenericContext *method_context = mono_method_get_context (method);
632 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
634 tmp_context = inflate_generic_context (method_context, context);
635 context = &tmp_context;
637 if (mono_metadata_generic_context_equal (method_context, context))
640 method = imethod->declaring;
643 if (!method->generic_container && !method->klass->generic_container)
646 mono_stats.inflated_method_count++;
647 iresult = g_new0 (MonoMethodInflated, 1);
648 iresult->context = *context;
649 iresult->declaring = method;
652 cached = mono_method_inflated_lookup (iresult, FALSE);
654 mono_loader_unlock ();
656 return (MonoMethod*)cached;
659 sig = mono_method_signature (method);
661 iresult->method.pinvoke = *(MonoMethodPInvoke*)method;
663 iresult->method.normal = *(MonoMethodNormal*)method;
664 iresult->method.normal.header = NULL;
667 result = (MonoMethod *) iresult;
668 result->is_inflated = 1;
669 /* result->generic_container = NULL; */
670 result->signature = NULL;
672 if (!klass_hint || !klass_hint->generic_class ||
673 klass_hint->generic_class->container_class != method->klass ||
674 klass_hint->generic_class->context.class_inst != context->class_inst)
677 if (method->klass->generic_container)
678 result->klass = klass_hint;
680 if (!result->klass) {
681 MonoType *inflated = inflate_generic_type (&method->klass->byval_arg, context);
682 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
685 if (context->method_inst)
686 result->generic_container = NULL;
687 else if (method->generic_container)
688 iresult->context.method_inst = method->generic_container->context.method_inst;
690 mono_method_inflated_lookup (iresult, TRUE);
691 mono_loader_unlock ();
696 * mono_get_inflated_method:
698 * Obsolete. We keep it around since it's mentioned in the public API.
701 mono_get_inflated_method (MonoMethod *method)
707 mono_method_get_context (MonoMethod *method)
709 MonoMethodInflated *imethod;
710 if (!method->is_inflated)
712 imethod = (MonoMethodInflated *) method;
713 return &imethod->context;
717 * mono_class_find_enum_basetype:
718 * @class: The enum class
720 * Determine the basetype of an enum by iterating through its fields. We do this
721 * in a separate function since it is cheaper than calling mono_class_setup_fields.
724 mono_class_find_enum_basetype (MonoClass *class)
726 MonoImage *m = class->image;
727 const int top = class->field.count;
730 g_assert (class->enumtype);
733 * Fetch all the field information.
735 for (i = 0; i < top; i++){
737 guint32 cols [MONO_FIELD_SIZE];
738 int idx = class->field.first + i;
739 MonoGenericContainer *container = NULL;
742 /* class->field.first and idx points into the fieldptr table */
743 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
744 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
745 mono_metadata_decode_value (sig, &sig);
746 /* FIELD signature == 0x06 */
747 g_assert (*sig == 0x06);
748 if (class->generic_container)
749 container = class->generic_container;
750 else if (class->generic_class) {
751 MonoClass *gklass = class->generic_class->container_class;
753 container = gklass->generic_container;
754 g_assert (container);
756 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
759 if (class->generic_class) {
760 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
761 ftype->attrs = cols [MONO_FIELD_FLAGS];
764 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC))
772 * mono_class_setup_fields:
773 * @class: The class to initialize
775 * Initializes the class->fields.
776 * LOCKING: Assumes the loader lock is held.
779 mono_class_setup_fields (MonoClass *class)
781 MonoImage *m = class->image;
782 int top = class->field.count;
783 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
784 int i, blittable = TRUE;
785 guint32 real_size = 0;
786 guint32 packing_size = 0;
787 gboolean explicit_size;
788 MonoClassField *field;
789 MonoGenericContainer *container = NULL;
790 MonoClass *gklass = NULL;
792 if (class->size_inited)
795 if (class->generic_class) {
796 MonoClass *gklass = class->generic_class->container_class;
797 mono_class_setup_fields (gklass);
798 top = gklass->field.count;
801 class->instance_size = 0;
803 class->sizes.class_size = 0;
806 /* For generic instances, class->parent might not have been initialized */
807 mono_class_init (class->parent);
808 if (!class->parent->size_inited)
809 mono_class_setup_fields (class->parent);
810 class->instance_size += class->parent->instance_size;
811 class->min_align = class->parent->min_align;
812 /* we use |= since it may have been set already */
813 class->has_references |= class->parent->has_references;
814 blittable = class->parent->blittable;
816 class->instance_size = sizeof (MonoObject);
817 class->min_align = 1;
820 /* Get the real size */
821 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
824 g_assert ((packing_size & 0xfffffff0) == 0);
825 class->packing_size = packing_size;
826 real_size += class->instance_size;
830 if (explicit_size && real_size) {
831 class->instance_size = MAX (real_size, class->instance_size);
833 class->size_inited = 1;
834 class->blittable = blittable;
838 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
841 /* Prevent infinite loops if the class references itself */
842 class->size_inited = 1;
844 class->fields = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassField) * top);
846 if (class->generic_container) {
847 container = class->generic_container;
848 } else if (class->generic_class) {
849 gklass = class->generic_class->container_class;
850 container = gklass->generic_container;
851 g_assert (container);
853 mono_class_setup_fields (gklass);
857 * Fetch all the field information.
859 for (i = 0; i < top; i++){
860 int idx = class->field.first + i;
861 field = &class->fields [i];
863 field->parent = class;
865 if (class->generic_class) {
866 MonoClassField *gfield = &gklass->fields [i];
867 MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
869 ifield->generic_type = gfield->type;
870 field->name = gfield->name;
871 field->generic_info = ifield;
872 field->type = mono_class_inflate_generic_type (gfield->type, mono_class_get_context (class));
873 field->type->attrs = gfield->type->attrs;
874 if (mono_field_is_deleted (field))
876 field->offset = gfield->offset;
877 field->data = gfield->data;
881 guint32 cols [MONO_FIELD_SIZE];
883 /* class->field.first and idx points into the fieldptr table */
884 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
885 /* The name is needed for fieldrefs */
886 field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
887 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
888 mono_metadata_decode_value (sig, &sig);
889 /* FIELD signature == 0x06 */
890 g_assert (*sig == 0x06);
891 field->type = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
893 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
896 if (mono_field_is_deleted (field))
898 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
900 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
901 field->offset = offset;
902 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
903 g_warning ("%s not initialized correctly (missing field layout info for %s)",
904 class->name, field->name);
907 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
908 mono_metadata_field_info (m, idx, NULL, &rva, NULL);
910 g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
911 field->data = mono_image_rva_map (class->image, rva);
915 /* Only do these checks if we still think this type is blittable */
916 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
917 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
920 MonoClass *field_class = mono_class_from_mono_type (field->type);
921 if (!field_class || !field_class->blittable)
926 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
927 class->enum_basetype = field->type;
928 class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
929 blittable = class->element_class->blittable;
932 /* The def_value of fields is compute lazily during vtable creation */
935 if (class == mono_defaults.string_class)
938 class->blittable = blittable;
940 if (class->enumtype && !class->enum_basetype) {
941 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
944 if (explicit_size && real_size) {
945 class->instance_size = MAX (real_size, class->instance_size);
948 if (class->exception_type)
950 mono_class_layout_fields (class);
954 * mono_class_setup_fields_locking:
955 * @class: The class to initialize
957 * Initializes the class->fields array of fields.
958 * Aquires the loader lock.
961 mono_class_setup_fields_locking (MonoClass *class)
964 mono_class_setup_fields (class);
965 mono_loader_unlock ();
969 * mono_class_has_references:
971 * Returns whenever @klass->has_references is set, initializing it if needed.
972 * Aquires the loader lock.
975 mono_class_has_references (MonoClass *klass)
977 if (klass->init_pending) {
978 /* Be conservative */
981 mono_class_init (klass);
983 return klass->has_references;
987 /* useful until we keep track of gc-references in corlib etc. */
989 #define IS_GC_REFERENCE(t) FALSE
991 #define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U && class->image == mono_defaults.corlib)
995 * mono_class_layout_fields:
998 * Compute the placement of fields inside an object or struct, according to
999 * the layout rules and set the following fields in @class:
1000 * - has_references (if the class contains instance references firled or structs that contain references)
1001 * - has_static_refs (same, but for static fields)
1002 * - instance_size (size of the object in memory)
1003 * - class_size (size needed for the static fields)
1004 * - size_inited (flag set when the instance_size is set)
1006 * LOCKING: this is supposed to be called with the loader lock held.
1009 mono_class_layout_fields (MonoClass *class)
1012 const int top = class->field.count;
1013 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1014 guint32 pass, passes, real_size;
1015 gboolean gc_aware_layout = FALSE;
1016 MonoClassField *field;
1018 if (class->generic_container ||
1019 (class->generic_class && class->generic_class->context.class_inst->is_open))
1023 * Enable GC aware auto layout: in this mode, reference
1024 * fields are grouped together inside objects, increasing collector
1026 * Requires that all classes whose layout is known to native code be annotated
1027 * with [StructLayout (LayoutKind.Sequential)]
1028 * Value types have gc_aware_layout disabled by default, as per
1029 * what the default is for other runtimes.
1031 /* corlib is missing [StructLayout] directives in many places */
1032 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1033 if (class->image != mono_defaults.corlib &&
1034 class->byval_arg.type != MONO_TYPE_VALUETYPE)
1035 gc_aware_layout = TRUE;
1036 /* from System.dll, used in metadata/process.h */
1037 if (strcmp (class->name, "ProcessStartInfo") == 0)
1038 gc_aware_layout = FALSE;
1041 /* Compute klass->has_references */
1043 * Process non-static fields first, since static fields might recursively
1044 * refer to the class itself.
1046 for (i = 0; i < top; i++) {
1049 field = &class->fields [i];
1051 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1052 ftype = mono_type_get_underlying_type (field->type);
1053 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1054 class->has_references = TRUE;
1058 for (i = 0; i < top; i++) {
1061 field = &class->fields [i];
1063 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1064 ftype = mono_type_get_underlying_type (field->type);
1065 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1066 class->has_static_refs = TRUE;
1070 for (i = 0; i < top; i++) {
1073 field = &class->fields [i];
1075 ftype = mono_type_get_underlying_type (field->type);
1076 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1077 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1078 class->has_static_refs = TRUE;
1080 class->has_references = TRUE;
1085 * Compute field layout and total size (not considering static fields)
1089 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1090 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1092 if (gc_aware_layout)
1097 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1101 real_size = class->parent->instance_size;
1103 real_size = sizeof (MonoObject);
1105 for (pass = 0; pass < passes; ++pass) {
1106 for (i = 0; i < top; i++){
1111 field = &class->fields [i];
1113 if (mono_field_is_deleted (field))
1115 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1118 ftype = mono_type_get_underlying_type (field->type);
1119 if (gc_aware_layout) {
1120 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1129 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1130 (strcmp (field->name, "$PRIVATE$") == 0)) {
1131 /* This field is a hack inserted by MCS to empty structures */
1135 size = mono_type_size (field->type, &align);
1137 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1138 align = class->packing_size ? MIN (class->packing_size, align): align;
1139 /* if the field has managed references, we need to force-align it
1142 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1143 align = MAX (align, sizeof (gpointer));
1145 class->min_align = MAX (align, class->min_align);
1146 field->offset = real_size;
1147 field->offset += align - 1;
1148 field->offset &= ~(align - 1);
1149 real_size = field->offset + size;
1152 class->instance_size = MAX (real_size, class->instance_size);
1154 if (class->instance_size & (class->min_align - 1)) {
1155 class->instance_size += class->min_align - 1;
1156 class->instance_size &= ~(class->min_align - 1);
1160 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1162 for (i = 0; i < top; i++) {
1167 field = &class->fields [i];
1170 * There must be info about all the fields in a type if it
1171 * uses explicit layout.
1174 if (mono_field_is_deleted (field))
1176 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1179 size = mono_type_size (field->type, &align);
1182 * When we get here, field->offset is already set by the
1183 * loader (for either runtime fields or fields loaded from metadata).
1184 * The offset is from the start of the object: this works for both
1185 * classes and valuetypes.
1187 field->offset += sizeof (MonoObject);
1188 ftype = mono_type_get_underlying_type (field->type);
1189 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1190 if (field->offset % sizeof (gpointer)) {
1191 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1198 real_size = MAX (real_size, size + field->offset);
1200 class->instance_size = MAX (real_size, class->instance_size);
1204 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1206 * For small structs, set min_align to at least the struct size, since the
1207 * JIT memset/memcpy code assumes this and generates unaligned accesses
1208 * otherwise. See #78990 for a testcase.
1210 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1211 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1214 class->size_inited = 1;
1217 * Compute static field layout and size
1219 for (i = 0; i < top; i++){
1223 field = &class->fields [i];
1225 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1227 if (mono_field_is_deleted (field))
1230 size = mono_type_size (field->type, &align);
1231 field->offset = class->sizes.class_size;
1232 field->offset += align - 1;
1233 field->offset &= ~(align - 1);
1234 class->sizes.class_size = field->offset + size;
1239 * mono_class_setup_methods:
1242 * Initializes the 'methods' array in the klass.
1243 * Calling this method should be avoided if possible since it allocates a lot
1244 * of long-living MonoMethod structures.
1245 * Methods belonging to an interface are assigned a sequential slot starting
1249 mono_class_setup_methods (MonoClass *class)
1252 MonoMethod **methods;
1257 mono_loader_lock ();
1259 if (class->methods) {
1260 mono_loader_unlock ();
1264 //printf ("INIT: %s.%s\n", class->name_space, class->name);
1266 if (!class->methods) {
1267 methods = mono_mempool_alloc (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
1268 for (i = 0; i < class->method.count; ++i) {
1269 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
1270 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
1274 if (MONO_CLASS_IS_INTERFACE (class))
1275 for (i = 0; i < class->method.count; ++i)
1276 methods [i]->slot = i;
1278 /* Leave this assignment as the last op in this function */
1279 class->methods = methods;
1281 mono_loader_unlock ();
1286 mono_class_setup_properties (MonoClass *class)
1288 guint startm, endm, i, j;
1289 guint32 cols [MONO_PROPERTY_SIZE];
1290 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
1291 MonoProperty *properties;
1294 if (class->properties)
1297 mono_loader_lock ();
1299 if (class->properties) {
1300 mono_loader_unlock ();
1304 class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
1305 class->property.count = last - class->property.first;
1307 if (class->property.count)
1308 mono_class_setup_methods (class);
1310 properties = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoProperty) * class->property.count);
1311 for (i = class->property.first; i < last; ++i) {
1312 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
1313 properties [i - class->property.first].parent = class;
1314 properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
1315 properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
1317 startm = mono_metadata_methods_from_property (class->image, i, &endm);
1318 for (j = startm; j < endm; ++j) {
1321 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
1323 if (class->image->uncompressed_metadata)
1324 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
1325 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
1327 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1329 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
1330 case METHOD_SEMANTIC_SETTER:
1331 properties [i - class->property.first].set = method;
1333 case METHOD_SEMANTIC_GETTER:
1334 properties [i - class->property.first].get = method;
1342 /* Leave this assignment as the last op in the function */
1343 class->properties = properties;
1345 mono_loader_unlock ();
1349 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
1351 MonoMethod **om, **retval;
1354 for (om = methods, count = 0; *om; ++om, ++count)
1357 retval = g_new0 (MonoMethod*, count + 1);
1359 for (om = methods, count = 0; *om; ++om, ++count)
1360 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
1366 mono_class_setup_events (MonoClass *class)
1368 guint startm, endm, i, j;
1369 guint32 cols [MONO_EVENT_SIZE];
1370 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
1377 mono_loader_lock ();
1379 if (class->events) {
1380 mono_loader_unlock ();
1384 if (class->generic_class) {
1385 MonoClass *gklass = class->generic_class->container_class;
1386 MonoGenericContext *context;
1388 mono_class_setup_events (gklass);
1389 class->event = gklass->event;
1391 class->events = g_new0 (MonoEvent, class->event.count);
1393 if (class->event.count)
1394 context = mono_class_get_context (class);
1396 for (i = 0; i < class->event.count; i++) {
1397 MonoEvent *event = &class->events [i];
1398 MonoEvent *gevent = &gklass->events [i];
1400 event->parent = class;
1401 event->name = gevent->name;
1402 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
1403 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
1404 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
1405 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
1406 event->attrs = gevent->attrs;
1409 mono_loader_unlock ();
1413 class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
1414 class->event.count = last - class->event.first;
1416 if (class->event.count)
1417 mono_class_setup_methods (class);
1419 events = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoEvent) * class->event.count);
1420 for (i = class->event.first; i < last; ++i) {
1421 MonoEvent *event = &events [i - class->event.first];
1423 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
1424 event->parent = class;
1425 event->attrs = cols [MONO_EVENT_FLAGS];
1426 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
1428 startm = mono_metadata_methods_from_event (class->image, i, &endm);
1429 for (j = startm; j < endm; ++j) {
1432 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
1434 if (class->image->uncompressed_metadata)
1435 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
1436 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
1438 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1440 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
1441 case METHOD_SEMANTIC_ADD_ON:
1442 event->add = method;
1444 case METHOD_SEMANTIC_REMOVE_ON:
1445 event->remove = method;
1447 case METHOD_SEMANTIC_FIRE:
1448 event->raise = method;
1450 case METHOD_SEMANTIC_OTHER: {
1453 if (event->other == NULL) {
1454 event->other = g_new0 (MonoMethod*, 2);
1456 while (event->other [n])
1458 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
1460 event->other [n] = method;
1461 /* NULL terminated */
1462 event->other [n + 1] = NULL;
1470 /* Leave this assignment as the last op in the function */
1471 class->events = events;
1473 mono_loader_unlock ();
1477 * Global pool of interface IDs, represented as a bitset.
1478 * LOCKING: this is supposed to be accessed with the loader lock held.
1480 static MonoBitSet *global_interface_bitset = NULL;
1483 * mono_unload_interface_ids:
1484 * @bitset: bit set of interface IDs
1486 * When an image is unloaded, the interface IDs associated with
1487 * the image are put back in the global pool of IDs so the numbers
1491 mono_unload_interface_ids (MonoBitSet *bitset)
1493 mono_loader_lock ();
1494 mono_bitset_sub (global_interface_bitset, bitset);
1495 mono_loader_unlock ();
1499 * mono_get_unique_iid:
1502 * Assign a unique integer ID to the interface represented by @class.
1503 * The ID will positive and as small as possible.
1504 * LOCKING: this is supposed to be called with the loader lock held.
1505 * Returns: the new ID.
1508 mono_get_unique_iid (MonoClass *class)
1512 g_assert (MONO_CLASS_IS_INTERFACE (class));
1514 if (!global_interface_bitset) {
1515 global_interface_bitset = mono_bitset_new (128, 0);
1518 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
1520 int old_size = mono_bitset_size (global_interface_bitset);
1521 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
1522 mono_bitset_free (global_interface_bitset);
1523 global_interface_bitset = new_set;
1526 mono_bitset_set (global_interface_bitset, iid);
1527 /* set the bit also in the per-image set */
1528 if (class->image->interface_bitset) {
1529 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
1530 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
1531 mono_bitset_free (class->image->interface_bitset);
1532 class->image->interface_bitset = new_set;
1535 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
1537 mono_bitset_set (class->image->interface_bitset, iid);
1539 if (mono_print_vtable) {
1541 char *type_name = mono_type_full_name (&class->byval_arg);
1542 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
1543 generic_id = class->generic_class->context.class_inst->id;
1544 g_assert (generic_id != 0);
1548 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
1552 g_assert (iid <= 65535);
1557 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res)
1562 for (i = 0; i < klass->interface_count; i++) {
1563 ic = klass->interfaces [i];
1566 *res = g_ptr_array_new ();
1567 g_ptr_array_add (*res, ic);
1568 mono_class_init (ic);
1570 collect_implemented_interfaces_aux (ic, res);
1575 mono_class_get_implemented_interfaces (MonoClass *klass)
1577 GPtrArray *res = NULL;
1579 collect_implemented_interfaces_aux (klass, &res);
1583 typedef struct _IOffsetInfo IOffsetInfo;
1584 struct _IOffsetInfo {
1588 int data [MONO_ZERO_LEN_ARRAY];
1591 static IOffsetInfo *cached_offset_info = NULL;
1592 static int next_offset_info_size = 128;
1595 cache_interface_offsets (int max_iid, int *data)
1597 IOffsetInfo *cached_info;
1600 for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
1601 cached = cached_info->data;
1602 while (cached < cached_info->data + cached_info->size && *cached) {
1603 if (*cached == max_iid) {
1604 int i, matched = TRUE;
1606 for (i = 0; i < max_iid; ++i) {
1607 if (cached [i] != data [i]) {
1616 cached += *cached + 1;
1620 /* find a free slot */
1621 for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
1622 if (cached_info->size - cached_info->next_free >= max_iid + 1) {
1623 cached = &cached_info->data [cached_info->next_free];
1624 *cached++ = max_iid;
1625 memcpy (cached, data, max_iid * sizeof (int));
1626 cached_info->next_free += max_iid + 1;
1630 /* allocate a new chunk */
1631 if (max_iid + 1 < next_offset_info_size) {
1632 new_size = next_offset_info_size;
1633 if (next_offset_info_size < 4096)
1634 next_offset_info_size += next_offset_info_size >> 2;
1636 new_size = max_iid + 1;
1638 cached_info = g_malloc0 (sizeof (IOffsetInfo) + sizeof (int) * new_size);
1639 cached_info->size = new_size;
1640 /*g_print ("allocated %d offset entries at %p (total: %d)\n", new_size, cached_info->data, offset_info_total_size);*/
1641 cached = &cached_info->data [0];
1642 *cached++ = max_iid;
1643 memcpy (cached, data, max_iid * sizeof (int));
1644 cached_info->next_free += max_iid + 1;
1645 cached_info->next = cached_offset_info;
1646 cached_offset_info = cached_info;
1651 compare_interface_ids (const void *p_key, const void *p_element) {
1652 const MonoClass *key = p_key;
1653 const MonoClass *element = *(MonoClass**) p_element;
1655 return (key->interface_id - element->interface_id);
1659 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
1660 MonoClass **result = bsearch (
1662 klass->interfaces_packed,
1663 klass->interface_offsets_count,
1664 sizeof (MonoClass *),
1665 compare_interface_ids);
1667 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
1674 print_implemented_interfaces (MonoClass *klass) {
1675 GPtrArray *ifaces = NULL;
1677 int ancestor_level = 0;
1679 printf ("Packed interface table for class %s has size %d\n", klass->name, klass->interface_offsets_count);
1680 for (i = 0; i < klass->interface_offsets_count; i++)
1681 printf (" [%d][UUID %d][SLOT %d] interface %s\n", i,
1682 klass->interfaces_packed [i]->interface_id,
1683 klass->interface_offsets_packed [i],
1684 klass->interfaces_packed [i]->name );
1685 printf ("Interface flags: ");
1686 for (i = 0; i <= klass->max_interface_id; i++)
1687 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
1688 printf ("(%d,T)", i);
1690 printf ("(%d,F)", i);
1692 printf ("Dump interface flags:");
1693 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
1694 printf (" %02X", klass->interface_bitmap [i]);
1696 while (klass != NULL) {
1697 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
1698 ifaces = mono_class_get_implemented_interfaces (klass);
1700 for (i = 0; i < ifaces->len; i++) {
1701 MonoClass *ic = g_ptr_array_index (ifaces, i);
1702 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
1704 g_ptr_array_free (ifaces, TRUE);
1707 klass = klass->parent;
1712 * LOCKING: this is supposed to be called with the loader lock held.
1715 setup_interface_offsets (MonoClass *class, int cur_slot)
1719 MonoClass **interfaces_full;
1720 int *interface_offsets_full;
1722 int interface_offsets_count;
1724 /* compute maximum number of slots and maximum interface id */
1726 for (k = class; k ; k = k->parent) {
1727 for (i = 0; i < k->interface_count; i++) {
1728 ic = k->interfaces [i];
1731 mono_class_init (ic);
1733 if (max_iid < ic->interface_id)
1734 max_iid = ic->interface_id;
1736 ifaces = mono_class_get_implemented_interfaces (k);
1738 for (i = 0; i < ifaces->len; ++i) {
1739 ic = g_ptr_array_index (ifaces, i);
1740 if (max_iid < ic->interface_id)
1741 max_iid = ic->interface_id;
1743 g_ptr_array_free (ifaces, TRUE);
1747 if (MONO_CLASS_IS_INTERFACE (class)) {
1748 if (max_iid < class->interface_id)
1749 max_iid = class->interface_id;
1751 class->max_interface_id = max_iid;
1752 /* compute vtable offset for interfaces */
1753 interfaces_full = g_malloc (sizeof (MonoClass*) * (max_iid + 1));
1754 interface_offsets_full = g_malloc (sizeof (int) * (max_iid + 1));
1756 for (i = 0; i <= max_iid; i++) {
1757 interfaces_full [i] = NULL;
1758 interface_offsets_full [i] = -1;
1761 ifaces = mono_class_get_implemented_interfaces (class);
1763 for (i = 0; i < ifaces->len; ++i) {
1764 ic = g_ptr_array_index (ifaces, i);
1765 interfaces_full [ic->interface_id] = ic;
1766 interface_offsets_full [ic->interface_id] = cur_slot;
1767 cur_slot += ic->method.count;
1769 g_ptr_array_free (ifaces, TRUE);
1772 for (k = class->parent; k ; k = k->parent) {
1773 ifaces = mono_class_get_implemented_interfaces (k);
1775 for (i = 0; i < ifaces->len; ++i) {
1776 ic = g_ptr_array_index (ifaces, i);
1778 if (interface_offsets_full [ic->interface_id] == -1) {
1779 int io = mono_class_interface_offset (k, ic);
1783 interfaces_full [ic->interface_id] = ic;
1784 interface_offsets_full [ic->interface_id] = io;
1787 g_ptr_array_free (ifaces, TRUE);
1791 if (MONO_CLASS_IS_INTERFACE (class)) {
1792 interfaces_full [class->interface_id] = class;
1793 interface_offsets_full [class->interface_id] = cur_slot;
1796 for (interface_offsets_count = 0, i = 0; i <= max_iid; i++) {
1797 if (interface_offsets_full [i] != -1) {
1798 interface_offsets_count ++;
1801 class->interface_offsets_count = interface_offsets_count;
1802 class->interfaces_packed = mono_mempool_alloc (class->image->mempool, sizeof (MonoClass*) * interface_offsets_count);
1803 class->interface_offsets_packed = mono_mempool_alloc (class->image->mempool, sizeof (int) * interface_offsets_count);
1804 class->interface_bitmap = mono_mempool_alloc0 (class->image->mempool, (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0));
1805 for (interface_offsets_count = 0, i = 0; i <= max_iid; i++) {
1806 if (interface_offsets_full [i] != -1) {
1807 class->interface_bitmap [i >> 3] |= (1 << (i & 7));
1808 class->interfaces_packed [interface_offsets_count] = interfaces_full [i];
1809 class->interface_offsets_packed [interface_offsets_count] = interface_offsets_full [i];
1810 interface_offsets_count ++;
1814 g_free (interfaces_full);
1815 g_free (interface_offsets_full);
1817 //printf ("JUST DONE: ");
1818 //print_implemented_interfaces (class);
1824 * Setup interface offsets for interfaces. Used by Ref.Emit.
1827 mono_class_setup_interface_offsets (MonoClass *class)
1829 mono_loader_lock ();
1831 setup_interface_offsets (class, 0);
1833 mono_loader_unlock ();
1837 mono_class_setup_vtable (MonoClass *class)
1839 MonoMethod **overrides;
1840 MonoGenericContext *context;
1848 mono_class_setup_methods (class);
1850 if (MONO_CLASS_IS_INTERFACE (class))
1853 mono_loader_lock ();
1855 if (class->vtable) {
1856 mono_loader_unlock ();
1860 mono_stats.generic_vtable_count ++;
1862 if (class->generic_class) {
1863 context = mono_class_get_context (class);
1864 type_token = class->generic_class->container_class->type_token;
1866 context = (MonoGenericContext *) class->generic_container;
1867 type_token = class->type_token;
1870 if (class->image->dynamic)
1871 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
1873 /* The following call fails if there are missing methods in the type */
1874 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
1878 mono_class_setup_vtable_general (class, overrides, onum);
1882 mono_loader_unlock ();
1888 check_core_clr_override_method (MonoClass *class, MonoMethod *override, MonoMethod *base)
1890 MonoSecurityCoreCLRLevel override_level = mono_security_core_clr_method_level (override, FALSE);
1891 MonoSecurityCoreCLRLevel base_level = mono_security_core_clr_method_level (base, FALSE);
1893 if (override_level != base_level && base_level == MONO_SECURITY_CORE_CLR_CRITICAL) {
1894 class->exception_type = MONO_EXCEPTION_TYPE_LOAD;
1895 class->exception_data = NULL;
1900 * LOCKING: this is supposed to be called with the loader lock held.
1903 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum)
1906 MonoMethod **vtable;
1907 int i, max_vtsize = 0, max_iid, cur_slot = 0;
1908 GPtrArray *ifaces, *pifaces = NULL;
1909 GHashTable *override_map = NULL;
1910 gboolean security_enabled = mono_is_security_manager_active ();
1915 ifaces = mono_class_get_implemented_interfaces (class);
1917 for (i = 0; i < ifaces->len; i++) {
1918 MonoClass *ic = g_ptr_array_index (ifaces, i);
1919 max_vtsize += ic->method.count;
1921 g_ptr_array_free (ifaces, TRUE);
1924 if (class->parent) {
1925 mono_class_init (class->parent);
1926 mono_class_setup_vtable (class->parent);
1927 max_vtsize += class->parent->vtable_size;
1928 cur_slot = class->parent->vtable_size;
1931 max_vtsize += class->method.count;
1933 vtable = alloca (sizeof (gpointer) * max_vtsize);
1934 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
1936 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
1938 cur_slot = setup_interface_offsets (class, cur_slot);
1939 max_iid = class->max_interface_id;
1941 if (class->parent && class->parent->vtable_size)
1942 memcpy (vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size);
1944 /* override interface methods */
1945 for (i = 0; i < onum; i++) {
1946 MonoMethod *decl = overrides [i*2];
1947 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
1949 mono_class_setup_methods (decl->klass);
1950 g_assert (decl->slot != -1);
1951 dslot = decl->slot + mono_class_interface_offset (class, decl->klass);
1952 vtable [dslot] = overrides [i*2 + 1];
1953 vtable [dslot]->slot = dslot;
1955 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
1957 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
1959 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1960 check_core_clr_override_method (class, vtable [dslot], decl);
1964 for (k = class; k ; k = k->parent) {
1967 ifaces = mono_class_get_implemented_interfaces (k);
1969 nifaces = ifaces->len;
1970 if (k->generic_class) {
1971 pifaces = mono_class_get_implemented_interfaces (
1972 k->generic_class->container_class);
1973 g_assert (pifaces && (pifaces->len == nifaces));
1976 for (i = 0; i < nifaces; i++) {
1977 MonoClass *pic = NULL;
1980 ic = g_ptr_array_index (ifaces, i);
1982 pic = g_ptr_array_index (pifaces, i);
1983 g_assert (ic->interface_id <= k->max_interface_id);
1984 io = mono_class_interface_offset (k, ic);
1987 g_assert (io <= max_vtsize);
1990 mono_class_setup_methods (ic);
1991 for (l = 0; l < ic->method.count; l++) {
1992 MonoMethod *im = ic->methods [l];
1994 if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1997 for (j = 0; j < class->method.count; ++j) {
1998 MonoMethod *cm = class->methods [j];
1999 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
2000 !((cm->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
2001 !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
2003 if (!strcmp(cm->name, im->name) &&
2004 mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
2006 /* CAS - SecurityAction.InheritanceDemand on interface */
2007 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
2008 mono_secman_inheritancedemand_method (cm, im);
2011 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2012 check_core_clr_override_method (class, cm, im);
2014 g_assert (io + l <= max_vtsize);
2015 vtable [io + l] = cm;
2020 /* already implemented */
2021 if (io >= k->vtable_size)
2025 // Override methods with the same fully qualified name
2026 for (l = 0; l < ic->method.count; l++) {
2027 MonoMethod *im = ic->methods [l];
2028 char *qname, *fqname, *cname, *the_cname;
2031 if (vtable [io + l])
2035 the_cname = mono_type_get_name_full (&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
2039 cname = (char*)ic->name;
2042 qname = g_strconcat (cname, ".", im->name, NULL);
2043 if (ic->name_space && ic->name_space [0])
2044 fqname = g_strconcat (ic->name_space, ".", cname, ".", im->name, NULL);
2048 for (k1 = class; k1; k1 = k1->parent) {
2049 for (j = 0; j < k1->method.count; ++j) {
2050 MonoMethod *cm = k1->methods [j];
2052 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
2055 if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
2056 mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im)) &&
2057 ((vtable [io + l] == NULL) || mono_class_is_subclass_of (cm->klass, vtable [io + l]->klass, FALSE))) {
2059 /* CAS - SecurityAction.InheritanceDemand on interface */
2060 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
2061 mono_secman_inheritancedemand_method (cm, im);
2064 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2065 check_core_clr_override_method (class, cm, im);
2067 g_assert (io + l <= max_vtsize);
2068 vtable [io + l] = cm;
2078 // Override methods with the same name
2079 for (l = 0; l < ic->method.count; l++) {
2080 MonoMethod *im = ic->methods [l];
2083 g_assert (io + l <= max_vtsize);
2085 if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
2088 for (k1 = class; k1; k1 = k1->parent) {
2089 for (j = 0; j < k1->method.count; ++j) {
2090 MonoMethod *cm = k1->methods [j];
2092 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
2093 !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
2096 if (!strcmp(cm->name, im->name) &&
2097 mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
2099 /* CAS - SecurityAction.InheritanceDemand on interface */
2100 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
2101 mono_secman_inheritancedemand_method (cm, im);
2104 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2105 check_core_clr_override_method (class, cm, im);
2107 g_assert (io + l <= max_vtsize);
2108 vtable [io + l] = cm;
2113 g_assert (io + l <= max_vtsize);
2114 if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
2119 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
2120 for (l = 0; l < ic->method.count; l++) {
2122 MonoMethod *im = ic->methods [l];
2123 if (im->flags & METHOD_ATTRIBUTE_STATIC)
2125 g_assert (io + l <= max_vtsize);
2128 * If one of our parents already implements this interface
2129 * we can inherit the implementation.
2131 if (!(vtable [io + l])) {
2132 MonoClass *parent = class->parent;
2134 for (; parent; parent = parent->parent) {
2135 if (MONO_CLASS_IMPLEMENTS_INTERFACE (parent, ic->interface_id) &&
2137 vtable [io + l] = parent->vtable [mono_class_interface_offset (parent, ic) + l];
2142 if (!(vtable [io + l])) {
2143 for (j = 0; j < onum; ++j) {
2144 g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name,
2145 overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
2147 msig = mono_signature_get_desc (mono_method_signature (im), FALSE);
2148 printf ("no implementation for interface method %s::%s(%s) in class %s.%s\n",
2149 mono_type_get_name (&ic->byval_arg), im->name, msig, class->name_space, class->name);
2151 for (j = 0; j < class->method.count; ++j) {
2152 MonoMethod *cm = class->methods [j];
2153 msig = mono_signature_get_desc (mono_method_signature (cm), TRUE);
2155 printf ("METHOD %s(%s)\n", cm->name, msig);
2159 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2162 g_ptr_array_free (ifaces, TRUE);
2164 g_hash_table_destroy (override_map);
2171 for (l = 0; l < ic->method.count; l++) {
2172 MonoMethod *im = vtable [io + l];
2175 g_assert (io + l <= max_vtsize);
2177 /* FIXME: why do we need this ? */
2179 /* g_assert_not_reached (); */
2185 g_ptr_array_free (ifaces, TRUE);
2188 for (i = 0; i < class->method.count; ++i) {
2191 cm = class->methods [i];
2194 * Non-virtual method have no place in the vtable.
2195 * This also catches static methods (since they are not virtual).
2197 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
2201 * If the method is REUSE_SLOT, we must check in the
2202 * base class for a method to override.
2204 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
2206 for (k = class->parent; k ; k = k->parent) {
2208 for (j = 0; j < k->method.count; ++j) {
2209 MonoMethod *m1 = k->methods [j];
2210 MonoMethodSignature *cmsig, *m1sig;
2212 if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
2215 cmsig = mono_method_signature (cm);
2216 m1sig = mono_method_signature (m1);
2218 if (!cmsig || !m1sig) {
2219 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2223 if (!strcmp(cm->name, m1->name) &&
2224 mono_metadata_signature_equal (cmsig, m1sig)) {
2226 /* CAS - SecurityAction.InheritanceDemand */
2227 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
2228 mono_secman_inheritancedemand_method (cm, m1);
2231 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2232 check_core_clr_override_method (class, cm, m1);
2234 slot = k->methods [j]->slot;
2235 g_assert (cm->slot < max_vtsize);
2237 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
2238 g_hash_table_insert (override_map, m1, cm);
2250 cm->slot = cur_slot++;
2252 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
2253 vtable [cm->slot] = cm;
2256 /* override non interface methods */
2257 for (i = 0; i < onum; i++) {
2258 MonoMethod *decl = overrides [i*2];
2259 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
2260 g_assert (decl->slot != -1);
2261 vtable [decl->slot] = overrides [i*2 + 1];
2262 overrides [i * 2 + 1]->slot = decl->slot;
2264 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
2265 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
2267 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2268 check_core_clr_override_method (class, vtable [decl->slot], decl);
2273 * If a method occupies more than one place in the vtable, and it is
2274 * overriden, then change the other occurances too.
2277 for (i = 0; i < max_vtsize; ++i)
2279 MonoMethod *cm = g_hash_table_lookup (override_map, vtable [i]);
2284 g_hash_table_destroy (override_map);
2287 if (class->generic_class) {
2288 MonoClass *gklass = class->generic_class->container_class;
2290 mono_class_init (gklass);
2292 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
2294 class->vtable_size = cur_slot;
2296 /* Try to share the vtable with our parent. */
2297 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
2298 class->vtable = class->parent->vtable;
2300 class->vtable = mono_mempool_alloc0 (class->image->mempool, sizeof (gpointer) * class->vtable_size);
2301 memcpy (class->vtable, vtable, sizeof (gpointer) * class->vtable_size);
2304 if (mono_print_vtable) {
2307 print_implemented_interfaces (class);
2309 for (i = 0; i <= max_iid; i++)
2310 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
2313 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
2314 class->vtable_size, icount);
2316 for (i = 0; i < class->vtable_size; ++i) {
2321 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
2322 mono_method_full_name (cm, TRUE));
2328 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
2329 class->name, max_iid);
2331 for (i = 0; i < class->interface_count; i++) {
2332 ic = class->interfaces [i];
2333 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
2334 mono_class_interface_offset (class, ic),
2335 ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
2338 for (k = class->parent; k ; k = k->parent) {
2339 for (i = 0; i < k->interface_count; i++) {
2340 ic = k->interfaces [i];
2341 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
2342 mono_class_interface_offset (class, ic),
2343 ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
2350 static MonoMethod *default_ghc = NULL;
2351 static MonoMethod *default_finalize = NULL;
2352 static int finalize_slot = -1;
2353 static int ghc_slot = -1;
2356 initialize_object_slots (MonoClass *class)
2361 if (class == mono_defaults.object_class) {
2362 mono_class_setup_vtable (class);
2363 for (i = 0; i < class->vtable_size; ++i) {
2364 MonoMethod *cm = class->vtable [i];
2366 if (!strcmp (cm->name, "GetHashCode"))
2368 else if (!strcmp (cm->name, "Finalize"))
2372 g_assert (ghc_slot > 0);
2373 default_ghc = class->vtable [ghc_slot];
2375 g_assert (finalize_slot > 0);
2376 default_finalize = class->vtable [finalize_slot];
2381 g_list_prepend_mempool (GList* l, MonoMemPool* mp, gpointer datum)
2383 GList* n = mono_mempool_alloc (mp, sizeof (GList));
2391 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, int pos)
2393 MonoGenericContext tmp_context;
2396 tmp_context.class_inst = NULL;
2397 tmp_context.method_inst = iface->generic_class->context.class_inst;
2399 for (i = 0; i < class->parent->method.count; i++) {
2400 MonoMethod *m = class->parent->methods [i];
2401 MonoMethod *inflated;
2402 const char *mname, *iname;
2405 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
2406 iname = "System.Collections.Generic.ICollection`1.";
2407 mname = m->name + 27;
2408 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
2409 iname = "System.Collections.Generic.IEnumerable`1.";
2410 mname = m->name + 27;
2411 } else if (!strncmp (m->name, "InternalArray__", 15)) {
2412 iname = "System.Collections.Generic.IList`1.";
2413 mname = m->name + 15;
2418 name = mono_mempool_alloc (class->image->mempool, strlen (iname) + strlen (mname) + 1);
2419 strcpy (name, iname);
2420 strcpy (name + strlen (iname), mname);
2422 inflated = mono_class_inflate_generic_method (m, &tmp_context);
2423 class->methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, name, inflated);
2428 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2432 method = (MonoMethod *) mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethodPInvoke));
2433 method->klass = class;
2434 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2435 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2436 method->signature = sig;
2437 method->name = name;
2440 if (name [0] == '.') {
2441 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2443 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2449 concat_two_strings_with_zero (MonoMemPool *pool, const char *s1, const char *s2)
2451 int len = strlen (s1) + strlen (s2) + 2;
2452 char *s = mono_mempool_alloc (pool, len);
2455 result = g_snprintf (s, len, "%s%c%s", s1, '\0', s2);
2456 g_assert (result == len - 1);
2462 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
2464 class->exception_type = error->exception_type;
2466 switch (error->exception_type) {
2467 case MONO_EXCEPTION_TYPE_LOAD:
2468 class->exception_data = concat_two_strings_with_zero (class->image->mempool, error->class_name, error->assembly_name);
2471 case MONO_EXCEPTION_MISSING_METHOD:
2472 class->exception_data = concat_two_strings_with_zero (class->image->mempool, error->class_name, error->member_name);
2475 case MONO_EXCEPTION_MISSING_FIELD: {
2476 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
2477 const char *class_name;
2480 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
2482 class_name = error->klass->name;
2484 class->exception_data = concat_two_strings_with_zero (class->image->mempool, class_name, error->member_name);
2487 g_free ((void*)class_name);
2491 case MONO_EXCEPTION_FILE_NOT_FOUND: {
2494 if (error->ref_only)
2495 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.";
2497 msg = "Could not load file or assembly '%s' or one of its dependencies.";
2499 class->exception_data = concat_two_strings_with_zero (class->image->mempool, msg, error->assembly_name);
2504 g_assert_not_reached ();
2509 check_core_clr_inheritance (MonoClass *class)
2511 MonoSecurityCoreCLRLevel class_level, parent_level;
2512 MonoClass *parent = class->parent;
2517 class_level = mono_security_core_clr_class_level (class);
2518 parent_level = mono_security_core_clr_class_level (parent);
2520 if (class_level < parent_level) {
2521 class->exception_type = MONO_EXCEPTION_TYPE_LOAD;
2522 class->exception_data = NULL;
2528 * @class: the class to initialize
2530 * compute the instance_size, class_size and other infos that cannot be
2531 * computed at mono_class_get() time. Also compute a generic vtable and
2532 * the method slot numbers. We use this infos later to create a domain
2535 * Returns TRUE on success or FALSE if there was a problem in loading
2536 * the type (incorrect assemblies, missing assemblies, methods, etc).
2539 mono_class_init (MonoClass *class)
2542 MonoCachedClassInfo cached_info;
2543 gboolean has_cached_info;
2544 int class_init_ok = TRUE;
2549 return class->exception_type == MONO_EXCEPTION_NONE;
2551 /*g_print ("Init class %s\n", class->name);*/
2553 /* We do everything inside the lock to prevent races */
2554 mono_loader_lock ();
2556 if (class->inited) {
2557 mono_loader_unlock ();
2558 /* Somebody might have gotten in before us */
2559 return class->exception_type == MONO_EXCEPTION_NONE;
2562 if (class->init_pending) {
2563 mono_loader_unlock ();
2564 /* this indicates a cyclic dependency */
2565 g_error ("pending init %s.%s\n", class->name_space, class->name);
2568 class->init_pending = 1;
2570 /* CAS - SecurityAction.InheritanceDemand */
2571 if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
2572 mono_secman_inheritancedemand_class (class, class->parent);
2575 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2576 check_core_clr_inheritance (class);
2578 if (mono_debugger_start_class_init_func)
2579 mono_debugger_start_class_init_func (class);
2581 mono_stats.initialized_class_count++;
2583 if (class->generic_class && !class->generic_class->is_dynamic) {
2584 MonoClass *gklass = class->generic_class->container_class;
2586 mono_stats.generic_class_count++;
2588 class->method = gklass->method;
2589 class->field = gklass->field;
2591 mono_class_init (gklass);
2592 mono_class_setup_methods (gklass);
2593 mono_class_setup_properties (gklass);
2595 if (MONO_CLASS_IS_INTERFACE (class))
2596 class->interface_id = mono_get_unique_iid (class);
2598 g_assert (class->method.count == gklass->method.count);
2599 class->methods = g_new0 (MonoMethod *, class->method.count);
2601 for (i = 0; i < class->method.count; i++) {
2602 class->methods [i] = mono_class_inflate_generic_method_full (
2603 gklass->methods [i], class, mono_class_get_context (class));
2606 class->property = gklass->property;
2607 class->properties = g_new0 (MonoProperty, class->property.count);
2609 for (i = 0; i < class->property.count; i++) {
2610 MonoProperty *prop = &class->properties [i];
2612 *prop = gklass->properties [i];
2615 prop->get = mono_class_inflate_generic_method_full (
2616 prop->get, class, mono_class_get_context (class));
2618 prop->set = mono_class_inflate_generic_method_full (
2619 prop->set, class, mono_class_get_context (class));
2621 prop->parent = class;
2624 g_assert (class->interface_count == gklass->interface_count);
2627 if (class->parent && !class->parent->inited)
2628 mono_class_init (class->parent);
2630 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
2632 if (!class->generic_class && !class->image->dynamic && (!has_cached_info || (has_cached_info && cached_info.has_nested_classes))) {
2633 i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
2636 guint32 cols [MONO_NESTED_CLASS_SIZE];
2637 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
2638 nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
2639 class->nested_classes = g_list_prepend_mempool (class->nested_classes, class->image->mempool, nclass);
2641 i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
2646 * Computes the size used by the fields, and their locations
2648 if (has_cached_info) {
2649 class->instance_size = cached_info.instance_size;
2650 class->sizes.class_size = cached_info.class_size;
2651 class->packing_size = cached_info.packing_size;
2652 class->min_align = cached_info.min_align;
2653 class->blittable = cached_info.blittable;
2654 class->has_references = cached_info.has_references;
2655 class->has_static_refs = cached_info.has_static_refs;
2656 class->no_special_static_fields = cached_info.no_special_static_fields;
2659 if (!class->size_inited){
2660 mono_class_setup_fields (class);
2661 if (class->exception_type || mono_loader_get_last_error ()){
2662 class_init_ok = FALSE;
2668 /* initialize method pointers */
2670 MonoMethod *amethod;
2671 MonoMethodSignature *sig;
2672 int count_generic = 0, first_generic = 0;
2675 class->method.count = 3 + (class->rank > 1? 2: 1);
2677 if (class->interface_count) {
2678 for (i = 0; i < class->parent->method.count; i++) {
2679 MonoMethod *m = class->parent->methods [i];
2680 if (!strncmp (m->name, "InternalArray__", 15))
2683 first_generic = class->method.count;
2684 class->method.count += class->interface_count * count_generic;
2687 sig = mono_metadata_signature_alloc (class->image, class->rank);
2688 sig->ret = &mono_defaults.void_class->byval_arg;
2689 sig->pinvoke = TRUE;
2690 sig->hasthis = TRUE;
2691 for (i = 0; i < class->rank; ++i)
2692 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2694 amethod = create_array_method (class, ".ctor", sig);
2695 class->methods = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
2696 class->methods [method_num++] = amethod;
2697 if (class->rank > 1) {
2698 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2699 sig->ret = &mono_defaults.void_class->byval_arg;
2700 sig->pinvoke = TRUE;
2701 sig->hasthis = TRUE;
2702 for (i = 0; i < class->rank * 2; ++i)
2703 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2705 amethod = create_array_method (class, ".ctor", sig);
2706 class->methods [method_num++] = amethod;
2708 /* element Get (idx11, [idx2, ...]) */
2709 sig = mono_metadata_signature_alloc (class->image, class->rank);
2710 sig->ret = &class->element_class->byval_arg;
2711 sig->pinvoke = TRUE;
2712 sig->hasthis = TRUE;
2713 for (i = 0; i < class->rank; ++i)
2714 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2715 amethod = create_array_method (class, "Get", sig);
2716 class->methods [method_num++] = amethod;
2717 /* element& Address (idx11, [idx2, ...]) */
2718 sig = mono_metadata_signature_alloc (class->image, class->rank);
2719 sig->ret = &class->element_class->this_arg;
2720 sig->pinvoke = TRUE;
2721 sig->hasthis = TRUE;
2722 for (i = 0; i < class->rank; ++i)
2723 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2724 amethod = create_array_method (class, "Address", sig);
2725 class->methods [method_num++] = amethod;
2726 /* void Set (idx11, [idx2, ...], element) */
2727 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2728 sig->ret = &mono_defaults.void_class->byval_arg;
2729 sig->pinvoke = TRUE;
2730 sig->hasthis = TRUE;
2731 for (i = 0; i < class->rank; ++i)
2732 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2733 sig->params [i] = &class->element_class->byval_arg;
2734 amethod = create_array_method (class, "Set", sig);
2735 class->methods [method_num++] = amethod;
2737 for (i = 0; i < class->interface_count; i++)
2738 setup_generic_array_ifaces (class, class->interfaces [i], first_generic + i * count_generic);
2741 mono_class_setup_supertypes (class);
2744 initialize_object_slots (class);
2747 * If possible, avoid the creation of the generic vtable by requesting
2748 * cached info from the runtime.
2750 if (has_cached_info) {
2751 guint32 cur_slot = 0;
2753 class->vtable_size = cached_info.vtable_size;
2754 class->has_finalize = cached_info.has_finalize;
2755 class->ghcimpl = cached_info.ghcimpl;
2756 class->has_cctor = cached_info.has_cctor;
2758 if (class->parent) {
2759 mono_class_init (class->parent);
2760 cur_slot = class->parent->vtable_size;
2763 setup_interface_offsets (class, cur_slot);
2766 mono_class_setup_vtable (class);
2768 if (class->exception_type || mono_loader_get_last_error ()){
2769 class_init_ok = FALSE;
2774 if (class->parent) {
2775 MonoMethod *cmethod = class->vtable [ghc_slot];
2776 if (cmethod->is_inflated)
2777 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
2778 if (cmethod == default_ghc) {
2783 /* Object::Finalize should have empty implemenatation */
2784 class->has_finalize = 0;
2785 if (class->parent) {
2786 MonoMethod *cmethod = class->vtable [finalize_slot];
2787 if (cmethod->is_inflated)
2788 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
2789 if (cmethod != default_finalize) {
2790 class->has_finalize = 1;
2794 for (i = 0; i < class->method.count; ++i) {
2795 MonoMethod *method = class->methods [i];
2796 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
2797 (strcmp (".cctor", method->name) == 0)) {
2798 class->has_cctor = 1;
2804 if (MONO_CLASS_IS_INTERFACE (class)) {
2806 * knowledge of interface offsets is needed for the castclass/isinst code, so
2807 * we have to setup them for interfaces, too.
2809 setup_interface_offsets (class, 0);
2814 class->init_pending = 0;
2816 if (mono_loader_get_last_error ()) {
2817 if (class->exception_type == MONO_EXCEPTION_NONE)
2818 set_failure_from_loader_error (class, mono_loader_get_last_error ());
2820 mono_loader_clear_error ();
2823 mono_loader_unlock ();
2825 if (mono_debugger_class_init_func)
2826 mono_debugger_class_init_func (class);
2828 return class_init_ok;
2832 * LOCKING: this assumes the loader lock is held
2835 mono_class_setup_mono_type (MonoClass *class)
2837 const char *name = class->name;
2838 const char *nspace = class->name_space;
2840 class->this_arg.byref = 1;
2841 class->this_arg.data.klass = class;
2842 class->this_arg.type = MONO_TYPE_CLASS;
2843 class->byval_arg.data.klass = class;
2844 class->byval_arg.type = MONO_TYPE_CLASS;
2846 if (!strcmp (nspace, "System")) {
2847 if (!strcmp (name, "ValueType")) {
2849 * do not set the valuetype bit for System.ValueType.
2850 * class->valuetype = 1;
2852 class->blittable = TRUE;
2853 } else if (!strcmp (name, "Enum")) {
2855 * do not set the valuetype bit for System.Enum.
2856 * class->valuetype = 1;
2858 class->valuetype = 0;
2859 class->enumtype = 0;
2860 } else if (!strcmp (name, "Object")) {
2861 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
2862 } else if (!strcmp (name, "String")) {
2863 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
2864 } else if (!strcmp (name, "TypedReference")) {
2865 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
2869 if (class->valuetype) {
2870 int t = MONO_TYPE_VALUETYPE;
2871 if (!strcmp (nspace, "System")) {
2874 if (!strcmp (name, "Boolean")) {
2875 t = MONO_TYPE_BOOLEAN;
2876 } else if (!strcmp(name, "Byte")) {
2878 class->blittable = TRUE;
2882 if (!strcmp (name, "Char")) {
2887 if (!strcmp (name, "Double")) {
2889 class->blittable = TRUE;
2893 if (!strcmp (name, "Int32")) {
2895 class->blittable = TRUE;
2896 } else if (!strcmp(name, "Int16")) {
2898 class->blittable = TRUE;
2899 } else if (!strcmp(name, "Int64")) {
2901 class->blittable = TRUE;
2902 } else if (!strcmp(name, "IntPtr")) {
2904 class->blittable = TRUE;
2908 if (!strcmp (name, "Single")) {
2910 class->blittable = TRUE;
2911 } else if (!strcmp(name, "SByte")) {
2913 class->blittable = TRUE;
2917 if (!strcmp (name, "UInt32")) {
2919 class->blittable = TRUE;
2920 } else if (!strcmp(name, "UInt16")) {
2922 class->blittable = TRUE;
2923 } else if (!strcmp(name, "UInt64")) {
2925 class->blittable = TRUE;
2926 } else if (!strcmp(name, "UIntPtr")) {
2928 class->blittable = TRUE;
2932 if (!strcmp (name, "TypedReference")) {
2933 t = MONO_TYPE_TYPEDBYREF;
2934 class->blittable = TRUE;
2938 if (!strcmp (name, "Void")) {
2946 class->this_arg.type = class->byval_arg.type = t;
2949 if (MONO_CLASS_IS_INTERFACE (class))
2950 class->interface_id = mono_get_unique_iid (class);
2955 * LOCKING: this assumes the loader lock is held
2958 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
2960 gboolean system_namespace;
2962 system_namespace = !strcmp (class->name_space, "System");
2964 /* if root of the hierarchy */
2965 if (system_namespace && !strcmp (class->name, "Object")) {
2966 class->parent = NULL;
2967 class->instance_size = sizeof (MonoObject);
2970 if (!strcmp (class->name, "<Module>")) {
2971 class->parent = NULL;
2972 class->instance_size = 0;
2976 if (!MONO_CLASS_IS_INTERFACE (class)) {
2977 /* Imported COM Objects always derive from __ComObject. */
2978 if (MONO_CLASS_IS_IMPORT (class)) {
2979 mono_init_com_types ();
2980 if (parent == mono_defaults.object_class)
2981 parent = mono_defaults.com_object_class;
2983 class->parent = parent;
2987 g_assert_not_reached (); /* FIXME */
2989 if (parent->generic_class && !parent->name) {
2991 * If the parent is a generic instance, we may get
2992 * called before it is fully initialized, especially
2993 * before it has its name.
2998 class->marshalbyref = parent->marshalbyref;
2999 class->contextbound = parent->contextbound;
3000 class->delegate = parent->delegate;
3001 if (MONO_CLASS_IS_IMPORT (class))
3002 class->is_com_object = 1;
3004 class->is_com_object = parent->is_com_object;
3006 if (system_namespace) {
3007 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
3008 class->marshalbyref = 1;
3010 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
3011 class->contextbound = 1;
3013 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
3014 class->delegate = 1;
3017 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) &&
3018 (strcmp (class->parent->name_space, "System") == 0)))
3019 class->valuetype = 1;
3020 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
3021 class->valuetype = class->enumtype = 1;
3023 /*class->enumtype = class->parent->enumtype; */
3024 mono_class_setup_supertypes (class);
3026 class->parent = NULL;
3032 * mono_class_setup_supertypes:
3035 * Build the data structure needed to make fast type checks work.
3036 * This currently sets two fields in @class:
3037 * - idepth: distance between @class and System.Object in the type
3039 * - supertypes: array of classes: each element has a class in the hierarchy
3040 * starting from @class up to System.Object
3042 * LOCKING: this assumes the loader lock is held
3045 mono_class_setup_supertypes (MonoClass *class)
3049 if (class->supertypes)
3052 if (class->parent && !class->parent->supertypes)
3053 mono_class_setup_supertypes (class->parent);
3055 class->idepth = class->parent->idepth + 1;
3059 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
3060 class->supertypes = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClass *) * ms);
3062 if (class->parent) {
3063 class->supertypes [class->idepth - 1] = class;
3064 memcpy (class->supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
3066 class->supertypes [0] = class;
3071 * mono_class_create_from_typedef:
3072 * @image: image where the token is valid
3073 * @type_token: typedef token
3075 * Create the MonoClass* representing the specified type token.
3076 * @type_token must be a TypeDef token.
3079 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
3081 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
3082 MonoClass *class, *parent = NULL;
3083 guint32 cols [MONO_TYPEDEF_SIZE];
3084 guint32 cols_next [MONO_TYPEDEF_SIZE];
3085 guint tidx = mono_metadata_token_index (type_token);
3086 MonoGenericContext *context = NULL;
3087 const char *name, *nspace;
3089 MonoClass **interfaces;
3090 guint32 field_last, method_last;
3091 guint32 nesting_tokeen;
3093 mono_loader_lock ();
3095 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
3096 mono_loader_unlock ();
3100 g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
3102 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
3104 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
3105 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
3107 class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
3110 class->name_space = nspace;
3112 class->image = image;
3113 class->type_token = type_token;
3114 class->flags = cols [MONO_TYPEDEF_FLAGS];
3116 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
3119 * Check whether we're a generic type definition.
3121 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
3122 if (class->generic_container) {
3123 class->generic_container->owner.klass = class;
3124 context = &class->generic_container->context;
3127 if (cols [MONO_TYPEDEF_EXTENDS]) {
3128 parent = mono_class_get_full (
3129 image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
3130 if (parent == NULL){
3131 mono_internal_hash_table_remove (&image->class_cache, GUINT_TO_POINTER (type_token));
3132 mono_loader_unlock ();
3137 /* do this early so it's available for interfaces in setup_mono_type () */
3138 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token)))
3139 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen);
3141 mono_class_setup_parent (class, parent);
3143 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
3144 mono_class_setup_mono_type (class);
3146 if (!class->enumtype) {
3147 if (!mono_metadata_interfaces_from_typedef_full (
3148 image, type_token, &interfaces, &icount, context)){
3149 mono_loader_unlock ();
3153 class->interfaces = interfaces;
3154 class->interface_count = icount;
3157 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
3161 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
3165 class->cast_class = class->element_class = class;
3167 /*g_print ("Load class %s\n", name);*/
3170 * Compute the field and method lists
3172 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
3173 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
3175 if (tt->rows > tidx){
3176 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
3177 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
3178 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
3180 field_last = image->tables [MONO_TABLE_FIELD].rows;
3181 method_last = image->tables [MONO_TABLE_METHOD].rows;
3184 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
3185 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
3186 class->field.count = field_last - class->field.first;
3188 class->field.count = 0;
3190 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
3191 class->method.count = method_last - class->method.first;
3193 class->method.count = 0;
3195 /* reserve space to store vector pointer in arrays */
3196 if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
3197 class->instance_size += 2 * sizeof (gpointer);
3198 g_assert (class->field.count == 0);
3201 if (class->enumtype) {
3202 class->enum_basetype = mono_class_find_enum_basetype (class);
3203 if (!class->enum_basetype) {
3204 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
3205 mono_loader_unlock ();
3208 class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
3212 * If we're a generic type definition, load the constraints.
3213 * We must do this after the class has been constructed to make certain recursive scenarios
3216 if (class->generic_container)
3217 mono_metadata_load_generic_param_constraints (
3218 image, type_token, class->generic_container);
3220 mono_loader_unlock ();
3225 /** is klass Nullable<T>? */
3227 mono_class_is_nullable (MonoClass *klass)
3229 return klass->generic_class != NULL &&
3230 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
3234 /** if klass is T? return T */
3236 mono_class_get_nullable_param (MonoClass *klass)
3238 g_assert (mono_class_is_nullable (klass));
3239 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3243 * Create the `MonoClass' for an instantiation of a generic type.
3244 * We only do this if we actually need it.
3247 mono_generic_class_get_class (MonoGenericClass *gclass)
3249 MonoClass *klass, *gklass;
3252 mono_loader_lock ();
3253 if (gclass->cached_class) {
3254 mono_loader_unlock ();
3255 g_assert (!gclass->cached_class->generic_container);
3256 return gclass->cached_class;
3259 gclass->cached_class = g_malloc0 (sizeof (MonoClass));
3260 klass = gclass->cached_class;
3262 gklass = gclass->container_class;
3264 if (gklass->nested_in) {
3266 * FIXME: the nested type context should include everything the
3267 * nesting context should have, but it may also have additional
3268 * generic parameters...
3270 MonoType *inflated = mono_class_inflate_generic_type (
3271 &gklass->nested_in->byval_arg, mono_generic_class_get_context (gclass));
3272 klass->nested_in = mono_class_from_mono_type (inflated);
3275 klass->name = gklass->name;
3276 klass->name_space = gklass->name_space;
3277 klass->image = gklass->image;
3278 klass->flags = gklass->flags;
3279 klass->type_token = gklass->type_token;
3281 klass->generic_class = gclass;
3283 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
3284 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
3285 klass->this_arg.byref = TRUE;
3287 klass->cast_class = klass->element_class = klass;
3289 if (mono_class_is_nullable (klass))
3290 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
3292 if (gclass->is_dynamic) {
3293 klass->instance_size = gklass->instance_size;
3294 klass->sizes.class_size = gklass->sizes.class_size;
3295 klass->size_inited = 1;
3298 klass->valuetype = gklass->valuetype;
3300 mono_class_setup_supertypes (klass);
3303 klass->interface_count = gklass->interface_count;
3304 klass->interfaces = g_new0 (MonoClass *, klass->interface_count);
3305 for (i = 0; i < klass->interface_count; i++) {
3306 MonoType *it = &gklass->interfaces [i]->byval_arg;
3307 MonoType *inflated = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
3308 klass->interfaces [i] = mono_class_from_mono_type (inflated);
3312 * We're not interested in the nested classes of a generic instance.
3313 * We use the generic type definition to look for nested classes.
3315 klass->nested_classes = NULL;
3317 if (gklass->parent) {
3318 MonoType *inflated = mono_class_inflate_generic_type (
3319 &gklass->parent->byval_arg, mono_generic_class_get_context (gclass));
3321 klass->parent = mono_class_from_mono_type (inflated);
3325 mono_class_setup_parent (klass, klass->parent);
3327 if (klass->enumtype) {
3328 klass->enum_basetype = gklass->enum_basetype;
3329 klass->cast_class = gklass->cast_class;
3332 if (MONO_CLASS_IS_INTERFACE (klass))
3333 setup_interface_offsets (klass, 0);
3335 mono_loader_unlock ();
3341 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
3343 MonoClass *klass, **ptr;
3347 return param->pklass;
3349 klass = param->pklass = g_new0 (MonoClass, 1);
3351 for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
3355 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) {
3356 klass->parent = param->constraints [0];
3358 } else if (param->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
3359 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
3361 klass->parent = mono_defaults.object_class;
3363 if (count - pos > 0) {
3364 klass->interface_count = count - pos;
3365 klass->interfaces = g_new0 (MonoClass *, count - pos);
3366 for (i = pos; i < count; i++)
3367 klass->interfaces [i - pos] = param->constraints [i];
3371 klass->name = param->name;
3373 klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
3375 klass->name_space = "";
3377 if (!image && param->owner) {
3379 MonoMethod *method = param->owner->owner.method;
3380 image = (method && method->klass) ? method->klass->image : NULL;
3382 MonoClass *klass = param->owner->owner.klass;
3383 // FIXME: 'klass' should not be null
3384 // But, monodis creates GenericContainers without associating a owner to it
3385 image = klass ? klass->image : NULL;
3390 image = mono_defaults.corlib;
3392 klass->image = image;
3394 klass->inited = TRUE;
3395 klass->cast_class = klass->element_class = klass;
3396 klass->enum_basetype = &klass->element_class->byval_arg;
3397 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
3399 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
3400 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
3401 klass->this_arg.byref = TRUE;
3403 mono_class_setup_supertypes (klass);
3409 mono_ptr_class_get (MonoType *type)
3412 MonoClass *el_class;
3416 el_class = mono_class_from_mono_type (type);
3417 image = el_class->image;
3419 mono_loader_lock ();
3421 if (!image->ptr_cache)
3422 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
3424 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
3425 mono_loader_unlock ();
3428 result = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
3430 result->parent = NULL; /* no parent for PTR types */
3431 result->name_space = el_class->name_space;
3432 name = g_strdup_printf ("%s*", el_class->name);
3433 result->name = mono_mempool_strdup (image->mempool, name);
3435 result->image = el_class->image;
3436 result->inited = TRUE;
3437 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
3438 /* Can pointers get boxed? */
3439 result->instance_size = sizeof (gpointer);
3440 result->cast_class = result->element_class = el_class;
3441 result->enum_basetype = &result->element_class->byval_arg;
3442 result->blittable = TRUE;
3444 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
3445 result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
3446 result->this_arg.byref = TRUE;
3448 mono_class_setup_supertypes (result);
3450 g_hash_table_insert (image->ptr_cache, el_class, result);
3452 mono_loader_unlock ();
3458 mono_fnptr_class_get (MonoMethodSignature *sig)
3461 static GHashTable *ptr_hash = NULL;
3463 /* FIXME: These should be allocate from a mempool as well, but which one ? */
3465 mono_loader_lock ();
3468 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3470 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
3471 mono_loader_unlock ();
3474 result = g_new0 (MonoClass, 1);
3476 result->parent = NULL; /* no parent for PTR types */
3477 result->name_space = "System";
3478 result->name = "MonoFNPtrFakeClass";
3479 result->image = mono_defaults.corlib; /* need to fix... */
3480 result->inited = TRUE;
3481 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
3482 /* Can pointers get boxed? */
3483 result->instance_size = sizeof (gpointer);
3484 result->cast_class = result->element_class = result;
3485 result->blittable = TRUE;
3487 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
3488 result->this_arg.data.method = result->byval_arg.data.method = sig;
3489 result->this_arg.byref = TRUE;
3490 result->enum_basetype = &result->element_class->byval_arg;
3491 result->blittable = TRUE;
3493 mono_class_setup_supertypes (result);
3495 g_hash_table_insert (ptr_hash, sig, result);
3497 mono_loader_unlock ();
3503 mono_class_from_mono_type (MonoType *type)
3505 switch (type->type) {
3506 case MONO_TYPE_OBJECT:
3507 return type->data.klass? type->data.klass: mono_defaults.object_class;
3508 case MONO_TYPE_VOID:
3509 return type->data.klass? type->data.klass: mono_defaults.void_class;
3510 case MONO_TYPE_BOOLEAN:
3511 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
3512 case MONO_TYPE_CHAR:
3513 return type->data.klass? type->data.klass: mono_defaults.char_class;
3515 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
3517 return type->data.klass? type->data.klass: mono_defaults.byte_class;
3519 return type->data.klass? type->data.klass: mono_defaults.int16_class;
3521 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
3523 return type->data.klass? type->data.klass: mono_defaults.int32_class;
3525 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
3527 return type->data.klass? type->data.klass: mono_defaults.int_class;
3529 return type->data.klass? type->data.klass: mono_defaults.uint_class;
3531 return type->data.klass? type->data.klass: mono_defaults.int64_class;
3533 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
3535 return type->data.klass? type->data.klass: mono_defaults.single_class;
3537 return type->data.klass? type->data.klass: mono_defaults.double_class;
3538 case MONO_TYPE_STRING:
3539 return type->data.klass? type->data.klass: mono_defaults.string_class;
3540 case MONO_TYPE_TYPEDBYREF:
3541 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
3542 case MONO_TYPE_ARRAY:
3543 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
3545 return mono_ptr_class_get (type->data.type);
3546 case MONO_TYPE_FNPTR:
3547 return mono_fnptr_class_get (type->data.method);
3548 case MONO_TYPE_SZARRAY:
3549 return mono_array_class_get (type->data.klass, 1);
3550 case MONO_TYPE_CLASS:
3551 case MONO_TYPE_VALUETYPE:
3552 return type->data.klass;
3553 case MONO_TYPE_GENERICINST:
3554 return mono_generic_class_get_class (type->data.generic_class);
3556 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
3557 case MONO_TYPE_MVAR:
3558 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
3560 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
3561 g_assert_not_reached ();
3568 * mono_type_retrieve_from_typespec
3569 * @image: context where the image is created
3570 * @type_spec: typespec token
3571 * @context: the generic context used to evaluate generic instantiations in
3574 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context)
3576 MonoType *t = mono_type_create_from_typespec (image, type_spec);
3579 if (context && (context->class_inst || context->method_inst)) {
3580 MonoType *inflated = inflate_generic_type (t, context);
3588 * mono_class_create_from_typespec
3589 * @image: context where the image is created
3590 * @type_spec: typespec token
3591 * @context: the generic context used to evaluate generic instantiations in
3594 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context)
3596 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context);
3599 return mono_class_from_mono_type (t);
3603 * mono_bounded_array_class_get:
3604 * @element_class: element class
3605 * @rank: the dimension of the array class
3606 * @bounded: whenever the array has non-zero bounds
3608 * Returns: a class object describing the array with element type @element_type and
3612 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
3616 MonoClass *parent = NULL;
3617 GSList *list, *rootlist;
3620 gboolean corlib_type = FALSE;
3622 g_assert (rank <= 255);
3625 /* bounded only matters for one-dimensional arrays */
3628 image = eclass->image;
3630 mono_loader_lock ();
3632 if (!image->array_cache)
3633 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
3635 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
3636 for (; list; list = list->next) {
3638 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
3639 mono_loader_unlock ();
3645 /* for the building corlib use System.Array from it */
3646 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
3647 parent = mono_class_from_name (image, "System", "Array");
3650 parent = mono_defaults.array_class;
3651 if (!parent->inited)
3652 mono_class_init (parent);
3655 class = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass));
3657 class->image = image;
3658 class->name_space = eclass->name_space;
3659 nsize = strlen (eclass->name);
3660 name = g_malloc (nsize + 2 + rank);
3661 memcpy (name, eclass->name, nsize);
3664 memset (name + nsize + 1, ',', rank - 1);
3665 name [nsize + rank] = ']';
3666 name [nsize + rank + 1] = 0;
3667 class->name = mono_mempool_strdup (image->mempool, name);
3669 class->type_token = 0;
3670 /* all arrays are marked serializable and sealed, bug #42779 */
3671 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
3672 (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
3673 class->parent = parent;
3674 class->instance_size = mono_class_instance_size (class->parent);
3676 if (eclass->enumtype && !eclass->enum_basetype) {
3677 if (!eclass->reflection_info || eclass->wastypebuilder) {
3678 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
3679 g_assert (eclass->reflection_info && !eclass->wastypebuilder);
3681 /* element_size -1 is ok as this is not an instantitable type*/
3682 class->sizes.element_size = -1;
3684 class->sizes.element_size = mono_class_array_element_size (eclass);
3686 mono_class_setup_supertypes (class);
3688 if (mono_defaults.generic_ilist_class) {
3689 MonoClass *fclass = NULL;
3692 if (eclass->valuetype) {
3693 if (eclass == mono_defaults.int16_class)
3694 fclass = mono_defaults.uint16_class;
3695 if (eclass == mono_defaults.uint16_class)
3696 fclass = mono_defaults.int16_class;
3697 if (eclass == mono_defaults.int32_class)
3698 fclass = mono_defaults.uint32_class;
3699 if (eclass == mono_defaults.uint32_class)
3700 fclass = mono_defaults.int32_class;
3701 if (eclass == mono_defaults.int64_class)
3702 fclass = mono_defaults.uint64_class;
3703 if (eclass == mono_defaults.uint64_class)
3704 fclass = mono_defaults.int64_class;
3705 if (eclass == mono_defaults.byte_class)
3706 fclass = mono_defaults.sbyte_class;
3707 if (eclass == mono_defaults.sbyte_class)
3708 fclass = mono_defaults.byte_class;
3710 class->interface_count = fclass ? 2 : 1;
3711 } else if (MONO_CLASS_IS_INTERFACE (eclass)) {
3712 class->interface_count = 2 + eclass->interface_count;
3714 class->interface_count = eclass->idepth + eclass->interface_count;
3717 class->interfaces = mono_mempool_alloc0 (image->mempool, sizeof (MonoClass*) * class->interface_count);
3719 for (i = 0; i < class->interface_count; i++) {
3723 if (eclass->valuetype)
3724 iface = (i == 0) ? eclass : fclass;
3725 else if (MONO_CLASS_IS_INTERFACE (eclass)) {
3727 iface = mono_defaults.object_class;
3731 iface = eclass->interfaces [i - 2];
3733 if (i < eclass->idepth)
3734 iface = eclass->supertypes [i];
3736 iface = eclass->interfaces [i - eclass->idepth];
3739 args [0] = &iface->byval_arg;
3741 class->interfaces [i] = mono_class_bind_generic_parameters (
3742 mono_defaults.generic_ilist_class, 1, args, FALSE);
3746 if (eclass->generic_class)
3747 mono_class_init (eclass);
3748 if (!eclass->size_inited)
3749 mono_class_setup_fields (eclass);
3750 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
3754 if (eclass->enumtype)
3755 class->cast_class = eclass->element_class;
3757 class->cast_class = eclass;
3759 class->element_class = eclass;
3761 if ((rank > 1) || bounded) {
3762 MonoArrayType *at = mono_mempool_alloc0 (image->mempool, sizeof (MonoArrayType));
3763 class->byval_arg.type = MONO_TYPE_ARRAY;
3764 class->byval_arg.data.array = at;
3765 at->eklass = eclass;
3767 /* FIXME: complete.... */
3769 class->byval_arg.type = MONO_TYPE_SZARRAY;
3770 class->byval_arg.data.klass = eclass;
3772 class->this_arg = class->byval_arg;
3773 class->this_arg.byref = 1;
3778 class->generic_container = eclass->generic_container;
3780 list = g_slist_append (rootlist, class);
3781 g_hash_table_insert (image->array_cache, eclass, list);
3783 mono_loader_unlock ();
3789 * mono_array_class_get:
3790 * @element_class: element class
3791 * @rank: the dimension of the array class
3793 * Returns: a class object describing the array with element type @element_type and
3797 mono_array_class_get (MonoClass *eclass, guint32 rank)
3799 return mono_bounded_array_class_get (eclass, rank, FALSE);
3803 * mono_class_instance_size:
3806 * Returns: the size of an object instance
3809 mono_class_instance_size (MonoClass *klass)
3811 if (!klass->size_inited)
3812 mono_class_init (klass);
3814 return klass->instance_size;
3818 * mono_class_min_align:
3821 * Returns: minimm alignment requirements
3824 mono_class_min_align (MonoClass *klass)
3826 if (!klass->size_inited)
3827 mono_class_init (klass);
3829 return klass->min_align;
3833 * mono_class_value_size:
3836 * This function is used for value types, and return the
3837 * space and the alignment to store that kind of value object.
3839 * Returns: the size of a value of kind @klass
3842 mono_class_value_size (MonoClass *klass, guint32 *align)
3846 /* fixme: check disable, because we still have external revereces to
3847 * mscorlib and Dummy Objects
3849 /*g_assert (klass->valuetype);*/
3851 size = mono_class_instance_size (klass) - sizeof (MonoObject);
3854 *align = klass->min_align;
3860 * mono_class_data_size:
3863 * Returns: the size of the static class data
3866 mono_class_data_size (MonoClass *klass)
3869 mono_class_init (klass);
3871 /* in arrays, sizes.class_size is unioned with element_size
3872 * and arrays have no static fields
3876 return klass->sizes.class_size;
3880 * Auxiliary routine to mono_class_get_field
3882 * Takes a field index instead of a field token.
3884 static MonoClassField *
3885 mono_class_get_field_idx (MonoClass *class, int idx)
3887 mono_class_setup_fields_locking (class);
3890 if (class->image->uncompressed_metadata) {
3892 * class->field.first points to the FieldPtr table, while idx points into the
3893 * Field table, so we have to do a search.
3895 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
3898 for (i = 0; i < class->field.count; ++i)
3899 if (class->fields [i].name == name)
3900 return &class->fields [i];
3901 g_assert_not_reached ();
3903 if (class->field.count) {
3904 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
3905 return &class->fields [idx - class->field.first];
3909 class = class->parent;
3915 * mono_class_get_field:
3916 * @class: the class to lookup the field.
3917 * @field_token: the field token
3919 * Returns: A MonoClassField representing the type and offset of
3920 * the field, or a NULL value if the field does not belong to this
3924 mono_class_get_field (MonoClass *class, guint32 field_token)
3926 int idx = mono_metadata_token_index (field_token);
3928 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
3930 return mono_class_get_field_idx (class, idx - 1);
3934 * mono_class_get_field_from_name:
3935 * @klass: the class to lookup the field.
3936 * @name: the field name
3938 * Search the class @klass and it's parents for a field with the name @name.
3940 * Returns: the MonoClassField pointer of the named field or NULL
3943 mono_class_get_field_from_name (MonoClass *klass, const char *name)
3947 mono_class_setup_fields_locking (klass);
3949 for (i = 0; i < klass->field.count; ++i) {
3950 if (strcmp (name, klass->fields [i].name) == 0)
3951 return &klass->fields [i];
3953 klass = klass->parent;
3959 * mono_class_get_field_token:
3960 * @field: the field we need the token of
3962 * Get the token of a field. Note that the tokesn is only valid for the image
3963 * the field was loaded from. Don't use this function for fields in dynamic types.
3965 * Returns: the token representing the field in the image it was loaded from.
3968 mono_class_get_field_token (MonoClassField *field)
3970 MonoClass *klass = field->parent;
3973 mono_class_setup_fields_locking (klass);
3975 for (i = 0; i < klass->field.count; ++i) {
3976 if (&klass->fields [i] == field) {
3977 int idx = klass->field.first + i + 1;
3979 if (klass->image->uncompressed_metadata)
3980 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
3981 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
3984 klass = klass->parent;
3987 g_assert_not_reached ();
3992 mono_class_get_event_token (MonoEvent *event)
3994 MonoClass *klass = event->parent;
3998 for (i = 0; i < klass->event.count; ++i) {
3999 if (&klass->events [i] == event)
4000 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->event.first + i + 1);
4002 klass = klass->parent;
4005 g_assert_not_reached ();
4010 mono_class_get_property_from_name (MonoClass *klass, const char *name)
4014 gpointer iter = NULL;
4015 while ((p = mono_class_get_properties (klass, &iter))) {
4016 if (! strcmp (name, p->name))
4019 klass = klass->parent;
4025 mono_class_get_property_token (MonoProperty *prop)
4027 MonoClass *klass = prop->parent;
4031 gpointer iter = NULL;
4032 while ((p = mono_class_get_properties (klass, &iter))) {
4033 if (&klass->properties [i] == prop)
4034 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->property.first + i + 1);
4038 klass = klass->parent;
4041 g_assert_not_reached ();
4046 mono_class_name_from_token (MonoImage *image, guint32 type_token)
4048 const char *name, *nspace;
4050 return g_strdup_printf ("DynamicType 0x%08x", type_token);
4052 switch (type_token & 0xff000000){
4053 case MONO_TOKEN_TYPE_DEF: {
4054 guint32 cols [MONO_TYPEDEF_SIZE];
4055 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
4056 guint tidx = mono_metadata_token_index (type_token);
4058 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
4059 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
4060 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
4061 if (strlen (nspace) == 0)
4062 return g_strdup_printf ("%s", name);
4064 return g_strdup_printf ("%s.%s", nspace, name);
4067 case MONO_TOKEN_TYPE_REF: {
4068 guint32 cols [MONO_TYPEREF_SIZE];
4069 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
4071 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
4072 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
4073 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
4074 if (strlen (nspace) == 0)
4075 return g_strdup_printf ("%s", name);
4077 return g_strdup_printf ("%s.%s", nspace, name);
4080 case MONO_TOKEN_TYPE_SPEC:
4081 return g_strdup_printf ("Typespec 0x%08x", type_token);
4083 g_assert_not_reached ();
4090 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
4093 return g_strdup_printf ("DynamicAssembly %s", image->name);
4095 switch (type_token & 0xff000000){
4096 case MONO_TOKEN_TYPE_DEF:
4097 return mono_stringify_assembly_name (&image->assembly->aname);
4099 case MONO_TOKEN_TYPE_REF: {
4100 MonoAssemblyName aname;
4101 guint32 cols [MONO_TYPEREF_SIZE];
4102 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
4105 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
4107 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
4108 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
4109 case MONO_RESOLTION_SCOPE_MODULE:
4111 return g_strdup ("");
4112 case MONO_RESOLTION_SCOPE_MODULEREF:
4114 return g_strdup ("");
4115 case MONO_RESOLTION_SCOPE_TYPEREF:
4117 return g_strdup ("");
4118 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
4119 mono_assembly_get_assemblyref (image, idx - 1, &aname);
4120 return mono_stringify_assembly_name (&aname);
4122 g_assert_not_reached ();
4126 case MONO_TOKEN_TYPE_SPEC:
4128 return g_strdup ("");
4130 g_assert_not_reached ();
4137 * mono_class_get_full:
4138 * @image: the image where the class resides
4139 * @type_token: the token for the class
4140 * @context: the generic context used to evaluate generic instantiations in
4142 * Returns: the MonoClass that represents @type_token in @image
4145 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
4147 MonoClass *class = NULL;
4150 return mono_lookup_dynamic_token (image, type_token);
4152 switch (type_token & 0xff000000){
4153 case MONO_TOKEN_TYPE_DEF:
4154 class = mono_class_create_from_typedef (image, type_token);
4156 case MONO_TOKEN_TYPE_REF:
4157 class = mono_class_from_typeref (image, type_token);
4159 case MONO_TOKEN_TYPE_SPEC:
4160 class = mono_class_create_from_typespec (image, type_token, context);
4163 g_warning ("unknown token type %x", type_token & 0xff000000);
4164 g_assert_not_reached ();
4168 char *name = mono_class_name_from_token (image, type_token);
4169 char *assembly = mono_assembly_name_from_token (image, type_token);
4170 mono_loader_set_error_type_load (name, assembly);
4178 * mono_type_get_full:
4179 * @image: the image where the type resides
4180 * @type_token: the token for the type
4181 * @context: the generic context used to evaluate generic instantiations in
4183 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
4185 * Returns: the MonoType that represents @type_token in @image
4188 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
4190 MonoType *type = NULL;
4192 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
4194 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token));
4196 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
4197 MonoClass *class = mono_class_get_full (image, type_token, context);
4198 return class ? mono_class_get_type (class) : NULL;
4201 type = mono_type_retrieve_from_typespec (image, type_token, context);
4204 char *name = mono_class_name_from_token (image, type_token);
4205 char *assembly = mono_assembly_name_from_token (image, type_token);
4206 mono_loader_set_error_type_load (name, assembly);
4214 mono_class_get (MonoImage *image, guint32 type_token)
4216 return mono_class_get_full (image, type_token, NULL);
4220 * mono_image_init_name_cache:
4222 * Initializes the class name cache stored in image->name_cache.
4224 * LOCKING: Acquires the loader lock.
4227 mono_image_init_name_cache (MonoImage *image)
4229 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
4230 guint32 cols [MONO_TYPEDEF_SIZE];
4233 guint32 i, visib, nspace_index;
4234 GHashTable *name_cache2, *nspace_table;
4236 mono_loader_lock ();
4238 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
4240 if (image->dynamic) {
4241 mono_loader_unlock ();
4245 /* Temporary hash table to avoid lookups in the nspace_table */
4246 name_cache2 = g_hash_table_new (NULL, NULL);
4248 for (i = 1; i <= t->rows; ++i) {
4249 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
4250 /* nested types are accessed from the nesting name */
4251 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4252 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
4254 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
4255 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
4257 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
4258 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
4259 if (!nspace_table) {
4260 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
4261 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
4262 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
4265 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
4268 /* Load type names from EXPORTEDTYPES table */
4270 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
4271 guint32 cols [MONO_EXP_TYPE_SIZE];
4274 for (i = 0; i < t->rows; ++i) {
4275 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
4276 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
4277 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
4279 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
4280 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
4281 if (!nspace_table) {
4282 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
4283 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
4284 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
4287 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
4291 g_hash_table_destroy (name_cache2);
4293 mono_loader_unlock ();
4297 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
4298 const char *name, guint32 index)
4300 GHashTable *nspace_table;
4301 GHashTable *name_cache;
4303 mono_loader_lock ();
4305 if (!image->name_cache)
4306 mono_image_init_name_cache (image);
4308 name_cache = image->name_cache;
4309 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
4310 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
4311 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
4313 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
4315 mono_loader_unlock ();
4324 find_nocase (gpointer key, gpointer value, gpointer user_data)
4326 char *name = (char*)key;
4327 FindUserData *data = (FindUserData*)user_data;
4329 if (!data->value && (g_strcasecmp (name, (char*)data->key) == 0))
4330 data->value = value;
4334 * mono_class_from_name_case:
4335 * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
4336 * @name_space: the type namespace
4337 * @name: the type short name.
4339 * Obtains a MonoClass with a given namespace and a given name which
4340 * is located in the given MonoImage. The namespace and name
4341 * lookups are case insensitive.
4344 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
4346 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
4347 guint32 cols [MONO_TYPEDEF_SIZE];
4352 if (image->dynamic) {
4354 FindUserData user_data;
4356 mono_loader_lock ();
4358 if (!image->name_cache)
4359 mono_image_init_name_cache (image);
4361 user_data.key = name_space;
4362 user_data.value = NULL;
4363 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
4365 if (user_data.value) {
4366 GHashTable *nspace_table = (GHashTable*)user_data.value;
4368 user_data.key = name;
4369 user_data.value = NULL;
4371 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
4373 if (user_data.value)
4374 token = GPOINTER_TO_UINT (user_data.value);
4377 mono_loader_unlock ();
4380 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
4386 /* add a cache if needed */
4387 for (i = 1; i <= t->rows; ++i) {
4388 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
4389 /* nested types are accessed from the nesting name */
4390 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4391 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
4393 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
4394 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
4395 if (g_strcasecmp (n, name) == 0 && g_strcasecmp (nspace, name_space) == 0)
4396 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
4402 return_nested_in (MonoClass *class, char *nested) {
4404 char *s = strchr (nested, '/');
4411 for (tmp = class->nested_classes; tmp; tmp = tmp->next) {
4413 if (strcmp (found->name, nested) == 0) {
4415 return return_nested_in (found, s);
4424 * mono_class_from_name:
4425 * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
4426 * @name_space: the type namespace
4427 * @name: the type short name.
4429 * Obtains a MonoClass with a given namespace and a given name which
4430 * is located in the given MonoImage.
4433 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
4435 GHashTable *nspace_table;
4436 MonoImage *loaded_image;
4442 if ((nested = strchr (name, '/'))) {
4443 int pos = nested - name;
4444 int len = strlen (name);
4447 memcpy (buf, name, len + 1);
4449 nested = buf + pos + 1;
4453 if (get_class_from_name) {
4454 gboolean res = get_class_from_name (image, name_space, name, &class);
4457 return class ? return_nested_in (class, nested) : NULL;
4463 mono_loader_lock ();
4465 if (!image->name_cache)
4466 mono_image_init_name_cache (image);
4468 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
4471 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
4473 mono_loader_unlock ();
4478 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
4479 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
4480 guint32 cols [MONO_EXP_TYPE_SIZE];
4483 idx = mono_metadata_token_index (token);
4485 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
4487 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
4488 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
4489 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
4492 class = mono_class_from_name (loaded_image, name_space, name);
4494 return return_nested_in (class, nested);
4496 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
4497 MonoAssembly **references = image->references;
4498 if (!references [idx - 1])
4499 mono_assembly_load_reference (image, idx - 1);
4500 g_assert (references == image->references);
4501 g_assert (references [idx - 1]);
4502 if (references [idx - 1] == (gpointer)-1)
4505 /* FIXME: Cycle detection */
4506 return mono_class_from_name (references [idx - 1]->image, name_space, name);
4508 g_error ("not yet implemented");
4512 token = MONO_TOKEN_TYPE_DEF | token;
4514 class = mono_class_get (image, token);
4516 return return_nested_in (class, nested);
4521 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
4522 gboolean check_interfaces)
4524 g_assert (klassc->idepth > 0);
4525 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
4526 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
4528 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
4531 for (i = 0; i < klass->interface_count; i ++) {
4532 MonoClass *ic = klass->interfaces [i];
4537 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
4542 * MS.NET thinks interfaces are a subclass of Object, so we think it as
4545 if (klassc == mono_defaults.object_class)
4552 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
4555 mono_class_init (klass);
4557 if (!oklass->inited)
4558 mono_class_init (oklass);
4560 if ((klass->byval_arg.type == MONO_TYPE_VAR) || (klass->byval_arg.type == MONO_TYPE_MVAR))
4561 return klass == oklass;
4563 if (MONO_CLASS_IS_INTERFACE (klass)) {
4564 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR))
4567 /* interface_offsets might not be set for dynamic classes */
4568 if (oklass->reflection_info && !oklass->interface_bitmap)
4570 * oklass might be a generic type parameter but they have
4571 * interface_offsets set.
4573 return mono_reflection_call_is_assignable_to (oklass, klass);
4575 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
4577 } else if (klass->rank) {
4578 MonoClass *eclass, *eoclass;
4580 if (oklass->rank != klass->rank)
4583 /* vectors vs. one dimensional arrays */
4584 if (oklass->byval_arg.type != klass->byval_arg.type)
4587 eclass = klass->cast_class;
4588 eoclass = oklass->cast_class;
4591 * a is b does not imply a[] is b[] when a is a valuetype, and
4592 * b is a reference type.
4595 if (eoclass->valuetype) {
4596 if ((eclass == mono_defaults.enum_class) ||
4597 (eclass == mono_defaults.enum_class->parent) ||
4598 (eclass == mono_defaults.object_class))
4602 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
4603 } else if (mono_class_is_nullable (klass))
4604 return (mono_class_is_assignable_from (klass->cast_class, oklass));
4605 else if (klass == mono_defaults.object_class)
4608 return mono_class_has_parent (oklass, klass);
4612 * mono_class_get_cctor:
4614 * Returns the static constructor of @klass if it exists, NULL otherwise.
4617 mono_class_get_cctor (MonoClass *klass)
4619 MonoCachedClassInfo cached_info;
4621 if (!klass->has_cctor)
4624 if (mono_class_get_cached_class_info (klass, &cached_info))
4625 return mono_get_method (klass->image, cached_info.cctor_token, klass);
4627 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
4631 * mono_class_get_finalizer:
4633 * Returns the finalizer method of @klass if it exists, NULL otherwise.
4636 mono_class_get_finalizer (MonoClass *klass)
4638 MonoCachedClassInfo cached_info;
4641 mono_class_init (klass);
4642 if (!klass->has_finalize)
4645 if (mono_class_get_cached_class_info (klass, &cached_info))
4646 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
4648 mono_class_setup_vtable (klass);
4649 return klass->vtable [finalize_slot];
4654 * mono_class_needs_cctor_run:
4656 * Determines whenever the class has a static constructor and whenever it
4657 * needs to be called when executing CALLER.
4660 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
4664 method = mono_class_get_cctor (klass);
4666 return (method == caller) ? FALSE : TRUE;
4672 * mono_class_array_element_size:
4675 * Returns: the number of bytes an element of type @klass
4676 * uses when stored into an array.
4679 mono_class_array_element_size (MonoClass *klass)
4681 MonoType *type = &klass->byval_arg;
4684 switch (type->type) {
4687 case MONO_TYPE_BOOLEAN:
4691 case MONO_TYPE_CHAR:
4700 case MONO_TYPE_CLASS:
4701 case MONO_TYPE_STRING:
4702 case MONO_TYPE_OBJECT:
4703 case MONO_TYPE_SZARRAY:
4704 case MONO_TYPE_ARRAY:
4706 case MONO_TYPE_MVAR:
4707 return sizeof (gpointer);
4712 case MONO_TYPE_VALUETYPE:
4713 if (type->data.klass->enumtype) {
4714 type = type->data.klass->enum_basetype;
4715 klass = klass->element_class;
4718 return mono_class_instance_size (klass) - sizeof (MonoObject);
4719 case MONO_TYPE_GENERICINST:
4720 type = &type->data.generic_class->container_class->byval_arg;
4723 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
4729 * mono_array_element_size:
4730 * @ac: pointer to a #MonoArrayClass
4732 * Returns: the size of single array element.
4735 mono_array_element_size (MonoClass *ac)
4737 g_assert (ac->rank);
4738 return ac->sizes.element_size;
4742 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
4743 MonoGenericContext *context)
4745 if (image->dynamic) {
4746 MonoClass *tmp_handle_class;
4747 gpointer obj = mono_lookup_dynamic_token_class (image, token, &tmp_handle_class);
4749 g_assert (tmp_handle_class);
4751 *handle_class = tmp_handle_class;
4753 if (tmp_handle_class == mono_defaults.typehandle_class)
4754 return &((MonoClass*)obj)->byval_arg;
4759 switch (token & 0xff000000) {
4760 case MONO_TOKEN_TYPE_DEF:
4761 case MONO_TOKEN_TYPE_REF:
4762 case MONO_TOKEN_TYPE_SPEC: {
4765 *handle_class = mono_defaults.typehandle_class;
4766 type = mono_type_get_full (image, token, context);
4769 mono_class_init (mono_class_from_mono_type (type));
4770 /* We return a MonoType* as handle */
4773 case MONO_TOKEN_FIELD_DEF: {
4775 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
4777 *handle_class = mono_defaults.fieldhandle_class;
4778 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
4781 mono_class_init (class);
4782 return mono_class_get_field (class, token);
4784 case MONO_TOKEN_METHOD_DEF: {
4786 meth = mono_get_method_full (image, token, NULL, context);
4788 *handle_class = mono_defaults.methodhandle_class;
4791 case MONO_TOKEN_MEMBER_REF: {
4792 guint32 cols [MONO_MEMBERREF_SIZE];
4794 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
4795 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
4796 mono_metadata_decode_blob_size (sig, &sig);
4797 if (*sig == 0x6) { /* it's a field */
4799 MonoClassField *field;
4800 field = mono_field_from_token (image, token, &klass, context);
4802 *handle_class = mono_defaults.fieldhandle_class;
4806 meth = mono_get_method_full (image, token, NULL, context);
4808 *handle_class = mono_defaults.methodhandle_class;
4813 g_warning ("Unknown token 0x%08x in ldtoken", token);
4820 * This function might need to call runtime functions so it can't be part
4821 * of the metadata library.
4823 static MonoLookupDynamicToken lookup_dynamic = NULL;
4826 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
4828 lookup_dynamic = func;
4832 mono_lookup_dynamic_token (MonoImage *image, guint32 token)
4834 MonoClass *handle_class;
4836 return lookup_dynamic (image, token, &handle_class);
4840 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, MonoClass **handle_class)
4842 return lookup_dynamic (image, token, handle_class);
4845 static MonoGetCachedClassInfo get_cached_class_info = NULL;
4848 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
4850 get_cached_class_info = func;
4854 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
4856 if (!get_cached_class_info)
4859 return get_cached_class_info (klass, res);
4863 mono_install_get_class_from_name (MonoGetClassFromName func)
4865 get_class_from_name = func;
4869 mono_class_get_image (MonoClass *klass)
4871 return klass->image;
4875 * mono_class_get_element_class:
4876 * @klass: the MonoClass to act on
4878 * Returns: the element class of an array or an enumeration.
4881 mono_class_get_element_class (MonoClass *klass)
4883 return klass->element_class;
4887 * mono_class_is_valuetype:
4888 * @klass: the MonoClass to act on
4890 * Returns: true if the MonoClass represents a ValueType.
4893 mono_class_is_valuetype (MonoClass *klass)
4895 return klass->valuetype;
4899 * mono_class_is_enum:
4900 * @klass: the MonoClass to act on
4902 * Returns: true if the MonoClass represents an enumeration.
4905 mono_class_is_enum (MonoClass *klass)
4907 return klass->enumtype;
4911 * mono_class_enum_basetype:
4912 * @klass: the MonoClass to act on
4914 * Returns: the underlying type representation for an enumeration.
4917 mono_class_enum_basetype (MonoClass *klass)
4919 return klass->enum_basetype;
4923 * mono_class_get_parent
4924 * @klass: the MonoClass to act on
4926 * Returns: the parent class for this class.
4929 mono_class_get_parent (MonoClass *klass)
4931 return klass->parent;
4935 * mono_class_get_nesting_type;
4936 * @klass: the MonoClass to act on
4938 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
4941 mono_class_get_nesting_type (MonoClass *klass)
4943 return klass->nested_in;
4947 * mono_class_get_rank:
4948 * @klass: the MonoClass to act on
4950 * Returns: the rank for the array (the number of dimensions).
4953 mono_class_get_rank (MonoClass *klass)
4959 * mono_class_get_flags:
4960 * @klass: the MonoClass to act on
4962 * The type flags from the TypeDef table from the metadata.
4963 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
4966 * Returns: the flags from the TypeDef table.
4969 mono_class_get_flags (MonoClass *klass)
4971 return klass->flags;
4975 * mono_class_get_name
4976 * @klass: the MonoClass to act on
4978 * Returns: the name of the class.
4981 mono_class_get_name (MonoClass *klass)
4987 * mono_class_get_namespace:
4988 * @klass: the MonoClass to act on
4990 * Returns: the namespace of the class.
4993 mono_class_get_namespace (MonoClass *klass)
4995 return klass->name_space;
4999 * mono_class_get_type:
5000 * @klass: the MonoClass to act on
5002 * This method returns the internal Type representation for the class.
5004 * Returns: the MonoType from the class.
5007 mono_class_get_type (MonoClass *klass)
5009 return &klass->byval_arg;
5013 * mono_class_get_type_token
5014 * @klass: the MonoClass to act on
5016 * This method returns type token for the class.
5018 * Returns: the type token for the class.
5021 mono_class_get_type_token (MonoClass *klass)
5023 return klass->type_token;
5027 * mono_class_get_byref_type:
5028 * @klass: the MonoClass to act on
5033 mono_class_get_byref_type (MonoClass *klass)
5035 return &klass->this_arg;
5039 * mono_class_num_fields:
5040 * @klass: the MonoClass to act on
5042 * Returns: the number of static and instance fields in the class.
5045 mono_class_num_fields (MonoClass *klass)
5047 return klass->field.count;
5051 * mono_class_num_methods:
5052 * @klass: the MonoClass to act on
5054 * Returns: the number of methods in the class.
5057 mono_class_num_methods (MonoClass *klass)
5059 return klass->method.count;
5063 * mono_class_num_properties
5064 * @klass: the MonoClass to act on
5066 * Returns: the number of properties in the class.
5069 mono_class_num_properties (MonoClass *klass)
5071 mono_class_setup_properties (klass);
5073 return klass->property.count;
5077 * mono_class_num_events:
5078 * @klass: the MonoClass to act on
5080 * Returns: the number of events in the class.
5083 mono_class_num_events (MonoClass *klass)
5085 mono_class_setup_events (klass);
5087 return klass->event.count;
5091 * mono_class_get_fields:
5092 * @klass: the MonoClass to act on
5094 * This routine is an iterator routine for retrieving the fields in a class.
5096 * You must pass a gpointer that points to zero and is treated as an opaque handle to
5097 * iterate over all of the elements. When no more values are
5098 * available, the return value is NULL.
5100 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
5103 mono_class_get_fields (MonoClass* klass, gpointer *iter)
5105 MonoClassField* field;
5108 mono_class_setup_fields_locking (klass);
5110 /* start from the first */
5111 if (klass->field.count) {
5112 return *iter = &klass->fields [0];
5120 if (field < &klass->fields [klass->field.count]) {
5121 return *iter = field;
5127 * mono_class_get_methods
5128 * @klass: the MonoClass to act on
5130 * This routine is an iterator routine for retrieving the fields in a class.
5132 * You must pass a gpointer that points to zero and is treated as an opaque handle to
5133 * iterate over all of the elements. When no more values are
5134 * available, the return value is NULL.
5136 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
5139 mono_class_get_methods (MonoClass* klass, gpointer *iter)
5141 MonoMethod** method;
5145 mono_class_init (klass);
5147 mono_class_setup_methods (klass);
5148 /* start from the first */
5149 if (klass->method.count) {
5150 *iter = &klass->methods [0];
5151 return klass->methods [0];
5159 if (method < &klass->methods [klass->method.count]) {
5167 * mono_class_get_properties:
5168 * @klass: the MonoClass to act on
5170 * This routine is an iterator routine for retrieving the properties in a class.
5172 * You must pass a gpointer that points to zero and is treated as an opaque handle to
5173 * iterate over all of the elements. When no more values are
5174 * available, the return value is NULL.
5176 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
5179 mono_class_get_properties (MonoClass* klass, gpointer *iter)
5181 MonoProperty* property;
5185 mono_class_init (klass);
5187 mono_class_setup_properties (klass);
5188 /* start from the first */
5189 if (klass->property.count) {
5190 return *iter = &klass->properties [0];
5198 if (property < &klass->properties [klass->property.count]) {
5199 return *iter = property;
5205 * mono_class_get_events:
5206 * @klass: the MonoClass to act on
5208 * This routine is an iterator routine for retrieving the properties in a class.
5210 * You must pass a gpointer that points to zero and is treated as an opaque handle to
5211 * iterate over all of the elements. When no more values are
5212 * available, the return value is NULL.
5214 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
5217 mono_class_get_events (MonoClass* klass, gpointer *iter)
5223 mono_class_init (klass);
5225 mono_class_setup_events (klass);
5226 /* start from the first */
5227 if (klass->event.count) {
5228 return *iter = &klass->events [0];
5236 if (event < &klass->events [klass->event.count]) {
5237 return *iter = event;
5243 * mono_class_get_interfaces
5244 * @klass: the MonoClass to act on
5246 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
5248 * You must pass a gpointer that points to zero and is treated as an opaque handle to
5249 * iterate over all of the elements. When no more values are
5250 * available, the return value is NULL.
5252 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
5255 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
5261 mono_class_init (klass);
5263 /* start from the first */
5264 if (klass->interface_count) {
5265 *iter = &klass->interfaces [0];
5266 return klass->interfaces [0];
5274 if (iface < &klass->interfaces [klass->interface_count]) {
5282 * mono_class_get_nested_types
5283 * @klass: the MonoClass to act on
5285 * This routine is an iterator routine for retrieving the nested types of a class.
5286 * This works only if @klass is non-generic, or a generic type definition.
5288 * You must pass a gpointer that points to zero and is treated as an opaque handle to
5289 * iterate over all of the elements. When no more values are
5290 * available, the return value is NULL.
5292 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
5295 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
5301 mono_class_init (klass);
5303 /* start from the first */
5304 if (klass->nested_classes) {
5305 *iter = klass->nested_classes;
5306 return klass->nested_classes->data;
5308 /* no nested types */
5322 * mono_field_get_name:
5323 * @field: the MonoClassField to act on
5325 * Returns: the name of the field.
5328 mono_field_get_name (MonoClassField *field)
5334 * mono_field_get_type:
5335 * @field: the MonoClassField to act on
5337 * Returns: MonoType of the field.
5340 mono_field_get_type (MonoClassField *field)
5346 * mono_field_get_type:
5347 * @field: the MonoClassField to act on
5349 * Returns: MonoClass where the field was defined.
5352 mono_field_get_parent (MonoClassField *field)
5354 return field->parent;
5358 * mono_field_get_flags;
5359 * @field: the MonoClassField to act on
5361 * The metadata flags for a field are encoded using the
5362 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
5364 * Returns: the flags for the field.
5367 mono_field_get_flags (MonoClassField *field)
5369 return field->type->attrs;
5373 * mono_field_get_data;
5374 * @field: the MonoClassField to act on
5376 * Returns: pointer to the metadata constant value or to the field
5377 * data if it has an RVA flag.
5380 mono_field_get_data (MonoClassField *field)
5386 * mono_property_get_name:
5387 * @prop: the MonoProperty to act on
5389 * Returns: the name of the property
5392 mono_property_get_name (MonoProperty *prop)
5398 * mono_property_get_set_method
5399 * @prop: the MonoProperty to act on.
5401 * Returns: the setter method of the property (A MonoMethod)
5404 mono_property_get_set_method (MonoProperty *prop)
5410 * mono_property_get_get_method
5411 * @prop: the MonoProperty to act on.
5413 * Returns: the setter method of the property (A MonoMethod)
5416 mono_property_get_get_method (MonoProperty *prop)
5422 * mono_property_get_parent:
5423 * @prop: the MonoProperty to act on.
5425 * Returns: the MonoClass where the property was defined.
5428 mono_property_get_parent (MonoProperty *prop)
5430 return prop->parent;
5434 * mono_property_get_flags:
5435 * @prop: the MonoProperty to act on.
5437 * The metadata flags for a property are encoded using the
5438 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
5440 * Returns: the flags for the property.
5443 mono_property_get_flags (MonoProperty *prop)
5449 * mono_event_get_name:
5450 * @event: the MonoEvent to act on
5452 * Returns: the name of the event.
5455 mono_event_get_name (MonoEvent *event)
5461 * mono_event_get_add_method:
5462 * @event: The MonoEvent to act on.
5464 * Returns: the @add' method for the event (a MonoMethod).
5467 mono_event_get_add_method (MonoEvent *event)
5473 * mono_event_get_remove_method:
5474 * @event: The MonoEvent to act on.
5476 * Returns: the @remove method for the event (a MonoMethod).
5479 mono_event_get_remove_method (MonoEvent *event)
5481 return event->remove;
5485 * mono_event_get_raise_method:
5486 * @event: The MonoEvent to act on.
5488 * Returns: the @raise method for the event (a MonoMethod).
5491 mono_event_get_raise_method (MonoEvent *event)
5493 return event->raise;
5497 * mono_event_get_parent:
5498 * @event: the MonoEvent to act on.
5500 * Returns: the MonoClass where the event is defined.
5503 mono_event_get_parent (MonoEvent *event)
5505 return event->parent;
5509 * mono_event_get_flags
5510 * @event: the MonoEvent to act on.
5512 * The metadata flags for an event are encoded using the
5513 * EVENT_* constants. See the tabledefs.h file for details.
5515 * Returns: the flags for the event.
5518 mono_event_get_flags (MonoEvent *event)
5520 return event->attrs;
5524 * mono_class_get_method_from_name:
5525 * @klass: where to look for the method
5526 * @name_space: name of the method
5527 * @param_count: number of parameters. -1 for any number.
5529 * Obtains a MonoMethod with a given name and number of parameters.
5530 * It only works if there are no multiple signatures for any given method name.
5533 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
5535 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
5539 * mono_class_get_method_from_name_flags:
5540 * @klass: where to look for the method
5541 * @name_space: name of the method
5542 * @param_count: number of parameters. -1 for any number.
5543 * @flags: flags which must be set in the method
5545 * Obtains a MonoMethod with a given name and number of parameters.
5546 * It only works if there are no multiple signatures for any given method name.
5549 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
5551 MonoMethod *res = NULL;
5554 mono_class_init (klass);
5556 if (klass->methods) {
5557 mono_class_setup_methods (klass);
5558 for (i = 0; i < klass->method.count; ++i) {
5559 MonoMethod *method = klass->methods [i];
5561 if (method->name[0] == name [0] &&
5562 !strcmp (name, method->name) &&
5563 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
5564 ((method->flags & flags) == flags)) {
5571 /* Search directly in the metadata to avoid calling setup_methods () */
5572 for (i = 0; i < klass->method.count; ++i) {
5573 guint32 cols [MONO_METHOD_SIZE];
5576 /* class->method.first points into the methodptr table */
5577 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
5579 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
5580 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
5581 if ((param_count == -1) || mono_method_signature (method)->param_count == param_count) {
5593 * mono_class_set_failure:
5594 * @klass: class in which the failure was detected
5595 * @ex_type: the kind of exception/error to be thrown (later)
5596 * @ex_data: exception data (specific to each type of exception/error)
5598 * Keep a detected failure informations in the class for later processing.
5599 * Note that only the first failure is kept.
5602 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
5604 if (klass->exception_type)
5606 klass->exception_type = ex_type;
5607 klass->exception_data = ex_data;
5612 * mono_classes_init:
5614 * Initialize the resources used by this module.
5617 mono_classes_init (void)
5622 * mono_classes_cleanup:
5624 * Free the resources used by this module.
5627 mono_classes_cleanup (void)
5629 IOffsetInfo *cached_info, *next;
5631 if (global_interface_bitset)
5632 mono_bitset_free (global_interface_bitset);
5634 for (cached_info = cached_offset_info; cached_info;) {
5635 next = cached_info->next;
5637 g_free (cached_info);
5643 * mono_class_get_exception_for_failure:
5644 * @klass: class in which the failure was detected
5646 * Return a constructed MonoException than the caller can then throw
5647 * using mono_raise_exception - or NULL if no failure is present (or
5648 * doesn't result in an exception).
5651 mono_class_get_exception_for_failure (MonoClass *klass)
5653 switch (klass->exception_type) {
5654 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
5655 MonoDomain *domain = mono_domain_get ();
5656 MonoSecurityManager* secman = mono_security_manager_get_methods ();
5657 MonoMethod *method = klass->exception_data;
5658 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
5659 MonoObject *exc = NULL;
5663 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
5664 args [2] = mono_type_get_object (domain, &klass->byval_arg);
5665 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
5667 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
5668 return (MonoException*) exc;
5670 case MONO_EXCEPTION_TYPE_LOAD: {
5673 char *str = mono_type_get_full_name (klass);
5674 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
5675 name = mono_string_new (mono_domain_get (), str);
5677 ex = mono_get_exception_type_load (name, astr);
5681 case MONO_EXCEPTION_MISSING_METHOD: {
5682 char *class_name = klass->exception_data;
5683 char *assembly_name = class_name + strlen (class_name) + 1;
5685 return mono_get_exception_missing_method (class_name, assembly_name);
5687 case MONO_EXCEPTION_MISSING_FIELD: {
5688 char *class_name = klass->exception_data;
5689 char *member_name = class_name + strlen (class_name) + 1;
5691 return mono_get_exception_missing_field (class_name, member_name);
5693 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5694 char *msg_format = klass->exception_data;
5695 char *assembly_name = msg_format + strlen (msg_format) + 1;
5696 char *msg = g_strdup_printf (msg_format, assembly_name);
5699 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
5706 MonoLoaderError *error;
5709 error = mono_loader_get_last_error ();
5711 ex = mono_loader_error_prepare_exception (error);
5715 /* TODO - handle other class related failures */
5722 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
5725 if (accessing == accessed)
5727 if (!accessed || !accessing)
5729 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
5730 MonoAssemblyName *friend = tmp->data;
5731 /* Be conservative with checks */
5734 if (strcmp (accessing->aname.name, friend->name))
5736 if (friend->public_key_token [0]) {
5737 if (!accessing->aname.public_key_token [0])
5739 if (strcmp ((char*)friend->public_key_token, (char*)accessing->aname.public_key_token))
5748 * If klass is a generic type or if it is derived from a generic type, return the
5749 * MonoClass of the generic definition
5750 * Returns NULL if not found
5753 get_generic_definition_class (MonoClass *klass)
5756 if (klass->generic_class && klass->generic_class->container_class)
5757 return klass->generic_class->container_class;
5758 klass = klass->parent;
5763 /* FIXME: check visibility of type, too */
5765 can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_level)
5767 MonoClass *member_generic_def;
5768 if (access_klass->generic_class && access_klass->generic_class->container_class &&
5769 (member_generic_def = get_generic_definition_class (member_klass))) {
5770 if (can_access_member (access_klass->generic_class->container_class,
5771 member_generic_def, access_level))
5775 /* Partition I 8.5.3.2 */
5776 /* the access level values are the same for fields and methods */
5777 switch (access_level) {
5778 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
5779 /* same compilation unit */
5780 return access_klass->image == member_klass->image;
5781 case FIELD_ATTRIBUTE_PRIVATE:
5782 return access_klass == member_klass;
5783 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
5784 if (mono_class_has_parent (access_klass, member_klass) &&
5785 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
5788 case FIELD_ATTRIBUTE_ASSEMBLY:
5789 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
5790 case FIELD_ATTRIBUTE_FAMILY:
5791 if (mono_class_has_parent (access_klass, member_klass))
5794 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
5795 if (mono_class_has_parent (access_klass, member_klass))
5797 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
5798 case FIELD_ATTRIBUTE_PUBLIC:
5805 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
5807 /* FIXME: check all overlapping fields */
5808 int can = can_access_member (method->klass, field->parent, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
5810 MonoClass *nested = method->klass->nested_in;
5812 can = can_access_member (nested, field->parent, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
5815 nested = nested->nested_in;
5822 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
5824 int can = can_access_member (method->klass, called->klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
5826 MonoClass *nested = method->klass->nested_in;
5828 can = can_access_member (nested, called->klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
5831 nested = nested->nested_in;
5836 * with generics calls to explicit interface implementations can be expressed
5837 * directly: the method is private, but we must allow it. This may be opening
5838 * a hole or the generics code should handle this differently.
5839 * Maybe just ensure the interface type is public.
5841 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
5847 * mono_type_is_valid_enum_basetype:
5848 * @type: The MonoType to check
5850 * Returns: TRUE if the type can be used as the basetype of an enum
5852 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
5853 switch (type->type) {
5856 case MONO_TYPE_BOOLEAN:
5859 case MONO_TYPE_CHAR:
5872 * mono_class_is_valid_enum:
5873 * @klass: An enum class to be validated
5875 * This method verify the required properties an enum should have.
5877 * Returns: TRUE if the informed enum class is valid
5879 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
5880 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
5881 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
5883 gboolean mono_class_is_valid_enum (MonoClass *klass) {
5884 MonoClassField * field;
5885 gpointer iter = NULL;
5886 gboolean found_base_field = FALSE;
5888 g_assert (klass->enumtype);
5889 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
5890 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
5894 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
5897 while ((field = mono_class_get_fields (klass, &iter))) {
5898 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
5899 if (found_base_field)
5901 found_base_field = TRUE;
5902 if (!mono_type_is_valid_enum_basetype (field->type))
5907 if (!found_base_field)
5910 if (klass->method.count > 0)