X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=1b2011b9b4bc067e68457434b7db94b04f8cef0f;hb=3e6e9349cd6e938a7f73af408b94bdc2c35a487e;hp=de6b4ecfaefbedd135689712b8059a8d04b7c838;hpb=2f723104ad69c78d4df9a63c87ccb65d5634cf32;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index de6b4ecfaef..1b2011b9b4b 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -29,17 +30,9 @@ #include #include #include +#include #include -/* - * Uncomment this to enable GC aware auto layout: in this mode, reference - * fields are grouped together inside objects, increasing collector - * performance. - * Requires that all classes whose layout is known to the runtime be annotated - * with [StructLayout (LayoutKind.Sequential)] - */ -//#define GC_AWARE_AUTO_LAYOUT - #define CSIZE(x) (sizeof (x) / 4) MonoStats mono_stats; @@ -59,7 +52,6 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token) const char *name, *nspace; MonoClass *res; MonoAssembly **references; - MonoImageOpenStatus status; mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE); @@ -91,7 +83,6 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token) break; } - mono_image_load_references (image, &status); references = image->references; if (!references || !references [idx-1]) { /* @@ -114,85 +105,196 @@ mono_class_from_typeref (MonoImage *image, guint32 type_token) return mono_class_from_name (image, nspace, name); } -MonoMarshalType * -mono_marshal_load_type_info (MonoClass* klass) +static MonoType* +dup_type (MonoType* t) { - int i, j, count = 0, native_size = 0; - MonoMarshalType *info; - guint32 layout; - - g_assert (klass != NULL); - - if (klass->marshal_info) - return klass->marshal_info; + MonoType *r = g_new0 (MonoType, 1); + *r = *t; + return r; +} - if (!klass->inited) - mono_class_init (klass); +static void +mono_type_get_name_recurse (MonoType *type, GString *str) +{ + MonoClass *klass; - for (i = 0; i < klass->field.count; ++i) { - if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) - continue; - count++; + switch (type->type) { + case MONO_TYPE_ARRAY: { + int i, rank = type->data.array->rank; + + mono_type_get_name_recurse (&type->data.array->eklass->byval_arg, str); + g_string_append_c (str, '['); + for (i = 1; i < rank; i++) + g_string_append_c (str, ','); + g_string_append_c (str, ']'); + break; } + case MONO_TYPE_SZARRAY: + mono_type_get_name_recurse (&type->data.klass->byval_arg, str); + g_string_append (str, "[]"); + break; + case MONO_TYPE_PTR: + mono_type_get_name_recurse (type->data.type, str); + g_string_append_c (str, '*'); + break; + default: + klass = mono_class_from_mono_type (type); + if (klass->nested_in) { + mono_type_get_name_recurse (&klass->nested_in->byval_arg, str); + g_string_append_c (str, '+'); + } + if (*klass->name_space) { + g_string_append (str, klass->name_space); + g_string_append_c (str, '.'); + } + g_string_append (str, klass->name); + break; + } +} - layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK; - - klass->marshal_info = info = g_malloc0 (sizeof (MonoMarshalType) + sizeof (MonoMarshalField) * count); - info->num_fields = count; - - /* Try to find a size for this type in metadata */ - mono_metadata_packing_from_typedef (klass->image, klass->type_token, NULL, &native_size); - - if (klass->parent) { - int parent_size = mono_class_native_size (klass->parent, NULL); +/* + * mono_type_get_name: + * @type: a type + * + * Returns the string representation for type as required by System.Reflection. + * The inverse of mono_reflection_parse_type (). + */ +char* +mono_type_get_name (MonoType *type) +{ + GString* result = g_string_new (""); + mono_type_get_name_recurse (type, result); - /* Add parent size to real size */ - native_size += parent_size; - info->native_size = parent_size; - } - - for (j = i = 0; i < klass->field.count; ++i) { - int size, align; - - if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) - continue; + if (type->byref) + g_string_append_c (result, '&'); - if (klass->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) - mono_metadata_field_info (klass->image, klass->field.first + i, - NULL, NULL, &info->fields [j].mspec); + return g_string_free (result, FALSE); +} - info->fields [j].field = &klass->fields [i]; +gboolean +mono_class_is_open_constructed_type (MonoType *t) +{ + switch (t->type) { + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: + return TRUE; + case MONO_TYPE_SZARRAY: + return mono_class_is_open_constructed_type (&t->data.klass->byval_arg); + case MONO_TYPE_ARRAY: + return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg); + case MONO_TYPE_PTR: + return mono_class_is_open_constructed_type (t->data.type); + case MONO_TYPE_GENERICINST: { + MonoGenericInst *ginst = t->data.generic_inst; + int i; - switch (layout) { - case TYPE_ATTRIBUTE_AUTO_LAYOUT: - case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT: - size = mono_marshal_type_size (klass->fields [i].type, info->fields [j].mspec, - &align, TRUE, klass->unicode); - align = klass->packing_size ? MIN (klass->packing_size, align): align; - info->fields [j].offset = info->native_size; - info->fields [j].offset += align - 1; - info->fields [j].offset &= ~(align - 1); - info->native_size = info->fields [j].offset + size; - break; - case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: - /* FIXME: */ - info->fields [j].offset = klass->fields [i].offset - sizeof (MonoObject); - info->native_size = klass->instance_size - sizeof (MonoObject); - break; - } - j++; + if (mono_class_is_open_constructed_type (ginst->generic_type)) + return TRUE; + for (i = 0; i < ginst->type_argc; i++) + if (mono_class_is_open_constructed_type (ginst->type_argv [i])) + return TRUE; + return FALSE; } + default: + return FALSE; + } +} - if(layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) { - info->native_size = MAX (native_size, info->native_size); +MonoType* +mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst) +{ + switch (type->type) { + case MONO_TYPE_MVAR: + if (ginst) + return dup_type (ginst->type_argv [type->data.generic_param->num]); + else + return type; + case MONO_TYPE_VAR: { + MonoType *t = ginst->type_argv [type->data.generic_param->num]; + + if ((t->type == MONO_TYPE_VAR) || (t->type == MONO_TYPE_MVAR)) + return type; + else + return dup_type (t); + } + case MONO_TYPE_SZARRAY: { + MonoClass *eclass = type->data.klass; + MonoClass *nclass; + MonoType *nt; + if (eclass->byval_arg.type == MONO_TYPE_MVAR) { + nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]); + } else if (eclass->byval_arg.type == MONO_TYPE_VAR) { + nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]); + } else { + return type; + } + nt = dup_type (type); + nt->data.klass = nclass; + return nt; + } + default: + return type; } + return type; +} + +MonoMethodSignature* +mono_class_inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericInst *ginst) +{ + MonoMethodSignature *res; + int i; + res = mono_metadata_signature_alloc (image, sig->param_count); + res->ret = mono_class_inflate_generic_type (sig->ret, ginst); + for (i = 0; i < sig->param_count; ++i) { + res->params [i] = mono_class_inflate_generic_type (sig->params [i], ginst); + } + res->hasthis = sig->hasthis; + res->explicit_this = sig->explicit_this; + res->call_convention = sig->call_convention; + res->generic_param_count = sig->generic_param_count; + return res; +} - if (info->native_size & (klass->min_align - 1)) { - info->native_size += klass->min_align - 1; - info->native_size &= ~(klass->min_align - 1); +static MonoMethodHeader* +inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *ginst) +{ + MonoMethodHeader *res; + int i; + res = g_malloc0 (sizeof (MonoMethodHeader) + sizeof (gpointer) * header->num_locals); + res->code = header->code; + res->code_size = header->code_size; + res->max_stack = header->max_stack; + res->num_clauses = header->num_clauses; + res->init_locals = header->init_locals; + res->num_locals = header->num_locals; + res->clauses = header->clauses; + res->gen_params = header->gen_params; + res->geninst = ginst; + for (i = 0; i < header->num_locals; ++i) { + res->locals [i] = mono_class_inflate_generic_type (header->locals [i], ginst); } + return res; +} - return klass->marshal_info; +MonoMethod* +mono_class_inflate_generic_method (MonoMethod *method, MonoGenericInst *ginst) +{ + MonoMethod *result; + if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) { + MonoMethodPInvoke *nmethod = g_new0 (MonoMethodPInvoke, 1); + *nmethod = *(MonoMethodPInvoke*)method; + result = (MonoMethod*)nmethod; + } else { + MonoMethodNormal *nmethod = g_new0 (MonoMethodNormal, 1); + *nmethod = *(MonoMethodNormal*)method; + result = (MonoMethod*)nmethod; + if (nmethod->header) + nmethod->header = inflate_generic_header (nmethod->header, ginst); + } + if (ginst->klass) + result->klass = ginst->klass; + result->signature = mono_class_inflate_generic_signature (method->klass->image, result->signature, ginst); + return result; } /** @@ -215,6 +317,7 @@ class_compute_field_layout (MonoClass *class) int i, blittable = TRUE, real_size = 0; guint32 rva; guint32 packing_size = 0; + gboolean explicit_size; if (class->size_inited) return; @@ -231,12 +334,18 @@ class_compute_field_layout (MonoClass *class) } /* Get the real size */ - mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size); + explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size); - g_assert ((packing_size & 0xfffffff0) == 0); - class->packing_size = packing_size; + if (explicit_size) { + g_assert ((packing_size & 0xfffffff0) == 0); + class->packing_size = packing_size; + real_size += class->instance_size; + } if (!top) { + if (explicit_size && real_size) { + class->instance_size = MAX (real_size, class->instance_size); + } class->size_inited = 1; return; } @@ -250,7 +359,7 @@ class_compute_field_layout (MonoClass *class) const char *sig; guint32 cols [MONO_FIELD_SIZE]; int idx = class->field.first + i; - + mono_metadata_decode_row (t, idx, cols, CSIZE (cols)); /* The name is needed for fieldrefs */ class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]); @@ -260,6 +369,10 @@ class_compute_field_layout (MonoClass *class) g_assert (*sig == 0x06); class->fields [i].type = mono_metadata_parse_field_type ( m, cols [MONO_FIELD_FLAGS], sig + 1, &sig); + if (class->generic_inst) { + class->fields [i].type = mono_class_inflate_generic_type (class->fields [i].type, class->generic_inst->data.generic_inst); + class->fields [i].type->attrs = cols [MONO_FIELD_FLAGS]; + } class->fields [i].parent = class; @@ -290,6 +403,8 @@ class_compute_field_layout (MonoClass *class) class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype); blittable = class->element_class->blittable; } + + /* The def_value of fields is compute lazily during vtable creation */ } if (class == mono_defaults.string_class) @@ -301,14 +416,14 @@ class_compute_field_layout (MonoClass *class) if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0))) G_BREAKPOINT (); } - mono_class_layout_fields (class); + if (explicit_size && real_size) { + class->instance_size = MAX (real_size, class->instance_size); + } - if(real_size) { - if(class->parent) - real_size += class->parent->instance_size; + if (class->gen_params) + return; - class->instance_size = MAX(real_size, class->instance_size); - } + mono_class_layout_fields (class); } void @@ -317,7 +432,21 @@ mono_class_layout_fields (MonoClass *class) int i; const int top = class->field.count; guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK; - guint32 pass, passes; + guint32 pass, passes, real_size; + gboolean gc_aware_layout = FALSE; + + /* + * Enable GC aware auto layout: in this mode, reference + * fields are grouped together inside objects, increasing collector + * performance. + * Requires that all classes whose layout is known to native code be annotated + * with [StructLayout (LayoutKind.Sequential)] + */ + /* corlib is missing [StructLayout] directives in many places */ + if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) { + if (class->image != mono_defaults.corlib) + gc_aware_layout = TRUE; + } /* * Compute field layout and total size (not considering static fields) @@ -327,14 +456,19 @@ mono_class_layout_fields (MonoClass *class) case TYPE_ATTRIBUTE_AUTO_LAYOUT: case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT: -#ifdef GC_AWARE_AUTO_LAYOUT - passes = 2; -#else - passes = 1; -#endif + if (gc_aware_layout) + passes = 2; + else + passes = 1; + if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT) passes = 1; + if (class->parent) + real_size = class->parent->instance_size; + else + real_size = sizeof (MonoObject); + for (pass = 0; pass < passes; ++pass) { for (i = 0; i < top; i++){ int size, align; @@ -342,14 +476,15 @@ mono_class_layout_fields (MonoClass *class) if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) continue; -#ifdef GC_AWARE_AUTO_LAYOUT - /* FIXME: Fix mono_marshal_load_type_info () too */ - if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) { + if (gc_aware_layout) { /* * We process fields with reference type in the first pass, * and fields with non-reference type in the second pass. + * We use IS_POINTER instead of IS_REFERENCE because in + * some internal structures, we store GC_MALLOCed memory + * in IntPtr fields... */ - if (MONO_TYPE_IS_REFERENCE (class->fields [i].type)) { + if (MONO_TYPE_IS_POINTER (class->fields [i].type)) { if (pass == 1) continue; } else { @@ -357,18 +492,25 @@ mono_class_layout_fields (MonoClass *class) continue; } } -#endif + + if ((top == 1) && (class->instance_size == sizeof (MonoObject)) && + (strcmp (class->fields [i].name, "$PRIVATE$") == 0)) { + /* This field is a hack inserted by MCS to empty structures */ + continue; + } size = mono_type_size (class->fields [i].type, &align); /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */ align = class->packing_size ? MIN (class->packing_size, align): align; class->min_align = MAX (align, class->min_align); - class->fields [i].offset = class->instance_size; + class->fields [i].offset = real_size; class->fields [i].offset += align - 1; class->fields [i].offset &= ~(align - 1); - class->instance_size = class->fields [i].offset + size; + real_size = class->fields [i].offset + size; } + + class->instance_size = MAX (real_size, class->instance_size); if (class->instance_size & (class->min_align - 1)) { class->instance_size += class->min_align - 1; @@ -377,6 +519,7 @@ mono_class_layout_fields (MonoClass *class) } break; case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: + real_size = 0; for (i = 0; i < top; i++) { int size, align; @@ -401,8 +544,9 @@ mono_class_layout_fields (MonoClass *class) /* * Calc max size. */ - class->instance_size = MAX (class->instance_size, size + class->fields [i].offset); + real_size = MAX (real_size, size + class->fields [i].offset); } + class->instance_size = MAX (real_size, class->instance_size); break; } @@ -411,42 +555,17 @@ mono_class_layout_fields (MonoClass *class) /* * Compute static field layout and size */ - switch (layout) { - case TYPE_ATTRIBUTE_AUTO_LAYOUT: - case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT: - for (i = 0; i < top; i++){ - int size, align; - - if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) - continue; + for (i = 0; i < top; i++){ + int size, align; - size = mono_type_size (class->fields [i].type, &align); - class->fields [i].offset = class->class_size; - class->fields [i].offset += align - 1; - class->fields [i].offset &= ~(align - 1); - class->class_size = class->fields [i].offset + size; - - } - break; - case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: - for (i = 0; i < top; i++){ - int size, align; - - /* - * There must be info about all the fields in a type if it - * uses explicit layout. - */ + if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) + continue; - if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) - continue; - - size = mono_type_size (class->fields [i].type, &align); - class->fields [i].offset = class->class_size; - class->fields [i].offset += align - 1; - class->fields [i].offset &= ~(align - 1); - class->class_size = class->fields [i].offset + size; - } - break; + size = mono_type_size (class->fields [i].type, &align); + class->fields [i].offset = class->class_size; + class->fields [i].offset += align - 1; + class->fields [i].offset &= ~(align - 1); + class->class_size = class->fields [i].offset + size; } } @@ -533,12 +652,15 @@ mono_get_unique_iid (MonoClass *class) g_assert (class->flags & TYPE_ATTRIBUTE_INTERFACE); + mono_loader_lock (); + if (!iid_hash) iid_hash = g_hash_table_new (g_str_hash, g_str_equal); str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name); if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) { + mono_loader_unlock (); g_free (str); return (guint)value; } else { @@ -546,11 +668,13 @@ mono_get_unique_iid (MonoClass *class) ++iid; } + mono_loader_unlock (); + return iid - 1; } static void -collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray *res) +collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res) { int i; MonoClass *ic; @@ -558,18 +682,20 @@ collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray *res) for (i = 0; i < klass->interface_count; i++) { ic = klass->interfaces [i]; - g_ptr_array_add (res, ic); + if (*res == NULL) + *res = g_ptr_array_new (); + g_ptr_array_add (*res, ic); collect_implemented_interfaces_aux (ic, res); } } -static GPtrArray* +static inline GPtrArray* collect_implemented_interfaces (MonoClass *klass) { - GPtrArray *res = g_ptr_array_new (); + GPtrArray *res = NULL; - collect_implemented_interfaces_aux (klass, res); + collect_implemented_interfaces_aux (klass, &res); return res; } @@ -606,28 +732,36 @@ setup_interface_offsets (MonoClass *class, int cur_slot) class->interface_offsets [i] = -1; ifaces = collect_implemented_interfaces (class); - for (i = 0; i < ifaces->len; ++i) { - ic = g_ptr_array_index (ifaces, i); - class->interface_offsets [ic->interface_id] = cur_slot; - cur_slot += ic->method.count; + if (ifaces) { + for (i = 0; i < ifaces->len; ++i) { + ic = g_ptr_array_index (ifaces, i); + class->interface_offsets [ic->interface_id] = cur_slot; + cur_slot += ic->method.count; + } + g_ptr_array_free (ifaces, TRUE); } - g_ptr_array_free (ifaces, TRUE); for (k = class->parent; k ; k = k->parent) { ifaces = collect_implemented_interfaces (k); - for (i = 0; i < ifaces->len; ++i) { - ic = g_ptr_array_index (ifaces, i); + if (ifaces) { + for (i = 0; i < ifaces->len; ++i) { + ic = g_ptr_array_index (ifaces, i); - if (class->interface_offsets [ic->interface_id] == -1) { - int io = k->interface_offsets [ic->interface_id]; + if (class->interface_offsets [ic->interface_id] == -1) { + int io = k->interface_offsets [ic->interface_id]; - g_assert (io >= 0); + g_assert (io >= 0); - class->interface_offsets [ic->interface_id] = io; + class->interface_offsets [ic->interface_id] = io; + } } + g_ptr_array_free (ifaces, TRUE); } - g_ptr_array_free (ifaces, TRUE); } + + if (class->flags & TYPE_ATTRIBUTE_INTERFACE) + class->interface_offsets [class->interface_id] = cur_slot; + return cur_slot; } @@ -638,7 +772,7 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) MonoMethod **vtable; int i, max_vtsize = 0, max_iid, cur_slot = 0; GPtrArray *ifaces; - MonoGHashTable *override_map; + MonoGHashTable *override_map = NULL; /* setup_vtable() must be called only once on the type */ if (class->interface_offsets) { @@ -647,11 +781,13 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) } ifaces = collect_implemented_interfaces (class); - for (i = 0; i < ifaces->len; i++) { - MonoClass *ic = g_ptr_array_index (ifaces, i); - max_vtsize += ic->method.count; + if (ifaces) { + for (i = 0; i < ifaces->len; i++) { + MonoClass *ic = g_ptr_array_index (ifaces, i); + max_vtsize += ic->method.count; + } + g_ptr_array_free (ifaces, TRUE); } - g_ptr_array_free (ifaces, TRUE); if (class->parent) { max_vtsize += class->parent->vtable_size; @@ -671,8 +807,6 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) if (class->parent && class->parent->vtable_size) memcpy (vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size); - override_map = mono_g_hash_table_new (NULL, NULL); - /* override interface methods */ for (i = 0; i < onum; i++) { MonoMethod *decl = overrides [i*2]; @@ -682,13 +816,19 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) dslot = decl->slot + class->interface_offsets [decl->klass->interface_id]; vtable [dslot] = overrides [i*2 + 1]; vtable [dslot]->slot = dslot; + if (!override_map) + override_map = mono_g_hash_table_new (NULL, NULL); + mono_g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]); } } for (k = class; k ; k = k->parent) { + int nifaces = 0; ifaces = collect_implemented_interfaces (k); - for (i = 0; i < ifaces->len; i++) { + if (ifaces) + nifaces = ifaces->len; + for (i = 0; i < nifaces; i++) { int j, l, io; ic = g_ptr_array_index (ifaces, i); @@ -829,7 +969,8 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) } } } - g_ptr_array_free (ifaces, TRUE); + if (ifaces) + g_ptr_array_free (ifaces, TRUE); } for (i = 0; i < class->method.count; ++i) { @@ -849,6 +990,8 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) mono_metadata_signature_equal (cm->signature, m1->signature)) { slot = k->methods [j]->slot; g_assert (cm->slot < max_vtsize); + if (!override_map) + override_map = mono_g_hash_table_new (NULL, NULL); mono_g_hash_table_insert (override_map, m1, cm); break; } @@ -863,7 +1006,7 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) if (cm->slot < 0) cm->slot = cur_slot++; - if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT)) + if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && !cm->signature->generic_param_count) vtable [cm->slot] = cm; } @@ -874,6 +1017,8 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) g_assert (decl->slot != -1); vtable [decl->slot] = overrides [i*2 + 1]; overrides [i * 2 + 1]->slot = decl->slot; + if (!override_map) + override_map = mono_g_hash_table_new (NULL, NULL); mono_g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]); } } @@ -882,14 +1027,16 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) * If a method occupies more than one place in the vtable, and it is * overriden, then change the other occurances too. */ - for (i = 0; i < max_vtsize; ++i) - if (vtable [i]) { - MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]); - if (cm) - vtable [i] = cm; - } - mono_g_hash_table_destroy (override_map); + if (override_map) { + for (i = 0; i < max_vtsize; ++i) + if (vtable [i]) { + MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]); + if (cm) + vtable [i] = cm; + } + mono_g_hash_table_destroy (override_map); + } class->vtable_size = cur_slot; class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size); @@ -965,6 +1112,17 @@ mono_class_init (MonoClass *class) if (class->inited) return; + /*g_print ("Init class %s\n", class->name);*/ + + /* We do everything inside the lock to prevent races */ + mono_loader_lock (); + + if (class->inited) { + mono_loader_unlock (); + /* Somebody might have gotten in before us */ + return; + } + if (class->init_pending) { /* this indicates a cyclic dependency */ g_error ("pending init %s.%s\n", class->name_space, class->name); @@ -984,10 +1142,50 @@ mono_class_init (MonoClass *class) class_compute_field_layout (class); /* initialize method pointers */ - class->methods = g_new (MonoMethod*, class->method.count); - for (i = 0; i < class->method.count; ++i) - class->methods [i] = mono_get_method (class->image, - MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class); + if (class->rank) { + MonoMethod *ctor; + MonoMethodSignature *sig; + class->method.count = class->rank > 1? 2: 1; + sig = mono_metadata_signature_alloc (class->image, class->rank); + sig->ret = &mono_defaults.void_class->byval_arg; + sig->pinvoke = TRUE; + for (i = 0; i < class->rank; ++i) + sig->params [i] = &mono_defaults.int32_class->byval_arg; + + ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1); + ctor->klass = class; + ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME; + ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL; + ctor->signature = sig; + ctor->name = ".ctor"; + ctor->slot = -1; + class->methods = g_new (MonoMethod*, class->method.count); + class->methods [0] = ctor; + if (class->rank > 1) { + sig = mono_metadata_signature_alloc (class->image, class->rank * 2); + sig->ret = &mono_defaults.void_class->byval_arg; + sig->pinvoke = TRUE; + for (i = 0; i < class->rank * 2; ++i) + sig->params [i] = &mono_defaults.int32_class->byval_arg; + + ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1); + ctor->klass = class; + ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME; + ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL; + ctor->signature = sig; + ctor->name = ".ctor"; + ctor->slot = -1; + class->methods [1] = ctor; + } + } else { + if (!class->generic_inst && !class->methods) { + class->methods = g_new (MonoMethod*, class->method.count); + for (i = 0; i < class->method.count; ++i) { + class->methods [i] = mono_get_method (class->image, + MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class); + } + } + } init_properties (class); init_events (class); @@ -1015,6 +1213,7 @@ mono_class_init (MonoClass *class) * we have to setup them for interfaces, too. */ setup_interface_offsets (class, 0); + mono_loader_unlock (); return; } @@ -1076,30 +1275,13 @@ mono_class_init (MonoClass *class) class->has_finalize = 1; } + mono_loader_unlock (); + if (mono_debugger_class_init_func) mono_debugger_class_init_func (class); } -/* - * Compute a relative numbering of the class hierarchy as described in - * "Java for Large-Scale Scientific Computations?" - */ -static void -mono_compute_relative_numbering (MonoClass *class, int *c) -{ - GList *s; - - (*c)++; - - class->baseval = *c; - - for (s = class->subclasses; s; s = s->next) - mono_compute_relative_numbering ((MonoClass *)s->data, c); - - class->diffval = *c - class->baseval; -} - void mono_class_setup_mono_type (MonoClass *class) { @@ -1199,6 +1381,12 @@ mono_class_setup_mono_type (MonoClass *class) class->blittable = TRUE; } break; + case 'T': + if (!strcmp (name, "TypedReference")) { + t = MONO_TYPE_TYPEDBYREF; + class->blittable = TRUE; + } + break; case 'V': if (!strcmp (name, "Void")) { t = MONO_TYPE_VOID; @@ -1232,12 +1420,20 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent) } if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) { - int rnum = 0; class->parent = parent; if (!parent) g_assert_not_reached (); /* FIXME */ + if (parent->generic_inst && !parent->name) { + /* + * If the parent is a generic instance, we may get + * called before it is fully initialized, especially + * before it has its name. + */ + return; + } + class->marshalbyref = parent->marshalbyref; class->contextbound = parent->contextbound; class->delegate = parent->delegate; @@ -1260,8 +1456,6 @@ mono_class_setup_parent (MonoClass *class, MonoClass *parent) class->valuetype = class->enumtype = 1; } /*class->enumtype = class->parent->enumtype; */ - class->parent->subclasses = g_list_prepend (class->parent->subclasses, class); - mono_compute_relative_numbering (mono_defaults.object_class, &rnum); mono_class_setup_supertypes (class); } else { class->parent = NULL; @@ -1310,8 +1504,12 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) guint icount = 0; MonoClass **interfaces; - if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) + mono_loader_lock (); + + if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) { + mono_loader_unlock (); return class; + } g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF); @@ -1347,7 +1545,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) class->cast_class = class->element_class = class; - /*g_print ("Init class %s\n", name);*/ + /*g_print ("Load class %s\n", name);*/ mono_class_setup_parent (class, parent); @@ -1391,9 +1589,217 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) if ((type_token = mono_metadata_nested_in_typedef (image, type_token))) class->nested_in = mono_class_create_from_typedef (image, type_token); + class->gen_params = mono_metadata_load_generic_params (image, class->type_token, &icount); + class->num_gen_params = icount; + + mono_loader_unlock (); + + return class; +} + +static char* +get_instantiation_name (const char *name, MonoGenericInst *ginst) +{ + GString *res = g_string_new (name); + const char *p; + int i; + MonoClass *argclass; + + p = strchr (name, '<'); + if (p) { + g_string_truncate (res, (p - name) + 1); + } else { + g_string_append_c (res, '<'); + } + for (i = 0; i < ginst->type_argc; ++i) { + if (i > 0) + g_string_append_c (res, ','); + argclass = mono_class_from_mono_type (ginst->type_argv [i]); + g_string_append (res, argclass->name); + } + g_string_append_c (res, '>'); + return g_string_free (res, FALSE); +} + +MonoClass* +mono_class_create_from_generic (MonoImage *image, MonoType *gtype) +{ + MonoClass *gklass = mono_class_from_mono_type (gtype->data.generic_inst->generic_type); + MonoClass *class; + + mono_class_init (gklass); + + class = g_new0 (MonoClass, 1); + class->name_space = gklass->name_space; + class->image = image; + class->flags = gklass->flags; + + class->generic_inst = gtype; + + class->cast_class = class->element_class = class; + + return class; +} + +void +mono_class_initialize_generic (MonoClass *class, gboolean inflate_methods) +{ + MonoGenericInst *ginst = class->generic_inst->data.generic_inst; + MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type); + + if (class->name) + return; + + class->name = get_instantiation_name (gklass->name, ginst); + + if (inflate_methods) { + int i; + + mono_class_setup_parent (class, gklass->parent); + mono_class_setup_mono_type (class); + + class->field = gklass->field; + class->method = gklass->method; + class->methods = g_new0 (MonoMethod *, class->method.count); + for (i = 0; i < class->method.count; i++) + class->methods [i] = mono_class_inflate_generic_method (gklass->methods [i], ginst); + } + + g_hash_table_insert (class->image->generics_cache, ginst->generic_type, class); +} + +MonoClass* +mono_class_from_generic (MonoType *gtype, gboolean inflate_methods) +{ + MonoGenericInst *ginst = gtype->data.generic_inst; + MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type); + MonoClass *class; + MonoImage *image; + + if (ginst->klass) + return ginst->klass; + + mono_loader_lock (); + + image = gklass->image; + if ((class = g_hash_table_lookup (image->generics_cache, gtype))) { + mono_loader_unlock (); + return class; + } + + mono_class_init (gklass); + + class = g_malloc0 (sizeof (MonoClass)); + class->name_space = gklass->name_space; + class->name = get_instantiation_name (gklass->name, ginst); + class->image = image; + class->flags = gklass->flags; + + class->generic_inst = gtype; + + class->cast_class = class->element_class = class; + + if (inflate_methods) { + int i; + + mono_class_setup_parent (class, gklass->parent); + mono_class_setup_mono_type (class); + + class->field = gklass->field; + class->method = gklass->method; + class->methods = g_new0 (MonoMethod *, class->method.count); + for (i = 0; i < class->method.count; i++) + class->methods [i] = mono_class_inflate_generic_method (gklass->methods [i], ginst); + } + + g_hash_table_insert (image->generics_cache, gtype, class); + + mono_loader_unlock (); + return class; } +MonoClass * +mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar) +{ + MonoClass *klass, **ptr; + int count, pos, i; + + if (param->pklass) + return param->pklass; + + klass = param->pklass = g_new0 (MonoClass, 1); + + for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++) + ; + + pos = 0; + if ((count > 0) && !(param->constraints [0]->flags & TYPE_ATTRIBUTE_INTERFACE)) { + klass->parent = param->constraints [0]; + pos++; + } else + klass->parent = mono_defaults.object_class; + + if (count - pos > 0) { + int j; + + klass->interface_count = count - pos; + klass->interfaces = g_new0 (MonoClass *, count - pos); + for (i = pos; i < count; i++) { + klass->interfaces [i - pos] = param->constraints [i]; + klass->method.count += param->constraints [i]->method.count; + } + + klass->methods = g_new0 (MonoMethod *, klass->method.count); + for (i = pos; i < count; i++) { + MonoClass *iface = klass->interfaces [i - pos]; + for (j = 0; j < iface->method.count; j++) + klass->methods [klass->method.last++] = iface->methods [j]; + } + } + + klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num); + klass->name_space = ""; + klass->image = image; + klass->cast_class = klass->element_class = klass; + klass->enum_basetype = &klass->element_class->byval_arg; + klass->flags = TYPE_ATTRIBUTE_INTERFACE; + + klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR; + klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param; + klass->this_arg.byref = TRUE; + + mono_class_init (klass); + + return klass; +} + +static MonoClass * +my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar) +{ + MonoClass *klass; + + if (param->pklass) + return param->pklass; + + klass = g_new0 (MonoClass, 1); + + klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num); + klass->name_space = ""; + klass->image = mono_defaults.corlib; + klass->cast_class = klass->element_class = klass; + klass->enum_basetype = &klass->element_class->byval_arg; + klass->flags = TYPE_ATTRIBUTE_INTERFACE; + + klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR; + klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param; + klass->this_arg.byref = TRUE; + + mono_class_init (klass); + + return klass; +} + MonoClass * mono_ptr_class_get (MonoType *type) { @@ -1401,11 +1807,15 @@ mono_ptr_class_get (MonoType *type) MonoClass *el_class; static GHashTable *ptr_hash = NULL; + mono_loader_lock (); + if (!ptr_hash) - ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal); + ptr_hash = g_hash_table_new (NULL, NULL); el_class = mono_class_from_mono_type (type); - if ((result = g_hash_table_lookup (ptr_hash, el_class))) + if ((result = g_hash_table_lookup (ptr_hash, el_class))) { + mono_loader_unlock (); return result; + } result = g_new0 (MonoClass, 1); result->parent = NULL; /* no parent for PTR types */ @@ -1416,9 +1826,6 @@ mono_ptr_class_get (MonoType *type) result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); /* Can pointers get boxed? */ result->instance_size = sizeof (gpointer); - /* - * baseval, diffval: need them to allow casting ? - */ result->cast_class = result->element_class = el_class; result->enum_basetype = &result->element_class->byval_arg; @@ -1426,8 +1833,12 @@ mono_ptr_class_get (MonoType *type) result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype; result->this_arg.byref = TRUE; + mono_class_setup_supertypes (result); + g_hash_table_insert (ptr_hash, el_class, result); + mono_loader_unlock (); + return result; } @@ -1437,11 +1848,15 @@ mono_fnptr_class_get (MonoMethodSignature *sig) MonoClass *result; static GHashTable *ptr_hash = NULL; + mono_loader_lock (); + if (!ptr_hash) - ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal); + ptr_hash = g_hash_table_new (NULL, NULL); - if ((result = g_hash_table_lookup (ptr_hash, sig))) + if ((result = g_hash_table_lookup (ptr_hash, sig))) { + mono_loader_unlock (); return result; + } result = g_new0 (MonoClass, 1); result->parent = NULL; /* no parent for PTR types */ @@ -1452,9 +1867,6 @@ mono_fnptr_class_get (MonoMethodSignature *sig) result->flags = TYPE_ATTRIBUTE_CLASS; // | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); /* Can pointers get boxed? */ result->instance_size = sizeof (gpointer); - /* - * baseval, diffval: need them to allow casting ? - */ result->cast_class = result->element_class = result; result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR; @@ -1462,8 +1874,12 @@ mono_fnptr_class_get (MonoMethodSignature *sig) result->this_arg.byref = TRUE; result->enum_basetype = &result->element_class->byval_arg; + mono_class_setup_supertypes (result); + g_hash_table_insert (ptr_hash, sig, result); + mono_loader_unlock (); + return result; } @@ -1472,65 +1888,58 @@ mono_class_from_mono_type (MonoType *type) { switch (type->type) { case MONO_TYPE_OBJECT: - return mono_defaults.object_class; + return type->data.klass? type->data.klass: mono_defaults.object_class; case MONO_TYPE_VOID: - return mono_defaults.void_class; + return type->data.klass? type->data.klass: mono_defaults.void_class; case MONO_TYPE_BOOLEAN: - return mono_defaults.boolean_class; + return type->data.klass? type->data.klass: mono_defaults.boolean_class; case MONO_TYPE_CHAR: - return mono_defaults.char_class; + return type->data.klass? type->data.klass: mono_defaults.char_class; case MONO_TYPE_I1: - return mono_defaults.sbyte_class; + return type->data.klass? type->data.klass: mono_defaults.sbyte_class; case MONO_TYPE_U1: - return mono_defaults.byte_class; + return type->data.klass? type->data.klass: mono_defaults.byte_class; case MONO_TYPE_I2: - return mono_defaults.int16_class; + return type->data.klass? type->data.klass: mono_defaults.int16_class; case MONO_TYPE_U2: - return mono_defaults.uint16_class; + return type->data.klass? type->data.klass: mono_defaults.uint16_class; case MONO_TYPE_I4: - return mono_defaults.int32_class; + return type->data.klass? type->data.klass: mono_defaults.int32_class; case MONO_TYPE_U4: - return mono_defaults.uint32_class; + return type->data.klass? type->data.klass: mono_defaults.uint32_class; case MONO_TYPE_I: - return mono_defaults.int_class; + return type->data.klass? type->data.klass: mono_defaults.int_class; case MONO_TYPE_U: - return mono_defaults.uint_class; + return type->data.klass? type->data.klass: mono_defaults.uint_class; case MONO_TYPE_I8: - return mono_defaults.int64_class; + return type->data.klass? type->data.klass: mono_defaults.int64_class; case MONO_TYPE_U8: - return mono_defaults.uint64_class; + return type->data.klass? type->data.klass: mono_defaults.uint64_class; case MONO_TYPE_R4: - return mono_defaults.single_class; + return type->data.klass? type->data.klass: mono_defaults.single_class; case MONO_TYPE_R8: - return mono_defaults.double_class; + return type->data.klass? type->data.klass: mono_defaults.double_class; case MONO_TYPE_STRING: - return mono_defaults.string_class; + return type->data.klass? type->data.klass: mono_defaults.string_class; case MONO_TYPE_TYPEDBYREF: - return mono_defaults.typed_reference_class; + return type->data.klass? type->data.klass: mono_defaults.typed_reference_class; case MONO_TYPE_ARRAY: - return mono_array_class_get (type->data.array->type, type->data.array->rank); + return mono_array_class_get (type->data.array->eklass, type->data.array->rank); case MONO_TYPE_PTR: return mono_ptr_class_get (type->data.type); case MONO_TYPE_FNPTR: return mono_fnptr_class_get (type->data.method); case MONO_TYPE_SZARRAY: - return mono_array_class_get (type->data.type, 1); + return mono_array_class_get (type->data.klass, 1); case MONO_TYPE_CLASS: case MONO_TYPE_VALUETYPE: return type->data.klass; - case MONO_TYPE_GENERICINST: - g_warning ("mono_class_from_type: implement me MONO_TYPE_GENERICINST"); - g_assert_not_reached (); - + return mono_class_from_generic (type, TRUE); case MONO_TYPE_VAR: - g_warning ("mono_class_from_type: implement me MONO_TYPE_VAR"); - g_assert_not_reached (); - + return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE); case MONO_TYPE_MVAR: - g_warning ("mono_class_from_type: implement me MONO_TYPE_MVAR"); - g_assert_not_reached (); - + return my_mono_class_from_generic_parameter (type->data.generic_param, TRUE); default: g_warning ("implement me 0x%02x\n", type->type); g_assert_not_reached (); @@ -1553,10 +1962,10 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec) switch (type->type) { case MONO_TYPE_ARRAY: - class = mono_array_class_get (type->data.array->type, type->data.array->rank); + class = mono_array_class_get (type->data.array->eklass, type->data.array->rank); break; case MONO_TYPE_SZARRAY: - class = mono_array_class_get (type->data.type, 1); + class = mono_array_class_get (type->data.klass, 1); break; case MONO_TYPE_PTR: class = mono_class_from_mono_type (type->data.type); @@ -1567,49 +1976,55 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec) break; } - mono_metadata_free_type (type); - return class; } /** * mono_array_class_get: - * @element_type: element type + * @element_class: element class * @rank: the dimension of the array class * * Returns: a class object describing the array with element type @element_type and * dimension @rank. */ MonoClass * -mono_array_class_get (MonoType *element_type, guint32 rank) +mono_array_class_get (MonoClass *eclass, guint32 rank) { - MonoClass *eclass; MonoImage *image; MonoClass *class; MonoClass *parent = NULL; - GSList *list; - int rnum = 0, nsize; + GSList *list, *rootlist; + int nsize; char *name; + gboolean corlib_type = FALSE; - eclass = mono_class_from_mono_type (element_type); g_assert (rank <= 255); - parent = mono_defaults.array_class; - - if (!parent->inited) - mono_class_init (parent); - image = eclass->image; - if ((list = g_hash_table_lookup (image->array_cache, element_type))) { + mono_loader_lock (); + + if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) { for (; list; list = list->next) { class = list->data; - if (class->rank == rank) + if (class->rank == rank) { + mono_loader_unlock (); return class; + } } } - - class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer)); + + /* for the building corlib use System.Array from it */ + if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) { + parent = mono_class_from_name (image, "System", "Array"); + corlib_type = TRUE; + } else { + parent = mono_defaults.array_class; + if (!parent->inited) + mono_class_init (parent); + } + + class = g_malloc0 (sizeof (MonoClass)); class->image = image; class->name_space = eclass->name_space; @@ -1623,15 +2038,12 @@ mono_array_class_get (MonoType *element_type, guint32 rank) name [nsize + rank + 1] = 0; class->name = name; class->type_token = 0; + /* all arrays are marked serializable and sealed, bug #42779 */ class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | - (eclass->flags & (TYPE_ATTRIBUTE_VISIBILITY_MASK | TYPE_ATTRIBUTE_LAYOUT_MASK | - TYPE_ATTRIBUTE_STRING_FORMAT_MASK)); + (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); class->parent = parent; class->instance_size = mono_class_instance_size (class->parent); class->class_size = 0; - class->vtable_size = parent->vtable_size; - class->parent->subclasses = g_list_prepend (class->parent->subclasses, class); - mono_compute_relative_numbering (mono_defaults.object_class, &rnum); mono_class_setup_supertypes (class); class->rank = rank; @@ -1647,19 +2059,25 @@ mono_array_class_get (MonoType *element_type, guint32 rank) MonoArrayType *at = g_new0 (MonoArrayType, 1); class->byval_arg.type = MONO_TYPE_ARRAY; class->byval_arg.data.array = at; - at->type = &eclass->byval_arg; + at->eklass = eclass; at->rank = rank; /* FIXME: complete.... */ } else { /* FIXME: this is not correct. the lbound could be >0 */ class->byval_arg.type = MONO_TYPE_SZARRAY; - class->byval_arg.data.type = &eclass->byval_arg; + class->byval_arg.data.klass = eclass; } class->this_arg = class->byval_arg; class->this_arg.byref = 1; + if (corlib_type) { + class->inited = 1; + } + + list = g_slist_append (rootlist, class); + g_hash_table_insert (image->array_cache, eclass, list); + + mono_loader_unlock (); - list = g_slist_append (list, class); - g_hash_table_insert (image->array_cache, &class->element_class->byval_arg, list); return class; } @@ -1671,34 +2089,13 @@ mono_array_class_get (MonoType *element_type, guint32 rank) */ gint32 mono_class_instance_size (MonoClass *klass) -{ - +{ if (!klass->size_inited) mono_class_init (klass); return klass->instance_size; } -/** - * mono_class_native_size: - * @klass: a class - * - * Returns: the native size of an object instance (when marshaled - * to unmanaged code) - */ -gint32 -mono_class_native_size (MonoClass *klass, guint32 *align) -{ - - if (!klass->marshal_info) - mono_marshal_load_type_info (klass); - - if (align) - *align = klass->min_align; - - return klass->marshal_info->native_size; -} - /** * mono_class_min_align: * @klass: a class @@ -1707,8 +2104,7 @@ mono_class_native_size (MonoClass *klass, guint32 *align) */ gint32 mono_class_min_align (MonoClass *klass) -{ - +{ if (!klass->size_inited) mono_class_init (klass); @@ -1750,8 +2146,7 @@ mono_class_value_size (MonoClass *klass, guint32 *align) */ gint32 mono_class_data_size (MonoClass *klass) -{ - +{ if (!klass->inited) mono_class_init (klass); @@ -1888,38 +2283,6 @@ mono_class_from_name_case (MonoImage *image, const char* name_space, const char return NULL; } -static MonoImage* -load_file_for_image (MonoImage *image, int fileidx) -{ - char *base_dir, *name; - MonoImage *res; - MonoTableInfo *t = &image->tables [MONO_TABLE_FILE]; - const char *fname; - guint32 fname_id; - - if (fileidx < 1 || fileidx > t->rows) - return NULL; - fname_id = mono_metadata_decode_row_col (t, fileidx - 1, MONO_FILE_NAME); - fname = mono_metadata_string_heap (image, fname_id); - base_dir = g_path_get_dirname (image->name); - name = g_build_filename (base_dir, fname, NULL); - res = mono_image_open (name, NULL); - if (res) { - int i; - t = &res->tables [MONO_TABLE_MODULEREF]; - //g_print ("loaded file %s from %s (%p)\n", name, image->name, image->assembly); - res->assembly = image->assembly; - for (i = 0; i < t->rows; ++i) { - if (res->modules [i] && !res->modules [i]->assembly) - res->modules [i]->assembly = image->assembly; - } - mono_image_load_references (image, NULL); - } - g_free (name); - g_free (base_dir); - return res; -} - static MonoClass* return_nested_in (MonoClass *class, char *nested) { MonoClass *found; @@ -1946,7 +2309,7 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name { GHashTable *nspace_table; MonoImage *loaded_image; - guint32 token; + guint32 token = 0; MonoClass *class; char *nested; char buf [1024]; @@ -1962,36 +2325,39 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name name = buf; } + mono_loader_lock (); + nspace_table = g_hash_table_lookup (image->name_cache, name_space); - - if (!nspace_table || !(token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name)))) { + + if (nspace_table) + token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name)); + + mono_loader_unlock (); + + if (!token) + return NULL; + + if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) { MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE]; guint32 cols [MONO_EXP_TYPE_SIZE]; - int i; - - for (i = 0; i < t->rows; ++i) { - const char *ename, *enspace; - mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE); - ename = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]); - enspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]); - - if (strcmp (name, ename) == 0 && strcmp (name_space, enspace) == 0) { - guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION]; - if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) { - loaded_image = load_file_for_image (image, impl >> IMPLEMENTATION_BITS); - if (!loaded_image) - return NULL; - class = mono_class_from_name (loaded_image, name_space, name); - if (nested) - return return_nested_in (class, nested); - return class; - } else { - g_error ("not yet implemented"); - } - } + guint32 idx, impl; + + idx = mono_metadata_token_index (token); + + mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE); + + impl = cols [MONO_EXP_TYPE_IMPLEMENTATION]; + if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) { + loaded_image = mono_assembly_load_module (image->assembly, impl >> IMPLEMENTATION_BITS); + if (!loaded_image) + return NULL; + class = mono_class_from_name (loaded_image, name_space, name); + if (nested) + return return_nested_in (class, nested); + return class; + } else { + g_error ("not yet implemented"); } - /*g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);*/ - return NULL; } token = MONO_TOKEN_TYPE_DEF | token; @@ -2019,16 +2385,89 @@ mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, return TRUE; } } else { - /* - * klass->baseval is 0 for interfaces - */ - if (klass->baseval && ((klass->baseval - klassc->baseval) <= klassc->diffval)) + if (!(klass->flags & TYPE_ATTRIBUTE_INTERFACE) && mono_class_has_parent (klass, klassc)) return TRUE; } + + /* + * MS.NET thinks interfaces are a subclass of Object, so we think it as + * well. + */ + if (klassc == mono_defaults.object_class) + return TRUE; return FALSE; } +gboolean +mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) +{ + if (!klass->inited) + mono_class_init (klass); + + if (!oklass->inited) + mono_class_init (oklass); + + if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) { + if ((klass->interface_id <= oklass->max_interface_id) && + (oklass->interface_offsets [klass->interface_id] != -1)) + return TRUE; + } else + if (klass->rank) { + MonoClass *eclass, *eoclass; + + if (oklass->rank != klass->rank) + return FALSE; + + eclass = klass->cast_class; + eoclass = oklass->cast_class; + + + /* + * a is b does not imply a[] is b[] when a is a valuetype, and + * b is a reference type. + */ + + if (eoclass->valuetype) { + if ((eclass == mono_defaults.enum_class) || + (eclass == mono_defaults.enum_class->parent) || + (eclass == mono_defaults.object_class)) + return FALSE; + } + + return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class); + } + else + if (klass == mono_defaults.object_class) + return TRUE; + + return mono_class_has_parent (oklass, klass); +} + +/* + * mono_class_needs_cctor_run: + * + * Determines whenever the class has a static constructor and whenever it + * needs to be called when executing CALLER. + */ +gboolean +mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller) +{ + int i; + MonoMethod *method; + + for (i = 0; i < klass->method.count; ++i) { + method = klass->methods [i]; + if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && + (strcmp (".cctor", method->name) == 0)) { + if (caller == method) + return FALSE; + return TRUE; + } + } + return FALSE; +} + /* * Returns the nnumber of bytes an element of type klass * uses when stored into an array. @@ -2059,7 +2498,9 @@ handle_enum: case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: + case MONO_TYPE_VAR: + case MONO_TYPE_MVAR: return sizeof (gpointer); case MONO_TYPE_I8: case MONO_TYPE_U8: @@ -2140,11 +2581,37 @@ mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class) class = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type); mono_class_init (class); if (handle_class) - *handle_class = mono_defaults.fieldhandle_class; + *handle_class = mono_defaults.fieldhandle_class; return mono_class_get_field (class, token); } - case MONO_TOKEN_METHOD_DEF: - case MONO_TOKEN_MEMBER_REF: + case MONO_TOKEN_METHOD_DEF: { + MonoMethod *meth; + meth = mono_get_method (image, token, NULL); + if (handle_class) + *handle_class = mono_defaults.methodhandle_class; + return meth; + } + case MONO_TOKEN_MEMBER_REF: { + guint32 cols [MONO_MEMBERREF_SIZE]; + const char *sig; + mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE); + sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]); + mono_metadata_decode_blob_size (sig, &sig); + if (*sig == 0x6) { /* it's a field */ + MonoClass *klass; + MonoClassField *field; + field = mono_field_from_token (image, token, &klass); + if (handle_class) + *handle_class = mono_defaults.fieldhandle_class; + return field; + } else { + MonoMethod *meth; + meth = mono_get_method (image, token, NULL); + if (handle_class) + *handle_class = mono_defaults.methodhandle_class; + return meth; + } + } default: g_warning ("Unknown token 0x%08x in ldtoken", token); break; @@ -2169,3 +2636,6 @@ mono_lookup_dynamic_token (MonoImage *image, guint32 token) { return lookup_dynamic (image, token); } + + +