X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fclass.c;h=6b8d75728face562a7abdf015799acb7d0a052bf;hb=88e4fcdd9a3a68aaacccbacd45522bbea4eb5e23;hp=541f3af836eebc9a9deeb0b2b2e0b78438553c3d;hpb=b3ab28d2b8261e834dcc7ccc4960c1c078cd9efd;p=mono.git diff --git a/mono/metadata/class.c b/mono/metadata/class.c index 541f3af836e..6b8d75728fa 100644 --- a/mono/metadata/class.c +++ b/mono/metadata/class.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -32,17 +33,6 @@ #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 native code be annotated - * with [StructLayout (LayoutKind.Sequential)] - */ -//#define GC_AWARE_AUTO_LAYOUT - -#define CSIZE(x) (sizeof (x) / 4) - MonoStats mono_stats; gboolean mono_print_vtable = FALSE; @@ -179,26 +169,63 @@ mono_type_get_name (MonoType *type) return g_string_free (result, FALSE); } -static MonoType* -inflate_generic_type (MonoType *type, MonoGenericInst *tgen, MonoGenericInst *mgen) +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; + + 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; + } +} + +MonoType* +mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst, + MonoGenericMethod *gmethod) { switch (type->type) { case MONO_TYPE_MVAR: - if (mgen) - return dup_type (mgen->type_argv [type->data.generic_param->num]); + if (gmethod && gmethod->mtype_argv) + return dup_type (gmethod->mtype_argv [type->data.generic_param->num]); else return type; case MONO_TYPE_VAR: - /*g_print ("inflating var %d to %s\n", type->data.type_param, mono_type_get_name (tgen->type_argv [type->data.type_param]));*/ - return dup_type (tgen->type_argv [type->data.generic_param->num]); + if (ginst) { + 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); + } else + return type; 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 (mgen->type_argv [eclass->byval_arg.data.generic_param->num]); - } else if (eclass->byval_arg.type == MONO_TYPE_VAR) { - nclass = mono_class_from_mono_type (tgen->type_argv [eclass->byval_arg.data.generic_param->num]); + if ((eclass->byval_arg.type == MONO_TYPE_MVAR) && gmethod) { + nclass = mono_class_from_mono_type (gmethod->mtype_argv [eclass->byval_arg.data.generic_param->num]); + } else if ((eclass->byval_arg.type == MONO_TYPE_VAR) && ginst) { + nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]); } else { return type; } @@ -206,6 +233,26 @@ inflate_generic_type (MonoType *type, MonoGenericInst *tgen, MonoGenericInst *mg nt->data.klass = nclass; return nt; } + case MONO_TYPE_GENERICINST: { + MonoGenericInst *oginst = type->data.generic_inst; + MonoGenericInst *nginst; + MonoType *nt; + int i; + + nginst = g_new0 (MonoGenericInst, 1); + *nginst = *oginst; + + nginst->type_argv = g_new0 (MonoType *, oginst->type_argc); + + for (i = 0; i < oginst->type_argc; i++) { + MonoType *t = oginst->type_argv [i]; + nginst->type_argv [i] = mono_class_inflate_generic_type (t, ginst, gmethod); + }; + + nt = dup_type (type); + nt->data.generic_inst = nginst; + return nt; + } default: return type; } @@ -213,25 +260,26 @@ inflate_generic_type (MonoType *type, MonoGenericInst *tgen, MonoGenericInst *mg } static MonoMethodSignature* -inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, MonoGenericInst *tgen, MonoGenericInst *mgen) +inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig, + MonoGenericMethod *gmethod) { MonoMethodSignature *res; int i; res = mono_metadata_signature_alloc (image, sig->param_count); - res->ret = inflate_generic_type (sig->ret, tgen, mgen); - for (i = 0; i < sig->param_count; ++i) { - res->params [i] = inflate_generic_type (sig->params [i], tgen, mgen); - } + res->ret = mono_class_inflate_generic_type (sig->ret, gmethod->generic_inst, gmethod); + for (i = 0; i < sig->param_count; ++i) + res->params [i] = mono_class_inflate_generic_type (sig->params [i], + gmethod->generic_inst, + gmethod); res->hasthis = sig->hasthis; res->explicit_this = sig->explicit_this; res->call_convention = sig->call_convention; res->generic_param_count = sig->generic_param_count; - res->gen_params = sig->gen_params; return res; } static MonoMethodHeader* -inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *tgen, MonoGenericInst *mgen) +inflate_generic_header (MonoMethodHeader *header, MonoGenericMethod *gmethod) { MonoMethodHeader *res; int i; @@ -243,14 +291,17 @@ inflate_generic_header (MonoMethodHeader *header, MonoGenericInst *tgen, MonoGen res->init_locals = header->init_locals; res->num_locals = header->num_locals; res->clauses = header->clauses; - for (i = 0; i < header->num_locals; ++i) { - res->locals [i] = inflate_generic_type (header->locals [i], tgen, mgen); - } + res->gen_params = header->gen_params; + res->gen_method = gmethod; + for (i = 0; i < header->num_locals; ++i) + res->locals [i] = mono_class_inflate_generic_type (header->locals [i], + gmethod->generic_inst, + gmethod); return res; } MonoMethod* -mono_class_inflate_generic_method (MonoMethod *method, MonoGenericInst *tgen, MonoGenericInst *mgen) +mono_class_inflate_generic_method (MonoMethod *method, MonoGenericMethod *gmethod) { MonoMethod *result; if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) { @@ -261,9 +312,12 @@ mono_class_inflate_generic_method (MonoMethod *method, MonoGenericInst *tgen, Mo MonoMethodNormal *nmethod = g_new0 (MonoMethodNormal, 1); *nmethod = *(MonoMethodNormal*)method; result = (MonoMethod*)nmethod; - nmethod->header = inflate_generic_header (((MonoMethodNormal*)method)->header, tgen, mgen); + if (nmethod->header) + nmethod->header = inflate_generic_header (nmethod->header, gmethod); } - result->signature = inflate_generic_signature (method->klass->image, result->signature, tgen, mgen); + result->klass = gmethod->klass; + result->signature = inflate_generic_signature ( + method->klass->image, result->signature, gmethod); return result; } @@ -288,6 +342,7 @@ class_compute_field_layout (MonoClass *class) guint32 rva; guint32 packing_size = 0; gboolean explicit_size; + MonoClassField *field; if (class->size_inited) return; @@ -328,66 +383,56 @@ class_compute_field_layout (MonoClass *class) for (i = 0; i < top; i++){ const char *sig; guint32 cols [MONO_FIELD_SIZE]; - guint32 constant_cols [MONO_CONSTANT_SIZE]; - guint32 cindex; int idx = class->field.first + i; - - mono_metadata_decode_row (t, idx, cols, CSIZE (cols)); + + field = &class->fields [i]; + mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE); /* The name is needed for fieldrefs */ - class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]); + field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]); sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]); mono_metadata_decode_value (sig, &sig); /* FIELD signature == 0x06 */ g_assert (*sig == 0x06); - class->fields [i].type = mono_metadata_parse_field_type ( + field->type = mono_metadata_parse_field_type ( m, cols [MONO_FIELD_FLAGS], sig + 1, &sig); + if (mono_field_is_deleted (field)) + continue; if (class->generic_inst) { - class->fields [i].type = inflate_generic_type (class->fields [i].type, class->generic_inst->data.generic_inst, NULL); - class->fields [i].type->attrs = cols [MONO_FIELD_FLAGS]; + field->type = mono_class_inflate_generic_type (field->type, class->generic_inst, NULL); + field->type->attrs = cols [MONO_FIELD_FLAGS]; } - class->fields [i].parent = class; + field->parent = class; - if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) { - if (class->fields [i].type->byref) { + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { + if (field->type->byref) { blittable = FALSE; } else { - MonoClass *field_class = mono_class_from_mono_type (class->fields [i].type); + MonoClass *field_class = mono_class_from_mono_type (field->type); if (!field_class || !field_class->blittable) blittable = FALSE; } } if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) { - mono_metadata_field_info (m, idx, &class->fields [i].offset, NULL, NULL); - if (class->fields [i].offset == (guint32)-1) - g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, class->fields [i].name); + mono_metadata_field_info (m, idx, &field->offset, NULL, NULL); + if (field->offset == (guint32)-1) + g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, field->name); } if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) { mono_metadata_field_info (m, idx, NULL, &rva, NULL); if (!rva) - g_warning ("field %s in %s should have RVA data, but hasn't", class->fields [i].name, class->name); - class->fields [i].data = mono_cli_rva_map (class->image->image_info, rva); + g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name); + field->data = mono_cli_rva_map (class->image->image_info, rva); } if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) { - class->enum_basetype = class->fields [i].type; + class->enum_basetype = field->type; class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype); blittable = class->element_class->blittable; } - if ((class->fields [i].type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) && - (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) { - cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (class->field.first + i + 1)); - if (!cindex) { - g_warning ("constant for field %s:%s not found", class->name, class->fields [i].name); - continue; - } - mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE); - class->fields [i].def_value = g_new0 (MonoConstant, 1); - class->fields [i].def_value->type = constant_cols [MONO_CONSTANT_TYPE]; - class->fields [i].def_value->value = (gpointer)mono_metadata_blob_heap (class->image, constant_cols [MONO_CONSTANT_VALUE]); - } + /* The def_value of fields is compute lazily during vtable creation */ } if (class == mono_defaults.string_class) @@ -416,6 +461,21 @@ mono_class_layout_fields (MonoClass *class) const int top = class->field.count; guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK; guint32 pass, passes, real_size; + gboolean gc_aware_layout = FALSE; + MonoClassField *field; + + /* + * 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) @@ -425,11 +485,11 @@ 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; @@ -441,13 +501,14 @@ mono_class_layout_fields (MonoClass *class) for (pass = 0; pass < passes; ++pass) { for (i = 0; i < top; i++){ int size, align; + field = &class->fields [i]; - if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) + if (mono_field_is_deleted (field)) + continue; + if (field->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. @@ -455,7 +516,7 @@ mono_class_layout_fields (MonoClass *class) * some internal structures, we store GC_MALLOCed memory * in IntPtr fields... */ - if (MONO_TYPE_IS_POINTER (class->fields [i].type)) { + if (MONO_TYPE_IS_POINTER (field->type)) { if (pass == 1) continue; } else { @@ -463,23 +524,22 @@ mono_class_layout_fields (MonoClass *class) continue; } } -#endif if ((top == 1) && (class->instance_size == sizeof (MonoObject)) && - (strcmp (class->fields [i].name, "$PRIVATE$") == 0)) { + (strcmp (field->name, "$PRIVATE$") == 0)) { /* This field is a hack inserted by MCS to empty structures */ continue; } - size = mono_type_size (class->fields [i].type, &align); + size = mono_type_size (field->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 = real_size; - class->fields [i].offset += align - 1; - class->fields [i].offset &= ~(align - 1); - real_size = class->fields [i].offset + size; + field->offset = real_size; + field->offset += align - 1; + field->offset &= ~(align - 1); + real_size = field->offset + size; } class->instance_size = MAX (real_size, class->instance_size); @@ -494,29 +554,32 @@ mono_class_layout_fields (MonoClass *class) real_size = 0; for (i = 0; i < top; i++) { int size, align; + field = &class->fields [i]; /* * 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) + if (mono_field_is_deleted (field)) + continue; + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; - size = mono_type_size (class->fields [i].type, &align); + size = mono_type_size (field->type, &align); /* - * When we get here, class->fields [i].offset is already set by the + * When we get here, field->offset is already set by the * loader (for either runtime fields or fields loaded from metadata). * The offset is from the start of the object: this works for both * classes and valuetypes. */ - class->fields [i].offset += sizeof (MonoObject); + field->offset += sizeof (MonoObject); /* * Calc max size. */ - real_size = MAX (real_size, size + class->fields [i].offset); + real_size = MAX (real_size, size + field->offset); } class->instance_size = MAX (real_size, class->instance_size); break; @@ -529,15 +592,18 @@ mono_class_layout_fields (MonoClass *class) */ for (i = 0; i < top; i++){ int size, align; + field = &class->fields [i]; - if (!(class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC)) + if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) + continue; + if (mono_field_is_deleted (field)) 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; + size = mono_type_size (field->type, &align); + field->offset = class->class_size; + field->offset += align - 1; + field->offset &= ~(align - 1); + class->class_size = field->offset + size; } } @@ -907,6 +973,20 @@ mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum) if (im->flags & METHOD_ATTRIBUTE_STATIC) continue; g_assert (io + l <= max_vtsize); + + /* + * If one of our parents already implements this interface + * we can inherit the implementation. + */ + if (!(vtable [io + l])) { + MonoClass *parent = class->parent; + + if ((ic->interface_id <= parent->max_interface_id) && + (parent->interface_offsets [ic->interface_id]) && + parent->vtable) + vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l]; + } + if (!(vtable [io + l])) { for (j = 0; j < onum; ++j) { g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, @@ -978,7 +1058,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; } @@ -1397,6 +1477,15 @@ mono_class_setup_parent (MonoClass *class, MonoClass *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; @@ -1521,7 +1610,7 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token) class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1; if (tt->rows > tidx){ - mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next)); + mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE); class->field.last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1; class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1; } else { @@ -1552,7 +1641,7 @@ 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, NULL); + class->gen_params = mono_metadata_load_generic_params (image, class->type_token, &icount); class->num_gen_params = icount; mono_loader_unlock (); @@ -1584,48 +1673,74 @@ get_instantiation_name (const char *name, MonoGenericInst *ginst) return g_string_free (res, FALSE); } -MonoClass* -mono_class_from_generic (MonoType *gtype, gboolean inflate_methods) +static void +mono_class_initialize_generic (MonoGenericInst *ginst, gboolean inflate_methods) { - MonoGenericInst *ginst = gtype->data.generic_inst; - MonoClass *gklass = mono_class_from_mono_type (ginst->generic_type); - MonoClass *class; - MonoImage *image; - - mono_loader_lock (); + MonoClass *klass, *gklass, *pklass; - image = gklass->image; - if ((class = g_hash_table_lookup (image->generics_cache, gtype))) { - mono_loader_unlock (); - return class; - } + if (ginst->initialized || ginst->init_pending) + return; + gklass = mono_class_from_mono_type (ginst->generic_type); 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; + klass = ginst->klass; + klass->name = get_instantiation_name (gklass->name, ginst); - class->generic_inst = gtype; + if (ginst->parent) + pklass = mono_class_from_mono_type (ginst->parent); + else + pklass = gklass->parent; - class->cast_class = class->element_class = class; + mono_class_setup_parent (klass, pklass); + mono_class_setup_mono_type (klass); if (inflate_methods) { int i; - mono_class_setup_parent (class, gklass->parent); - mono_class_setup_mono_type (class); + klass->field = gklass->field; + klass->method = gklass->method; + klass->methods = g_new0 (MonoMethod *, klass->method.count); + + for (i = 0; i < klass->method.count; i++) { + MonoGenericMethod *gmethod = g_new0 (MonoGenericMethod, 1); - 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, NULL); + gmethod->klass = klass; + gmethod->generic_method = gklass->methods [i]; + gmethod->generic_inst = ginst; + + klass->methods [i] = mono_class_inflate_generic_method ( + gklass->methods [i], gmethod); + } } - g_hash_table_insert (image->generics_cache, gtype, class); + ginst->initialized = TRUE; +} + +MonoClass* +mono_class_from_generic (MonoGenericInst *ginst) +{ + MonoClass *class, *gklass, *pklass; + + if (ginst->klass) { + mono_class_initialize_generic (ginst, TRUE); + return ginst->klass; + } + + mono_loader_lock (); + + gklass = mono_class_from_mono_type (ginst->generic_type); + mono_class_init (gklass); + + class = ginst->klass = g_malloc0 (sizeof (MonoClass)); + class->name_space = gklass->name_space; + class->name = get_instantiation_name (gklass->name, ginst); + class->image = gklass->image; + class->flags = gklass->flags; + + class->generic_inst = ginst; + + class->cast_class = class->element_class = class; mono_loader_unlock (); @@ -1654,21 +1769,10 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb 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++) { + 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); @@ -1676,7 +1780,33 @@ mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gb klass->image = image; klass->cast_class = klass->element_class = klass; klass->enum_basetype = &klass->element_class->byval_arg; - klass->flags = TYPE_ATTRIBUTE_INTERFACE; + klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC; + + 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 | TYPE_ATTRIBUTE_PUBLIC; 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; @@ -1811,7 +1941,7 @@ mono_class_from_mono_type (MonoType *type) case MONO_TYPE_TYPEDBYREF: return type->data.klass? type->data.klass: mono_defaults.typed_reference_class; case MONO_TYPE_ARRAY: - return mono_array_class_get (type->data.array->eklass, type->data.array->rank); + return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE); case MONO_TYPE_PTR: return mono_ptr_class_get (type->data.type); case MONO_TYPE_FNPTR: @@ -1822,11 +1952,11 @@ mono_class_from_mono_type (MonoType *type) case MONO_TYPE_VALUETYPE: return type->data.klass; case MONO_TYPE_GENERICINST: - return mono_class_from_generic (type, TRUE); + return mono_class_from_generic (type->data.generic_inst); case MONO_TYPE_VAR: + return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE); case MONO_TYPE_MVAR: - g_assert (type->data.generic_param->pklass); - return type->data.generic_param->pklass; + 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 (); @@ -1857,27 +1987,29 @@ mono_class_create_from_typespec (MonoImage *image, guint32 type_spec) case MONO_TYPE_PTR: class = mono_class_from_mono_type (type->data.type); break; + case MONO_TYPE_GENERICINST: + class = mono_class_from_generic (type->data.generic_inst); + break; default: /* it seems any type can be stored in TypeSpec as well */ class = mono_class_from_mono_type (type); break; } - mono_metadata_free_type (type); - return class; } /** - * mono_array_class_get: + * mono_bounded_array_class_get: * @element_class: element class * @rank: the dimension of the array class + * @bounded: whenever the array has non-zero bounds * * Returns: a class object describing the array with element type @element_type and * dimension @rank. */ MonoClass * -mono_array_class_get (MonoClass *eclass, guint32 rank) +mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded) { MonoImage *image; MonoClass *class; @@ -1889,6 +2021,10 @@ mono_array_class_get (MonoClass *eclass, guint32 rank) g_assert (rank <= 255); + if (rank > 1) + /* bounded only matters for one-dimensional arrays */ + bounded = FALSE; + image = eclass->image; mono_loader_lock (); @@ -1896,7 +2032,7 @@ mono_array_class_get (MonoClass *eclass, guint32 rank) 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) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) { mono_loader_unlock (); return class; } @@ -1904,7 +2040,7 @@ mono_array_class_get (MonoClass *eclass, guint32 rank) } /* for the building corlib use System.Array from it */ - if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "corlib") == 0) { + if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) { parent = mono_class_from_name (image, "System", "Array"); corlib_type = TRUE; } else { @@ -1944,7 +2080,7 @@ mono_array_class_get (MonoClass *eclass, guint32 rank) class->element_class = eclass; - if (rank > 1) { + if ((rank > 1) || bounded) { MonoArrayType *at = g_new0 (MonoArrayType, 1); class->byval_arg.type = MONO_TYPE_ARRAY; class->byval_arg.data.array = at; @@ -1952,7 +2088,6 @@ mono_array_class_get (MonoClass *eclass, guint32 rank) 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.klass = eclass; } @@ -1970,6 +2105,20 @@ mono_array_class_get (MonoClass *eclass, guint32 rank) return class; } +/** + * mono_array_class_get: + * @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 (MonoClass *eclass, guint32 rank) +{ + return mono_bounded_array_class_get (eclass, rank, FALSE); +} + /** * mono_class_instance_size: * @klass: a class @@ -2122,9 +2271,9 @@ mono_class_get_property_from_name (MonoClass *klass, const char *name) MonoClass * mono_class_get (MonoImage *image, guint32 type_token) { - MonoClass *class; + MonoClass *class = NULL; - if (image->assembly->dynamic) + if (image->dynamic) return mono_lookup_dynamic_token (image, type_token); switch (type_token & 0xff000000){ @@ -2172,37 +2321,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; - } - } - g_free (name); - g_free (base_dir); - return res; -} - static MonoClass* return_nested_in (MonoClass *class, char *nested) { MonoClass *found; @@ -2253,35 +2371,31 @@ mono_class_from_name (MonoImage *image, const char* name_space, const char *name token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name)); mono_loader_unlock (); - - if (!token) { + + 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; + guint32 idx, impl; - 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"); - } - } + 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; @@ -2343,6 +2457,10 @@ mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass) if (oklass->rank != klass->rank) return FALSE; + /* vectors vs. one dimensional arrays */ + if (oklass->byval_arg.type != klass->byval_arg.type) + return FALSE; + eclass = klass->cast_class; eoclass = oklass->cast_class; @@ -2457,7 +2575,7 @@ mono_array_element_size (MonoClass *ac) gpointer mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class) { - if (image->assembly->dynamic) { + if (image->dynamic) { gpointer obj = mono_lookup_dynamic_token (image, token); switch (token & 0xff000000) {